Creates a new ShaderBlock from a table of variable definitions with their names and types.

shaderBlock = lovr.graphics.newShaderBlock(uniforms, flags)


uniformstableA table where the keys are uniform names and the values are uniform types. Uniform arrays can be specified by supplying a table as the uniform's value containing the type and the array size.
flagstable{}Optional settings.
.usageBufferUsagedynamicHow the data in the block will be updated.
.writablebooleanfalseWhether Shaders can write to the data in the block.


shaderBlockShaderBlockThe new ShaderBlock.


The writable flag can only be true if compute shaders are supported, see lovr.graphics.getFeatures. Writable blocks may be slightly slower than non-writable blocks, but they can also be much, much larger. Non-writable blocks are usually limited to around 16 kilobytes in size, depending on hardware.


Create a ShaderBlock to hold a block of useful shader data.

function lovr.load()
  block = lovr.graphics.newShaderBlock({
    time = 'float',
    lightCount = 'int',
    lightPositions = { 'vec3', 16 },
    lightColors = { 'vec3', 16 },
    objectCount = 'int',
    objectTransforms = { 'mat4', 256 }

  shader = lovr.graphics.newShader(
    block:getShaderCode('Block') .. -- Define the block in the shader
      vec4 position(mat4 projection, mat4 transform, vec4 vertex) {
        // ...use the object transforms from the block
        return projection * transform * vertex;

    block:getShaderCode('Block') ..
      vec4 color(vec4 gColor, sampler2D image, vec2 uv) {
        // ...use the lights from the block
        return gColor * texture(image, uv);

  -- Bind the block to the shader
  shader:sendBlock('Block', block)

-- Update the data in the block every frame
function lovr.update(dt)
  block:send('time', lovr.timer.getTime())
  block:send('lightCount', lightCount)
  block:send('lightPositions', { { x, y, z}, { x, y, z } })
  -- etc.

See also