select
Conditionally selects between two values.
Test select in a live shader
Open the playground, start from a visual preset, and wire select into the fragment stage to see how it behaves with real values.
Open PlaygroundLive Demo
The select function returns one of two values based on a boolean condition, providing a branchless conditional selection.
Signature
select :: (T falseVal, T trueVal, bool condition) -> T {...}
Where T can be any numeric type including vectors.
Parameters
| Parameter | Type | Description |
|---|---|---|
falseVal | T | Value returned when condition is false |
trueVal | T | Value returned when condition is true |
condition | bool | Selection condition |
Return Value
Returns trueVal if condition is true, otherwise returns falseVal.
Example
pipeline BranchlessShader {
fragment {
float3 normal = normalize(input.normal);
float3 lightDir = normalize(lightPos - input.worldPos);
float NdotL = dot(normal, lightDir);
// Branchless two-sided lighting
float3 effectiveNormal = select(normal, -normal, NdotL < 0.0);
float lighting = abs(NdotL);
output.color = float4(baseColor * lighting, 1.0);
}
}Common Use Cases
Avoiding Branches
// Instead of:
// float result = condition ? valueA : valueB;
// Use:
float result = select(valueB, valueA, condition);Two-Sided Normals
// Flip normal for backfaces
float3 normal = select(surfaceNormal, -surfaceNormal, gl_FrontFacing);Clamping Alternative
// Custom clamping behavior
float clamped = select(x, minVal, x < minVal);
clamped = select(clamped, maxVal, clamped > maxVal);
Safe Division
// Avoid division by zero
float result = select(fallback, a / b, abs(b) > epsilon);
Conditional Blending
// Blend based on mask
float3 color = select(colorA, colorB, mask > 0.5);
Material Selection
// Choose material properties
float roughness = select(roughnessA, roughnessB, materialId == 1);
float metallic = select(metallicA, metallicB, materialId == 1);
Parameter Order
Note the parameter order: select(false_value, true_value, condition). The false value comes first, which differs from the ternary operator condition ? true_value : false_value.
Branchless Execution
select evaluates both values before selecting, making it truly branchless. This can improve performance when both values are cheap to compute and divergence would be expensive.
Both Values Computed
Unlike if/else, both falseVal and trueVal are always computed. Don't use select if one path has expensive side effects or computations that should be skipped.
Compiled Output
When compiled to GLSL:
condition ? trueVal : falseVal
When compiled to HLSL:
condition ? trueVal : falseVal
When compiled to SPIR-V:
Uses OpSelect instruction.
See Also
- step - Step function
- lerp - Linear interpolation
- smoothstep - Smooth interpolation