GLSL Shaders
Cacao Engine shaders must be written in Vulkan GLSL so they can be compiled to SPIR-V. They should only use #version 450 core
or above.
Inputs
Cacao Engine provides vertex input attributes in a specific order. Below is the code for accessing every single one, but feel free to pick and choose what you need.
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoords;
layout(location = 2) in vec3 tangent;
layout(location = 3) in vec3 bitangent;
layout(location = 4) in vec3 normal;
Cacao Engine Data
All GLSL vertex shaders must have the uniform CacaoGlobals
block object, which is how engine information is passed to shaders.
Below is an example of how this should be declared. The order of members is important!
layout(std140,binding=0) uniform CacaoGlobals {
mat4 projection;
mat4 view;
} globals;
Transform Matrix
All shaders must declare the transformation matrix as a push constant. This is done as follows:
layout(push_constant) uniform Transformation {
mat4 transform;
};
Local Object Data
All data for individual objects (material data) must be declared within another uniform block, which must be declared as follows:
layout(std140,binding=1) uniform ObjectData {
//Material data goes here...
} object;
Applying the Matrices
To get the final gl_Position
value, you should write that assignment as follows:
gl_Position = globals.projection * globals.view * transform * vec4(position, 1.0);
Texture Bindings
In Vulkan GLSL, every uniform must have a declared binding
value (as seen above with the uniform blocks). This includes texture samplers. They must have distinct binding values from every other binding, so you can’t have a binding=0
or binding=1
in your fragment shader, as those are already assigned to the CacaoGlobals
and ObjectData
uniform blocks.
Passing Data Between Shader Stages
Any data that is to be passed between shader stages must be declared as follows:
layout(location = 0) out Vertex2Fragment {
vec4 pos;
} V2F;