Browse Source

Update shader syntax/guide;

bjorn 9 months ago
parent
commit
49af210cec

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


+ 1 - 1
api/lovr/graphics/Pass/compute.lua

@@ -101,7 +101,7 @@ return {
       function lovr.load()
       function lovr.load()
         shader = lovr.graphics.newShader([[
         shader = lovr.graphics.newShader([[
           layout(local_size_x = 8, local_size_y = 8) in;
           layout(local_size_x = 8, local_size_y = 8) in;
-          layout(set = 0, binding = 0, rgba8) uniform image2D image;
+          layout(rgba8) uniform image2D image;
 
 
           void lovrmain() {
           void lovrmain() {
             ivec2 size = imageSize(image);
             ivec2 size = imageSize(image);

+ 4 - 7
api/lovr/graphics/Pass/send.lua

@@ -86,13 +86,10 @@ return {
   example = [=[
   example = [=[
     function lovr.load()
     function lovr.load()
       shader = lovr.graphics.newShader([[
       shader = lovr.graphics.newShader([[
-        layout(set = 2, binding = 0) uniform sampler mySampler;
-        layout(set = 2, binding = 1) uniform Colors { vec4 colors[256]; };
-        layout(set = 2, binding = 2) uniform texture2D rocks;
-
-        Constants {
-          uint constant;
-        };
+        uniform sampler mySampler;
+        uniform Colors { vec4 colors[256]; };
+        uniform texture2D rocks;
+        uniform uint constant;
 
 
         vec4 lovrmain() {
         vec4 lovrmain() {
           return DefaultPosition;
           return DefaultPosition;

+ 1 - 1
api/lovr/graphics/Sampler/init.lua

@@ -7,7 +7,7 @@ return {
     Each `Pass` has a default sampler that will be used by default, which can be changed using
     Each `Pass` has a default sampler that will be used by default, which can be changed using
     `Pass:setSampler`.  Also, samplers can be declared in shaders using the following syntax:
     `Pass:setSampler`.  Also, samplers can be declared in shaders using the following syntax:
 
 
-        layout(set = 2, binding = X) uniform sampler mySampler;
+        uniform sampler mySampler;
 
 
     A Sampler can be sent to the variable using `Pass:send('mySampler', sampler)`.
     A Sampler can be sent to the variable using `Pass:send('mySampler', sampler)`.
 
 

+ 3 - 3
api/lovr/graphics/Shader/getBufferFormat.lua

@@ -37,7 +37,7 @@ return {
     of a single-field struct with an array in it.  Example:
     of a single-field struct with an array in it.  Example:
 
 
         shader = lovr.graphics.newShader([[
         shader = lovr.graphics.newShader([[
-          layout(set = 0, binding = 0) buffer Numbers {
+          buffer Numbers {
             uint numbers[64];
             uint numbers[64];
           };
           };
 
 
@@ -58,7 +58,7 @@ return {
             float grip;
             float grip;
           };
           };
 
 
-          layout(set = 0, binding = 0) buffer Hand {
+          buffer Hand {
             HandParams params;
             HandParams params;
           };
           };
 
 
@@ -71,7 +71,7 @@ return {
   ]=],
   ]=],
   example = [=[
   example = [=[
     shader = lovr.graphics.newShader([[
     shader = lovr.graphics.newShader([[
-      layout(set = 2, binding = 0) uniform Transforms {
+      uniform Transforms {
         mat4 transforms[32];
         mat4 transforms[32];
       };
       };
 
 

+ 1 - 3
api/lovr/graphics/Shader/hasAttribute.lua

@@ -30,7 +30,7 @@ return {
   example = [=[
   example = [=[
     function lovr.load()
     function lovr.load()
       shader = lovr.graphics.newShader([[
       shader = lovr.graphics.newShader([[
-        layout(location = 7) in uint coolAttribute;
+        in uint coolAttribute;
 
 
         vec4 lovrmain() {
         vec4 lovrmain() {
           return DefaultPosition;
           return DefaultPosition;
@@ -42,8 +42,6 @@ return {
       ]])
       ]])
 
 
       print(shader:hasAttribute('coolAttribute')) --> true
       print(shader:hasAttribute('coolAttribute')) --> true
-      print(shader:hasAttribute(7)) --> true
-      print(shader:hasAttribute(8)) --> false
     end
     end
   ]=]
   ]=]
 }
 }

+ 1 - 1
examples/Effects/Blur/main.lua

@@ -25,7 +25,7 @@ local blurShader = [[
   };
   };
 
 
   // The texture to sample from.
   // The texture to sample from.
-  layout(set = 2, binding = 0) uniform texture2DArray sourceTexture;
+  uniform texture2DArray sourceTexture;
 
 
   // lovr's shader architecture will automatically supply a main(), which will call this lovrmain() function
   // lovr's shader architecture will automatically supply a main(), which will call this lovrmain() function
   vec4 lovrmain() {
   vec4 lovrmain() {

+ 1 - 1
examples/Effects/Cubemap_Generate/main.lua

@@ -118,7 +118,7 @@ function cubemap.load()
 
 
 	-- Create reflection shader
 	-- Create reflection shader
 	cubemap.shader = lovr.graphics.newShader('unlit', [[
 	cubemap.shader = lovr.graphics.newShader('unlit', [[
-		layout(set = 2, binding = 0) uniform textureCube cubemap;
+		uniform textureCube cubemap;
 
 
 		vec4 lovrmain() {
 		vec4 lovrmain() {
 			vec3 V = normalize(CameraPositionWorld - PositionWorld);
 			vec3 V = normalize(CameraPositionWorld - PositionWorld);

+ 3 - 3
examples/Effects/Cubemap_Texturing/main.lua

@@ -12,14 +12,14 @@ function lovr.load()
   })
   })
 
 
   shader = lovr.graphics.newShader([[
   shader = lovr.graphics.newShader([[
-    layout(location = 0) out vec3 pos;
+    out vec3 pos;
     vec4 lovrmain() {
     vec4 lovrmain() {
       pos = VertexPosition.xyz;
       pos = VertexPosition.xyz;
       return DefaultPosition;
       return DefaultPosition;
     }
     }
   ]], [[
   ]], [[
-    layout(set = 2, binding = 0) uniform textureCube cube;
-    layout(location = 0) in vec3 pos;
+    in vec3 pos;
+    uniform textureCube cube;
     vec4 lovrmain() {
     vec4 lovrmain() {
       return getPixel(cube, pos);
       return getPixel(cube, pos);
     }
     }

+ 4 - 6
examples/Environment/Terrain_-_Heightmap/main.lua

@@ -1,7 +1,7 @@
 local shaderCode = {[[
 local shaderCode = {[[
 /* VERTEX shader */
 /* VERTEX shader */
-layout(location = 0) out vec4 fragmentClip;
-layout(set = 2) uniform texture2D heightmap;
+out vec4 fragmentClip;
+uniform texture2D heightmap;
 
 
 vec4 lovrmain() {
 vec4 lovrmain() {
   vec3 position = VertexPosition.xyz;
   vec3 position = VertexPosition.xyz;
@@ -10,11 +10,9 @@ vec4 lovrmain() {
   return fragmentClip;
   return fragmentClip;
 } ]], [[
 } ]], [[
 /* FRAGMENT shader */
 /* FRAGMENT shader */
-layout(location = 0) in vec4 fragmentView;
+vec4 fragmentView;
 
 
-Constants {
-  vec3 fogColor;
-};
+uniform vec3 fogColor;
 
 
 vec4 lovrmain() {
 vec4 lovrmain() {
   float fogAmount = atan(length(fragmentView) * 0.1) * 2.0 / PI;
   float fogAmount = atan(length(fragmentView) * 0.1) * 2.0 / PI;

+ 2 - 2
examples/Lighting/PBR_Materials/main.lua

@@ -11,8 +11,8 @@ function lovr.load()
       return DefaultPosition;
       return DefaultPosition;
     }
     }
   ]], [[
   ]], [[
-    layout(set = 2, binding = 0) uniform textureCube cubemap;
-    layout(set = 2, binding = 1) uniform sphericalHarmonics { vec3 sh[9]; };
+    uniform textureCube cubemap;
+    uniform sphericalHarmonics { vec3 sh[9]; };
 
 
     vec4 lovrmain() {
     vec4 lovrmain() {
       Surface surface;
       Surface surface;

+ 4 - 6
examples/Lighting/Shadows/main.lua

@@ -55,13 +55,11 @@ local function lighting_shader()
   ]]
   ]]
 
 
   local fs = [[
   local fs = [[
-    Constants {
-      vec3 lightPos;
-      mat4 lightSpaceMatrix;
-      bool lightOrthographic;
-    };
+    uniform vec3 lightPos;
+    uniform mat4 lightSpaceMatrix;
+    uniform bool lightOrthographic;
 
 
-    layout(set = 2, binding = 0) uniform texture2D shadowMapTexture;
+    uniform texture2D shadowMapTexture;
 
 
     vec4 diffuseLighting(vec3 lightDir, vec3 normal, float shadow) {
     vec4 diffuseLighting(vec3 lightDir, vec3 normal, float shadow) {
       float diff = max(dot(normal, lightDir), 0.0);
       float diff = max(dot(normal, lightDir), 0.0);

+ 1 - 1
examples/Optimization/Instancing/main.lua

@@ -18,7 +18,7 @@ function lovr.load()
 
 
   -- Make a shader that uses transforms from a buffer
   -- Make a shader that uses transforms from a buffer
   shader = lovr.graphics.newShader([[
   shader = lovr.graphics.newShader([[
-    layout(set = 2, binding = 0) uniform Transforms {
+    uniform Transforms {
       mat4 transforms[500];
       mat4 transforms[500];
     };
     };
 
 

+ 1 - 1
examples/Optimization/Instancing_-_Blob/main.lua

@@ -25,7 +25,7 @@ function lovr.load()
   buffer = lovr.graphics.newBuffer('mat4', transformBlob)
   buffer = lovr.graphics.newBuffer('mat4', transformBlob)
 
 
   shader = lovr.graphics.newShader([[
   shader = lovr.graphics.newShader([[
-    layout(set = 2, binding = 0) uniform TransformBuffer { mat4 transforms[500]; };
+    uniform TransformBuffer { mat4 transforms[500]; };
 
 
     vec4 lovrmain() {
     vec4 lovrmain() {
       return Projection * View * Transform * transforms[InstanceIndex] * VertexPosition;
       return Projection * View * Transform * transforms[InstanceIndex] * VertexPosition;

+ 4 - 6
examples/Optimization/Instancing_-_Compute/main.lua

@@ -33,12 +33,10 @@ function lovr.load()
   computeShader = lovr.graphics.newShader([[
   computeShader = lovr.graphics.newShader([[
     layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in;
     layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in;
 
 
-    layout(set = 0, binding = 0) buffer TransformBuffer { mat4 Transforms[]; };
-    layout(set = 0, binding = 1) buffer OffsetBuffer { mat4 Offsets[]; };
+    buffer TransformBuffer { mat4 Transforms[]; };
+    buffer OffsetBuffer { mat4 Offsets[]; };
 
 
-    Constants {
-      uint monkeyCount;
-    };
+    uniform uint monkeyCount;
 
 
     void lovrmain() {
     void lovrmain() {
       uint i = GlobalThreadID.x;
       uint i = GlobalThreadID.x;
@@ -49,7 +47,7 @@ function lovr.load()
 
 
   -- Create the display shader, injecting the shader code for the block
   -- Create the display shader, injecting the shader code for the block
   shader = lovr.graphics.newShader([[
   shader = lovr.graphics.newShader([[
-    layout(set = 2, binding = 0) buffer TransformBuffer { mat4 Transforms[]; };
+    buffer TransformBuffer { mat4 Transforms[]; };
 
 
     vec4 lovrmain() {
     vec4 lovrmain() {
       return Projection * View * Transforms[InstanceIndex] * Transform * VertexPosition;
       return Projection * View * Transforms[InstanceIndex] * Transform * VertexPosition;

+ 38 - 42
guides/Shaders.md

@@ -98,6 +98,16 @@ the code of one or both of the stages:
 
 
     shader = lovr.graphics.newShader('vertex.glsl', 'unlit')
     shader = lovr.graphics.newShader('vertex.glsl', 'unlit')
 
 
+Finally, for advanced use, `lovr.graphics.newShader` takes a `raw` option that will use raw GLSL
+code without any LÖVR helpers:
+
+    shader = lovr.graphics.newShader([[
+      #version 460
+      void main() {
+        //
+      }
+    ]], { raw = true })
+
 Shader Builtins
 Shader Builtins
 ---
 ---
 
 
@@ -302,7 +312,7 @@ The following built-in variables and macros are available only in fragment shade
     </tr>
     </tr>
     <tr>
     <tr>
       <td><code>Tangent</code></td>
       <td><code>Tangent</code></td>
-      <td>vec3</td>
+      <td>vec4</td>
       <td>The tangent vector of the current pixel, in world space.</td>
       <td>The tangent vector of the current pixel, in world space.</td>
     </tr>
     </tr>
     <tr>
     <tr>
@@ -425,25 +435,21 @@ Shader Inputs
 It's also possible to send values or objects from Lua to a Shader.  There are a few different ways
 It's also possible to send values or objects from Lua to a Shader.  There are a few different ways
 to do this, each with their own tradeoffs (speed, size, ease of use, etc.).
 to do this, each with their own tradeoffs (speed, size, ease of use, etc.).
 
 
-### Constants
+### Uniforms
 
 
-Shaders can declare constants, which can be booleans, numbers, vectors, or matrices.  There is a
-very limited amount of space for constants (usually 128 or 256 bytes, depends on the GPU), but they
-are very easy and inexpensive to update.
+Shaders can declare uniforms, which can be booleans, numbers, vectors, or matrices.  These have a
+constant or "uniform" value for all vertices/pixels that are drawn.  They are easy to use and
+inexpensive to update, but they must be resent every frame and whenever the shader changes.
 
 
-Constants are declared in shader code in a `Constants` block, then individual constants are modified
-from Lua using `Pass:send`:
+Uniforms are declared in shader code with the `uniform` keyword, and can be set with `Pass:send`:
 
 
     function lovr.load()
     function lovr.load()
       shader = lovr.graphics.newShader('unlit', [[
       shader = lovr.graphics.newShader('unlit', [[
-        Constants {
-          vec4 color1;
-          vec4 color2;
-        };
-
-        // Apply a vertical gradient using the 2 colors from the constants:
+        uniform vec4 color1;
+        uniform vec4 color2;
 
 
         vec4 lovrmain() {
         vec4 lovrmain() {
+          // Apply a vertical gradient using the 2 colors from the uniforms:
           return mix(color1, color2, dot(Normal, vec3(0, 1, 0)) * .5 + .5);
           return mix(color1, color2, dot(Normal, vec3(0, 1, 0)) * .5 + .5);
         }
         }
       ]])
       ]])
@@ -451,17 +457,12 @@ from Lua using `Pass:send`:
 
 
     function lovr.draw(pass)
     function lovr.draw(pass)
       pass:setShader(shader)
       pass:setShader(shader)
-
       pass:send('color1', { 1, 0, 1, 1 })
       pass:send('color1', { 1, 0, 1, 1 })
       pass:send('color2', { 0, 1, 1, 1 })
       pass:send('color2', { 0, 1, 1, 1 })
-
       pass:sphere(0, 1.7, -2)
       pass:sphere(0, 1.7, -2)
     end
     end
 
 
-The vertex and fragment stages share the constants block, so they should match or one should be a
-subset of the other.
-
-When the active shader is changed, constants will be preserved.
+When the active shader is changed, uniforms with the same name and type will be preserved.
 
 
 ### Vertex Attributes
 ### Vertex Attributes
 
 
@@ -500,28 +501,22 @@ the following default vertex attributes for shapes and meshes:
     </tr>
     </tr>
     <tr>
     <tr>
       <td>VertexTangent</td>
       <td>VertexTangent</td>
-      <td>vec3</td>
+      <td>vec4</td>
       <td>14</td>
       <td>14</td>
     </tr>
     </tr>
   </tbody>
   </tbody>
 </table>
 </table>
 
 
-Custom vertex attributes can be declared for locations 0 through 9:
+Custom vertex attributes can be declared like this:
 
 
-    layout(location = 3) in vec3 customAttribute;
+    in vec3 customAttribute;
 
 
-The data in a buffer can then be associated with the attribute, either by name:
+The data in a buffer can then be associated with the attribute, by name:
 
 
     vertices = lovr.graphics.newBuffer(vertexCount, {
     vertices = lovr.graphics.newBuffer(vertexCount, {
       { type = 'vec3', name = 'customAttribute' }
       { type = 'vec3', name = 'customAttribute' }
     })
     })
 
 
-Or by location:
-
-    vertices = lovr.graphics.newBuffer(vertexCount, {
-      { type = 'vec3', location = 3 }
-    })
-
 ### Buffers
 ### Buffers
 
 
 Shaders can access data in `Buffer` objects.  Buffers can store large arrays of data from Lua tables
 Shaders can access data in `Buffer` objects.  Buffers can store large arrays of data from Lua tables
@@ -534,22 +529,20 @@ Data in buffers can be accessed in 2 ways:
 
 
 First, the buffer should be declared in the shader.  Here's an example declaring a uniform buffer:
 First, the buffer should be declared in the shader.  Here's an example declaring a uniform buffer:
 
 
-    layout(set = 2, binding = 0) uniform Colors {
+    uniform Colors {
       vec4 colors[100];
       vec4 colors[100];
     };
     };
 
 
 And an example storage buffer:
 And an example storage buffer:
 
 
-    layout(set = 2, binding = 0) buffer Colors {
+    buffer Colors {
       vec4 colors[100];
       vec4 colors[100];
     };
     };
 
 
-The first part declares the set and binding of the variable.  Right now the set should always be 2
-(LÖVR uses set 0 and 1 internally).  The binding is a number that can be used to identify the
-variable.  After that, `uniform` or `buffer` is used to declare which type of buffer it is, followed
-by the name of the variable.  Finally, there is a block declaring the format of the data in the
-buffer, which should match the format used to create the Buffer in Lua (structs can be used if the
-buffer has multiple fields per element).
+First the `uniform` or `buffer` keyword is used to declare which type of buffer it is, followed by
+the name of the variable.  Finally, there is a block declaring the format of the data in the buffer,
+which should match the format used to create the Buffer in Lua (structs can be used if the buffer
+has multiple fields per element).
 
 
 A Buffer can be sent to one of the above variables like this:
 A Buffer can be sent to one of the above variables like this:
 
 
@@ -561,6 +554,9 @@ A Buffer can be sent to one of the above variables like this:
 
 
 The shader can then use the `colors` array to access the data from the `palette` table.
 The shader can then use the `colors` array to access the data from the `palette` table.
 
 
+There is a very handy `Shader:getBufferFormat` method that will return a Buffer format from a
+variable in a shader, so you don't have to duplicate it in the Lua code.
+
 It's possible to bind a subset of a buffer to the shader by passing the range as extra arguments to
 It's possible to bind a subset of a buffer to the shader by passing the range as extra arguments to
 `Pass:send`.
 `Pass:send`.
 
 
@@ -569,19 +565,19 @@ It's possible to bind a subset of a buffer to the shader by passing the range as
 Shaders can also access data from `Texture` objects.  Similar to buffers, textures can be accessed
 Shaders can also access data from `Texture` objects.  Similar to buffers, textures can be accessed
 in 2 ways:
 in 2 ways:
 
 
-- Sampled textures are read-only, and can use `Sampler` objects.
-- Storage textures can be written to using compute shaders.
+- **Sampled** textures are read-only, and can use `Sampler` objects.
+- **Storage** textures can be written to using compute shaders.
 
 
 Sampled textures are declared like this:
 Sampled textures are declared like this:
 
 
-    layout(set = 2, binding = 0) uniform texture2D myTexture;
+    uniform texture2D myTexture;
 
 
 The texture type can be `texture2D`, `textureCube`, `texture2DArray`, or `texture3D` (see
 The texture type can be `texture2D`, `textureCube`, `texture2DArray`, or `texture3D` (see
 `TextureType`).
 `TextureType`).
 
 
 Storage textures are declared like this:
 Storage textures are declared like this:
 
 
-    layout(set = 2, binding = 0) uniform image2D myImage;
+    uniform image2D myImage;
 
 
 A texture can be sent to the shader variable using `Pass:send`.
 A texture can be sent to the shader variable using `Pass:send`.
 
 
@@ -596,7 +592,7 @@ This will sample from the texture using the UV coordinates and the default sampl
 
 
 It's also possible to declare a custom sampler variable and use it to sample textures:
 It's also possible to declare a custom sampler variable and use it to sample textures:
 
 
-    layout(set = 2, binding = 0) uniform sampler mySampler;
+    uniform sampler mySampler;
 
 
     // texture(sampler2D(myTexture, mySampler), UV)
     // texture(sampler2D(myTexture, mySampler), UV)
 
 

+ 6 - 6
showcase/Break/shader.lua

@@ -1,9 +1,9 @@
 return lovr.graphics.newShader([[
 return lovr.graphics.newShader([[
 
 
 // All of these are in view-space.
 // All of these are in view-space.
-layout(location = 0) out vec3 lightDirection; // A vector from the vertex to the light
-layout(location = 1) out vec3 normalDirection;
-layout(location = 2) out vec3 vertexPosition;
+out vec3 lightDirection; // A vector from the vertex to the light
+out vec3 normalDirection;
+out vec3 vertexPosition;
 
 
 const vec3 lightPosition = vec3(0, 10, 3);
 const vec3 lightPosition = vec3(0, 10, 3);
 
 
@@ -18,9 +18,9 @@ vec4 lovrmain() {
   return DefaultPosition;
   return DefaultPosition;
 }
 }
 ]], [[
 ]], [[
-layout(location = 0) in vec3 lightDirection;
-layout(location = 1) in vec3 normalDirection;
-layout(location = 2) in vec3 vertexPosition;
+in vec3 lightDirection;
+in vec3 normalDirection;
+in vec3 vertexPosition;
 
 
 const vec3 cAmbient = vec3(.25);
 const vec3 cAmbient = vec3(.25);
 const vec3 cDiffuse = vec3(1);
 const vec3 cDiffuse = vec3(1);

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