ShaderBlocks are objects that can hold large amounts of data and can be sent to Shaders. It is common to use "uniform" variables to send data to shaders, but uniforms are usually limited to a few kilobytes in size. ShaderBlocks are useful for a few reasons:

On systems that support compute shaders, ShaderBlocks can optionally be "writable". A writable ShaderBlock is a little bit slower than a non-writable one, but shaders can modify its contents and it can be much, much larger than a non-writable ShaderBlock.

Constructor a new ShaderBlock.


ShaderBlock:getOffsetGet the byte offset of a variable in the ShaderBlock.
ShaderBlock:readRead a variable from the ShaderBlock.
ShaderBlock:sendUpdate a variable in the ShaderBlock.
ShaderBlock:getShaderCodeGet a GLSL string that defines the ShaderBlock in a Shader.
ShaderBlock:getSizeGet the size of the ShaderBlock.
ShaderBlock:getTypeGet the type of the ShaderBlock.



function lovr.load()
  -- Create a ShaderBlock to store positions for 1000 models
  block ='uniform', {
    modelPositions = { 'mat4', 1000 }
  }, { usage = 'static' })

  -- Write some random transforms to the block
  local transforms = {}
  for i = 1, 1000 do
    transforms[i] = lovr.math.mat4()
    local random, randomNormal = lovr.math.random, lovr.math.randomNormal
    transforms[i]:translate(randomNormal(8), randomNormal(8), randomNormal(8))
    transforms[i]:rotate(random(2 * math.pi), random(), random(), random())
  block:send('modelPositions', transforms)

  -- Create the shader, injecting the shader code for the block
  shader =
    block:getShaderCode('ModelBlock') .. [[
    vec4 lovrMain() {
      return lovrProjection * lovrTransform * modelPositions[gl_InstanceID] * lovrVertex;

  -- Bind the block to the shader
  shader:sendBlock('ModelBlock', block)
  model ='monkey.obj')

-- Draw the model 1000 times, using positions from the shader block
function lovr.draw()
  model:draw(lovr.math.mat4(), 1000)

See also