|
@@ -5529,7 +5529,7 @@ return {
|
|
|
code = "function lovr.load()\n local x, y, z = 0, 1, -2\n local radius = .3\n local points = 40\n\n -- A table to hold the Mesh data\n local vertices = {}\n\n for i = 0, points do\n local angle = i / points * 2 * math.pi\n local vx = x + math.cos(angle)\n local vy = y + math.sin(angle)\n table.insert(vertices, { vx, vy, z })\n end\n\n mesh = lovr.graphics.newMesh(vertices, 'fan')\nend\n\nfunction lovr.draw()\n mesh:draw()\nend"
|
|
|
}
|
|
|
},
|
|
|
- notes = "Each vertex in a Mesh can hold several pieces of data. For example, you might want a vertex to keep track of its position, color, and a weight. Each one of these pieces of information is called a vertex **attribute**. A vertex attribute must have a name, a type, and a size. Here's what the \"position\" attribute would look like as a Lua table:\n\n { 'vPosition', 'float', 3 } -- 3 floats, one for x, y, and z\n\nEvery vertex in a Mesh must have the same set of attributes. We call this set of attributes the **format** of the Mesh, and it's specified as a simple table of attributes. For example, we could represent the format described above as:\n\n {\n { 'vPosition', 'float', 3 },\n { 'vColor', 'byte', 4 },\n { 'vWeight', 'int', 1 }\n }\n\nWhen creating a Mesh, you can give it any format you want, or use the default. The default Mesh format looks like this:\n\n {\n { 'lovrPosition', 'float', 3 },\n { 'lovrNormal', 'float', 3 },\n { 'lovrTexCoord', 'float', 2 }\n }\n\nGreat, so why do we go through the trouble of naming everything in our vertex and saying what type and size it is? The cool part is that we can access this data in a Shader. We can write a vertex Shader that has `in` variables for every vertex attribute in our Mesh:\n\n in vec3 vPosition;\n in vec4 vColor;\n in int vWeight;\n\n vec4 lovrMain() {\n // Here we can access the vPosition, vColor, and vWeight of each vertex in the Mesh!\n }\n\nSpecifying custom vertex data is really powerful and is often used for lighting, animation, and more!\n\nFor more on the different data types available for the attributes, see `AttributeType`.",
|
|
|
+ notes = "Each vertex in a Mesh can hold several pieces of data. For example, you might want a vertex to keep track of its position, color, and a weight. Each one of these pieces of information is called a vertex **attribute**. A vertex attribute must have a name, a type, and a size. Here's what the \"position\" attribute would look like as a Lua table:\n\n { 'vPosition', 'float', 3 } -- 3 floats, one for x, y, and z\n\nEvery vertex in a Mesh must have the same set of attributes. We call this set of attributes the **format** of the Mesh, and it's specified as a simple table of attributes. For example, we could represent the format described above as:\n\n {\n { 'vPosition', 'float', 3 },\n { 'vColor', 'byte', 4 },\n { 'vWeight', 'int', 1 }\n }\n\nWhen creating a Mesh, you can give it any format you want, or use the default. The default Mesh format looks like this:\n\n {\n { 'lovrPosition', 'float', 3 },\n { 'lovrNormal', 'float', 3 },\n { 'lovrTexCoord', 'float', 2 }\n }\n\nGreat, so why do we go through the trouble of naming everything in our vertex and saying what type and size it is? The cool part is that we can access this data in a Shader. We can write a vertex Shader that has `in` variables for every vertex attribute in our Mesh:\n\n in vec3 vPosition;\n in vec4 vColor;\n in int vWeight;\n\n vec4 position(mat4 projection, mat4 transform, vec4 vertex) {\n // Here we can access the vPosition, vColor, and vWeight of each vertex in the Mesh!\n }\n\nSpecifying custom vertex data is really powerful and is often used for lighting, animation, and more!\n\nFor more on the different data types available for the attributes, see `AttributeType`.",
|
|
|
methods = {
|
|
|
{
|
|
|
name = "attachAttributes",
|
|
@@ -7262,7 +7262,7 @@ return {
|
|
|
},
|
|
|
examples = {
|
|
|
{
|
|
|
- code = "function lovr.load()\n -- Create a ShaderBlock to store positions for 1000 models\n block = lovr.graphics.newShaderBlock('uniform', {\n modelPositions = { 'mat4', 1000 }\n }, { usage = 'static' })\n\n -- Write some random transforms to the block\n local transforms = {}\n for i = 1, 1000 do\n transforms[i] = lovr.math.mat4()\n local random, randomNormal = lovr.math.random, lovr.math.randomNormal\n transforms[i]:translate(randomNormal(8), randomNormal(8), randomNormal(8))\n transforms[i]:rotate(random(2 * math.pi), random(), random(), random())\n end\n block:send('modelPositions', transforms)\n\n -- Create the shader, injecting the shader code for the block\n shader = lovr.graphics.newShader(\n block:getShaderCode('ModelBlock') .. [[\n vec4 lovrMain() {\n return lovrProjection * lovrTransform * modelPositions[gl_InstanceID] * lovrVertex;\n }\n ]])\n\n -- Bind the block to the shader\n shader:sendBlock('ModelBlock', block)\n model = lovr.graphics.newModel('monkey.obj')\nend\n\n-- Draw the model 1000 times, using positions from the shader block\nfunction lovr.draw()\n lovr.graphics.setShader(shader)\n model:draw(lovr.math.mat4(), 1000)\n lovr.graphics.setShader()\nend"
|
|
|
+ code = "function lovr.load()\n -- Create a ShaderBlock to store positions for 1000 models\n block = lovr.graphics.newShaderBlock('uniform', {\n modelPositions = { 'mat4', 1000 }\n }, { usage = 'static' })\n\n -- Write some random transforms to the block\n local transforms = {}\n for i = 1, 1000 do\n transforms[i] = lovr.math.mat4()\n local random, randomNormal = lovr.math.random, lovr.math.randomNormal\n transforms[i]:translate(randomNormal(8), randomNormal(8), randomNormal(8))\n transforms[i]:rotate(random(2 * math.pi), random(), random(), random())\n end\n block:send('modelPositions', transforms)\n\n -- Create the shader, injecting the shader code for the block\n shader = lovr.graphics.newShader(\n block:getShaderCode('ModelBlock') .. [[\n vec4 position(mat4 projecion, mat4 transform, vec4 vertex) {\n return projection * transform * modelPositions[gl_InstanceID] * vertex;\n }\n ]])\n\n -- Bind the block to the shader\n shader:sendBlock('ModelBlock', block)\n model = lovr.graphics.newModel('monkey.obj')\nend\n\n-- Draw the model 1000 times, using positions from the shader block\nfunction lovr.draw()\n lovr.graphics.setShader(shader)\n model:draw(lovr.math.mat4(), 1000)\n lovr.graphics.setShader()\nend"
|
|
|
}
|
|
|
},
|
|
|
notes = "- A Shader can use up to 8 ShaderBlocks.\n- ShaderBlocks can not contain textures.\n- Some systems have bugs with `vec3` variables in ShaderBlocks. If you run into strange bugs,\n try switching to a `vec4` for the variable.",
|
|
@@ -11154,7 +11154,7 @@ return {
|
|
|
examples = {
|
|
|
{
|
|
|
description = "Create a ShaderBlock to hold a block of useful shader data.",
|
|
|
- code = "function lovr.load()\n block = lovr.graphics.newShaderBlock('uniform', {\n time = 'float',\n lightCount = 'int',\n lightPositions = { 'vec3', 16 },\n lightColors = { 'vec3', 16 },\n objectCount = 'int',\n objectTransforms = { 'mat4', 256 }\n }, 'uniform')\n\n shader = lovr.graphics.newShader(\n block:getShaderCode('Block') .. -- Define the block in the shader\n [[\n vec4 lovrMain() {\n // ...use the object transforms from the block\n return lovrProjection * lovrTransform * lovrVertex;\n }\n ]],\n\n block:getShaderCode('Block') ..\n [[\n vec4 lovrMain() {\n // ...use the lights from the block\n return lovrGraphicsColor * texture(lovrDiffuseTexture, lovrTexCoord);\n }\n ]]\n )\n\n -- Bind the block to the shader\n shader:sendBlock('Block', block)\nend\n\n-- Update the data in the block every frame\nfunction lovr.update(dt)\n block:send('time', lovr.timer.getTime())\n block:send('lightCount', lightCount)\n block:send('lightPositions', { { x, y, z}, { x, y, z } })\n -- etc.\nend"
|
|
|
+ code = "function lovr.load()\n block = lovr.graphics.newShaderBlock('uniform', {\n time = 'float',\n lightCount = 'int',\n lightPositions = { 'vec3', 16 },\n lightColors = { 'vec3', 16 },\n objectCount = 'int',\n objectTransforms = { 'mat4', 256 }\n }, 'uniform')\n\n shader = lovr.graphics.newShader(\n block:getShaderCode('Block') .. -- Define the block in the shader\n [[\n vec4 position(mat4 projection, mat4 transform, vec4 vertex) {\n // ...use the object transforms from the block\n return projection * transform * vertex;\n }\n ]],\n\n block:getShaderCode('Block') ..\n [[\n vec4 color(vec4 graphicsColor, sampler2D image, vec2 uv) {\n // ...use the lights from the block\n return graphicsColor * texture(lovrDiffuseTexture, lovrTexCoord);\n }\n ]]\n )\n\n -- Bind the block to the shader\n shader:sendBlock('Block', block)\nend\n\n-- Update the data in the block every frame\nfunction lovr.update(dt)\n block:send('time', lovr.timer.getTime())\n block:send('lightCount', lightCount)\n block:send('lightPositions', { { x, y, z}, { x, y, z } })\n -- etc.\nend"
|
|
|
}
|
|
|
},
|
|
|
notes = "`compute` blocks can only be true if compute shaders are supported, see `lovr.graphics.getFeatures`. Compute blocks may be slightly slower than uniform blocks, but they can also be much, much larger. Uniform blocks are usually limited to around 16 kilobytes in size, depending on hardware.",
|
|
@@ -14152,7 +14152,7 @@ return {
|
|
|
module = "lovr.headset",
|
|
|
examples = {
|
|
|
{
|
|
|
- code = "function lovr.load()\n lovr.graphics.setBackgroundColor(1, 1, 1)\n\n shader = lovr.graphics.newShader([[\n vec4 lovrMain() {\n vec4 vertex = lovrVertex;\n\n // Rescale mesh coordinates from (0,1) to (-1,1)\n vertex.xy *= 2.;\n vertex.xy -= 1.;\n\n // Flip the mesh if it's being drawn in the right eye\n if (lovrViewID == 1) {\n vertex.x = -vertex.x;\n }\n\n return vertex;\n }\n ]], [[\n // The fragment shader returns solid black for illustration purposes. It could be transparent.\n vec4 lovrMain() {\n return vec4(0., 0., 0., 1.);\n }\n ]])\n\n mask = lovr.headset.getDisplayMask()\n\n if mask then\n mesh = lovr.graphics.newMesh({ { 'lovrPosition', 'float', 2 } }, mask, 'triangles')\n end\nend\n\nfunction lovr.draw()\n if mask then\n -- Mask out parts of the display that aren't visible to skip rendering those pixels later\n lovr.graphics.setShader(shader)\n mesh:draw()\n lovr.graphics.setShader()\n\n -- Draw a red cube\n lovr.graphics.setColor(0xff0000)\n lovr.graphics.cube('fill', 0, 1.7, -1, .5, lovr.timer.getTime())\n lovr.graphics.setColor(0xffffff)\n else\n lovr.graphics.setColor(0x000000)\n lovr.graphics.print('No mask found.', 0, 1.7, -3, .2)\n lovr.graphics.setColor(0xffffff)\n end\nend"
|
|
|
+ code = "function lovr.load()\n lovr.graphics.setBackgroundColor(1, 1, 1)\n\n shader = lovr.graphics.newShader([[\n vec4 position(mat4 projection, mat4 transform, vec4 vertex) {\n\n // Rescale mesh coordinates from (0,1) to (-1,1)\n vertex.xy *= 2.;\n vertex.xy -= 1.;\n\n // Flip the mesh if it's being drawn in the right eye\n if (lovrViewID == 1) {\n vertex.x = -vertex.x;\n }\n\n return vertex;\n }\n ]], [[\n // The fragment shader returns solid black for illustration purposes. It could be transparent.\n vec4 color(vec4 graphicsColor, sampler2D image, vec2 uv) {\n return vec4(0., 0., 0., 1.);\n }\n ]])\n\n mask = lovr.headset.getDisplayMask()\n\n if mask then\n mesh = lovr.graphics.newMesh({ { 'lovrPosition', 'float', 2 } }, mask, 'triangles')\n end\nend\n\nfunction lovr.draw()\n if mask then\n -- Mask out parts of the display that aren't visible to skip rendering those pixels later\n lovr.graphics.setShader(shader)\n mesh:draw()\n lovr.graphics.setShader()\n\n -- Draw a red cube\n lovr.graphics.setColor(0xff0000)\n lovr.graphics.cube('fill', 0, 1.7, -1, .5, lovr.timer.getTime())\n lovr.graphics.setColor(0xffffff)\n else\n lovr.graphics.setColor(0x000000)\n lovr.graphics.print('No mask found.', 0, 1.7, -3, .2)\n lovr.graphics.setColor(0xffffff)\n end\nend"
|
|
|
}
|
|
|
},
|
|
|
related = {
|