Shaders and Materials¶
A special program that runs per vertex/pixel for drawing and compute operations on the GPU
Codea shaders are written in GLSL (GL shading language)
In Codea shaders can be used in various places to customise rendering including meshes, entities, sprites, backgrounds and post processing effects
myShader = shader(vsh, fsh)
myMesh.shader = myShader
myMaterial = material(shader)
myMesh.material = myMaterial
sprite(myShader, x, y, w, h)
background(myShader)
.
WARNING: Shaders live very close to the hardware and are much more likely to cause crashes or graphical corruption when things go wrong, you have been warned ;)
Graphics Pipeline¶
TODO
Vertex Shaders¶
Each vertex within a mesh is passed to the GPU via the vertex processing stage, where various calculations can be performed to control the final appearance
Fragment Shaders¶
After the vertex processing stage, the fragment processing stage begins. Primtives assembled from vertices, such as triangles, are drawn on to the framebuffer in a process known as rasterization.
The fragment shader is able to calculate the final output of this stage (typically the color and/or depth of the fragment)
Compute Shaders¶
Compute shaders bypass the normal rasterisation stage, useful for more general purpose computations
More info: https://www.khronos.org/opengl/wiki/Compute_Shader
myComputeShader = shader.compute
[[
#version 430
#include <codea/common.glsl>
NUM_THREADS(1, 1, 1)
void main()
{
}
]]
Threading Model¶
Workgroups¶
NUM_THREADS(x, y, z)
gl_GlobalInvocationID
Dispatch¶
TODO
Image Properties¶
TODO
Buffers¶
Also known as SSBOs (Shader Storage Buffer Objects)
TODO
Shader Definitions¶
Shader definitions are Lua tables that define all the settings of a shader. These can be used for fine-grained control over shader behaviour
Anatomy of a Shader Definition¶
A shader definition is broken into several parts:
options - enable and disable specific parts of a shader
properties - values passed into the shader (via uniforms)
passes - one ore more passes that contain shader code and settings
NOTE: shaders can either have an array of
passes
or a singlepass
shdr = shader
{
properties =
{
{name, type, value, ...}
},
options =
{
NAME = {default, options}
},
passes =
{
{
vertex =
[[
...
]],
fragment =
[[
...
]]
}
}
}
Properties¶
Each property is a Lua table with the following form:
{<name>, <type>, <value>, ...}
<name>
a string identifier for the property, this should be treated like a lua identifier (starts with an underscore or letter, followed by a sequence of alphanumeric characters and underscores and no spaces or funny symbols)
The property name directly links to a shader uniform in one or more passes
<type>
is a string containing the type of property, corresponding to a GLSL uniform type
Type Name |
GLSL type |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
<value>
is the initial value of the property
Additional property settings are available, such as
color = true
range = {low, high}
onSet = function(...) end
Options¶
Options let you conditionally enable/disable chunks of shader code via the shader macro preprocessor (i.e. #if
and #ifdef
). This is useful when creating optional features and uber shaders where expensive operations can be skipped if not currently in use
<name> = {<default>, ...}
Options can be linked to specific properties or based complex conditions
TODO
Passes¶
TODO
Materials¶
Shaders can be re-used in multiple meshes/entities but will retain their current state globally. Setting properties on a shader in one place will effect rendering on all objects they are attached to
This is where materials come in. Placing a shader within a material isntance and passing that to various objects will allow for the same shader to be used with different state (properties) as many times are needed
The Standard Shader¶
For convenience there is a built-in uber-shader, called the standard shader which contains a large number of shading options
For more details see: material.unlit()
and material.lit()
Surface Shaders¶
Surface shaders provide support for advanced shading models, where only the surface attributes need to be specified
Our shading models are derived from Google’s amazing Filament: https://google.github.io/filament/Materials.html
Surface shaders are created using a shader definition with a shadingModel
set. A vertex and material function can then be spefified to customise the surface appearance
surface = shader
{
pass =
{
shadingModel = "lit",
vertex =
[[
void materialVertex(inout MaterialVertexInputs material)
{
}
]],
material =
[[
void material(inout MaterialInputs material)
{
prepareMaterial(material);
vec2 uv = getUV0();
material.metallic = 1.0;
material.roughness =
mod(floor(uv.x * 20) + floor(uv.y * 10), 2)
* 0.5;
material.baseColor = baseColor;
}
]]
}
}
Shading Models¶
The following shading models are supported:
unlit
Basic unlit shadinglit
Physically based lit shading modelcustom
Custom shading model
MaterialInputs Struct
The material
function can set the various fields within the MaterialInputs
struct to control the shading of the surface
This ranges from diffuse surface color, metal/roughness to normal mapping, ambient occlusion and more
Some are only available in specific lighting models and expect values to be within certain ranges
Name |
Type |
Models |
Description |
---|---|---|---|
|
|
All |
Diffuse albedo color |
|
|
Lit |
The metalness of the surface (zero or one) |
|
|
Lit |
Perceived smoothness (1.0) or roughness (0.0) of a surface |
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
|
|
|
Lit |
Shade Pro Integration¶
TODO