Implementing Vertex and Fragment Shaders with CG in Unity
Vertex and Fragment Shader Structure
Unity shaders using the CG language follow a specific structure with vertex and fragment programs:
Shader "Custom/VertexFragmentExample" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vertexProgram
#pragma fragment fragmentProgram
// Structure for vertex to fragment data transfer
struct VertexOutput {
float4 clipPosition : SV_POSITION;
float4 vertexColor : COLOR;
};
VertexOutput vertexProgram(float2 meshPosition : POSITION) {
VertexOutput outputData;
outputData.clipPosition = float4(meshPosition, 0, 1);
outputData.vertexColor = outputData.clipPosition;
return outputData;
}
float4 fragmentProgram(VertexOutput inputData) : SV_Target {
float red = 1.0;
float green = 0.0;
float blue = 0.0;
float alpha = 1.0;
return float4(red, green, blue, alpha);
}
ENDCG
}
}
}
CG Language Data Types and Operations
CG provides various precision data types optimized for graphics programming:
// Precision types
float highPrecision = 1.0; // 32-bit precision
half mediumPrecision = 0.5; // 16-bit precision
fixed lowPrecision = 0.1; // 8-bit precision (sufficient for colors)
// Vector types
float2 vec2 = float2(1.0, 0.5);
float3 vec3 = float3(1.0, 0.5, 0.2);
float4 vec4 = float4(1.0, 0.5, 0.2, 1.0);
// Swizzling operations
float4 combined = float4(vec2.xy, 0.0, 1.0);
float4 rearranged = float4(vec4.yxzw);
// Matrix declarations
float2x2 matrix2x2 = {1.0, 0.0, 0.0, 1.0};
float3x3 matrix3x3;
float4x4 matrix4x4;
// Array initialization
float colorComponents[4] = {1.0, 0.5, 0.5, 1.0};
Function Declaration and Usage
CG functions require proper declaration order or forward declarations:
// Forward declaration approach
void processColor();
float4 fragmentShader(VertexOutput input) : SV_Target {
processColor();
return input.vertexColor;
}
void processColor() {
// Color processing implementation
}
// Implementation first approach
void initializeData() {
// Data initialization code
}
float4 alternativeFragment(VertexOutput input) : SV_Target {
initializeData();
return input.vertexColor;
}
Parameter Passing and Output Modifiers
Since CG doesn't support references, use out modifiers for parameter output:
void transformPosition(in float2 inputPos, out float4 outputPos) {
outputPos = float4(inputPos, 0, 1);
}
void calculateColor(out float4 resultColor) {
resultColor = float4(1.0, 0.0, 0.0, 1.0);
}
Array Parameters and External Encludes
Array parameters require explicit length specification:
void processArray(float dataArray[4]) {
// Array processing with known length
}
// External file inclusion
#include "UnityCG.cginc"
#include "CustomHelpers.cginc"
Common include file locationns:
- Windows:
UnityInstallPath/Editor/Data/CGIncludes/ - macOS:
UnityInstallPath/Unity.app/Contents/CGIncludes/
Built-in Mathematical Functions
CG provides optimized mathematical fucntions that should be preferred over custom implementations:
// Common math operations
float squared = pow(value, 2.0);
float root = sqrt(value);
float exponential = exp(value);
float logarithm = log(value);
// Trigonometric functions
float sine = sin(angle);
float cosine = cos(angle);
float tangent = tan(angle);
// Vector operations
float magnitude = length(vector);
float3 normalized = normalize(vector);
float dotProduct = dot(vec1, vec2);
float3 crossProduct = cross(vec1, vec2);
// Matrix operations
float4 transformed = mul(matrix, vector);
float4x4 inverted = transpose(matrix);