Control Flow & Functions
GLSL ES 1.00 (WebGL 1) restricts loops to constant bounds (for (int i = 0; i < 16; i++)).
10.1 Control flow
GLSL ES 1.00 (WebGL 1) restricts loops to constant bounds (for (int i = 0; i < 16; i++)).
if (d < 0.0) {
col = vec3(1.0, 0.0, 0.0);
} else if (d < 0.5) {
col = vec3(0.0, 1.0, 0.0);
} else {
col = vec3(0.0, 0.0, 1.0);
}
for (int i = 0; i < 8; ++i) {
if (i >= uLightCount) break;
color += shade(uLights[i]);
}
int k = 0;
while (k < 10) { k++; }
do { k--; } while (k > 0);
switch (mode) { // int/uint selector (GLSL 1.30+, ES 3.00+)
case 0: col = vec3(1); break;
case 1:
case 2: col = vec3(0.5); break;
default: col = vec3(0);
}
float t = cond ? 1.0 : 0.0;
discard; // fragment shaders only: drop this fragment
return;10.2 Branching & divergence
GPUs execute invocations in groups (warps/wavefronts). If invocations in a group take different branches, both paths execute (masked) — divergence costs performance. Prefer branch-free math (mix, step, clamp) for simple selections; uniform branches (same for all invocations, e.g., based on a uniform) are cheap.
10.3 Functions
Rules: no recursion; parameters passed by value (copy-in/copy-out for out/inout); functions must be declared before use; entry point is void main().
float square(float x) { return x * x; }
vec3 lambert(vec3 n, vec3 l, vec3 color) {
return color * max(dot(n, l), 0.0);
}
void decompose(in vec4 c, out vec3 rgb, out float alpha) { // out parameters
rgb = c.rgb;
alpha = c.a;
}
float sdCircle(vec2 p, float r); // prototype (declaration before use)
float sdCircle(vec2 p, float r) { return length(p) - r; }
// Overloading by parameter types
float luminance(vec3 c) { return dot(c, vec3(0.2126, 0.7152, 0.0722)); }
float luminance(vec4 c) { return luminance(c.rgb); }