Browse Source

Start ShaderBlock;

bjorn 7 years ago
parent
commit
4f790f120b

File diff suppressed because it is too large
+ 41 - 1
api/init.lua


+ 4 - 1
api/lovr/graphics/Shader/send.lua

@@ -1,6 +1,6 @@
 return {
 return {
   summary = 'Update a uniform variable in the Shader.',
   summary = 'Update a uniform variable in the Shader.',
-  description = 'Update a uniform variable in the Shader.',
+  description = 'Updates a uniform variable in the Shader.',
   arguments = {
   arguments = {
     {
     {
       name = 'uniform',
       name = 'uniform',
@@ -39,5 +39,8 @@ return {
         shader:send('offset', { .3, .7, 0 })
         shader:send('offset', { .3, .7, 0 })
       end
       end
     ]=]
     ]=]
+  },
+  related = {
+    'Shader:sendBlock'
   }
   }
 }
 }

+ 40 - 0
api/lovr/graphics/Shader/sendBlock.lua

@@ -0,0 +1,40 @@
+return {
+  summary = 'Send a ShaderBlock to a Shader.',
+  description = [[
+    Sends a ShaderBlock to a Shader.  After the block is sent, you can update the data in the block
+    without needing to resend the block.  The block can be sent to multiple shaders and they will
+    all see the same data from the block.
+  ]],
+  arguments = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The name of the block to send to.'
+    },
+    {
+      name = 'block',
+      type = 'ShaderBlock',
+      description = 'The ShaderBlock to associate with the specified block.'
+    },
+    {
+      name = 'access',
+      type = 'UniformAccess',
+      default = 'readwrite',
+      description = 'How the Shader will use this block (used as an optimization hint).'
+    }
+  },
+  returns = {},
+  notes = [[
+    The shader does not need to send it a block.
+
+    Make sure the ShaderBlock's variables line up with the block variables declared in the shader
+    code, otherwise you'll get garbage data in the block.  An easy way to do this is to use
+    `ShaderBlock:getShaderCode` to get a GLSL snippet that is compatible with the block.
+  ]],
+  related = {
+    'Shader:send',
+    'ShaderBlock:getShaderCode',
+    'UniformAccess',
+    'ShaderBlock'
+  }
+}

+ 62 - 0
api/lovr/graphics/ShaderBlock/init.lua

@@ -0,0 +1,62 @@
+return {
+  summary = 'A big ol\' block of data that can be accessed in a Shader.',
+  description = [[
+    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:
+
+    - They can hold a lot more data.
+    - Shaders can modify the data in them, which is really useful for compute shaders.
+    - Setting the data in a ShaderBlock updates the data for all Shaders using the block, so you
+      don't need to go around setting the same uniforms in lots of different shaders.
+
+    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 = 'lovr.graphics.newShaderBlock',
+  example = [=[
+    function lovr.load()
+      -- Create a ShaderBlock to store positions for 1000 models
+      block = lovr.graphics.newShaderBlock({
+        modelPositions = { 'mat4', 1000 }
+      }, { writable = false, usage = 'static' })
+
+      -- Write some random transforms to the block
+      local transforms = {}
+      for i = 1, 1000 do
+        local transform = lovr.math.newTransform()
+
+        local x = lovr.math.randomNormal(10)
+        local y = lovr.math.randomNormal(10)
+        local z = lovr.math.randomNormal(10)
+        transform:translate(x, y, z)
+        local angle = lovr.math.random() * 2 * math.pi
+        local ax, ay, az = lovr.math.random(), lovr.math.random(), lovr.math.random()
+        transform:rotate(angle, ax, ay, az)
+
+        transforms[i] = transform
+      end
+
+      -- Create the shader, injecting the shader code for the block
+      shader = lovr.graphics.newShader(
+        block:getShaderCode('ModelBlock') .. [[
+        vec4 position(mat4 projection, mat4 transform, vec4 vertex) {
+          return projection * lovrTransform * modelPositions[gl_InstanceID] * vertex;
+        }
+      ]])
+
+      -- Bind the block to the shader
+      shader:sendBlock('ModelBlock', block)
+
+      model = lovr.graphics.newModel('monkey.obj')
+    end
+
+    -- Draw the model 1000 times, using positions from the shader block
+    function lovr.draw()
+      lovr.graphics.setShader(shader)
+      model:drawInstanced(1000)
+      lovr.graphics.setShader()
+    end
+  ]=]
+}

Some files were not shown because too many files changed in this diff