This tutorial will introduce the basic syntax of ShaderLab using a simple texture rendering shader. Through this basic example, you will learn:
ShaderLab uses a three-level nested structure: Shader → SubShader → Pass
Shader "Tutorial/01-BasicShader" {
SubShader "Default" {
Pass "Forward" {
// Shader code goes here
}
}
}In the Pass, we need to declare the variables used by the shader:
// Engine-built-in variable: MVP transformation matrix
mat4 renderer_MVPMat;
// Custom material properties
vec4 material_BaseColor; // Base color
sampler2D material_BaseTexture; // Texture samplerUse structures to define vertex data and data to be passed:
// Vertex shader input (from mesh)
struct Attributes {
vec4 POSITION; // Vertex position
vec2 TEXCOORD_0; // UV coordinates
};
// Vertex shader output / Fragment shader input
struct Varyings {
vec2 uv; // UV coordinates passed to the fragment shader
};Built-in vertex attributes:
POSITION: Vertex positionTEXCOORD_0: First set of UV coordinatesNORMAL: Vertex normalCOLOR_0: Vertex colorSpecify the entry functions for the vertex and fragment shaders:
VertexShader = vert; // Vertex shader entry point
FragmentShader = frag; // Fragment shader entry pointThe vertex shader is responsible for processing the transformation of each vertex:
Varyings vert(Attributes attr) {
Varyings output;
// MVP transformation: Transform the vertex from model space to clip space
gl_Position = renderer_MVPMat * attr.POSITION;
// Pass the UV coordinates to the fragment shader
output.uv = attr.TEXCOORD_0;
return output;
}Key Points:
gl_Position is a built-in output variable and must be assigned a value.The fragment shader is responsible for calculating the color of each pixel:
void frag(Varyings varying) {
// Sample color from the texture
vec4 texColor = texture2D(material_BaseTexture, varying.uv);
// Multiply with the material base color
vec4 finalColor = texColor * material_BaseColor;
// Output the final color
gl_FragColor = finalColor;
}Key Points:
texture2D() function is used for texture sampling.gl_FragColor is a built-in output variable representing the final pixel color.Texture sampling is a common operation in shaders:
// Declare the texture sampler
sampler2D material_BaseTexture;
// Sample in the fragment shader
vec4 texColor = texture2D(material_BaseTexture, uv);Sampling Parameters:
Let's analyze the complete shader code:
Shader "Tutorial/01-BasicShader" {
SubShader "Default" {
// Pass defines the rendering pipeline, specifying the rendering logic
Pass "Forward" {
// Engine-provided MVP matrix for vertex transformation
mat4 renderer_MVPMat;
// Custom material properties
vec4 material_BaseColor;
sampler2D material_BaseTexture;
// Vertex shader input structure (Attributes)
struct Attributes {
vec4 POSITION; // Vertex position
vec2 TEXCOORD_0; // UV coordinates
};
// Vertex shader output / Fragment shader input structure (Varyings)
struct Varyings {
vec2 uv; // UV coordinates passed to the fragment shader
};
// Specify the shader entry points
VertexShader = vert;
FragmentShader = frag;
// Vertex shader: Handles vertex transformation and data passing
Varyings vert(Attributes attr) {
Varyings output;
// Transform the vertex from model space to clip space
gl_Position = renderer_MVPMat * attr.POSITION;
// Pass the UV coordinates to the fragment shader
output.uv = attr.TEXCOORD_0;
return output;
}
// Fragment shader: Calculates the final color for each pixel
void frag(Varyings varying) {
// Sample color from the texture
vec4 texColor = texture2D(material_BaseTexture, varying.uv);
// Multiply with the base color
vec4 finalColor = texColor * material_BaseColor;
// Output the final color
gl_FragColor = finalColor;
}
}
}
}This shader will:
Go to Playground