Intrinsics2 min read

select

Conditionally selects between two values.

Reading Time
2 min
Word Count
189
Sections
13
Try It Live

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 Playground

Live Demo

The select function returns one of two values based on a boolean condition, providing a branchless conditional selection.

Signature

bwsl
select :: (T falseVal, T trueVal, bool condition) -> T {...}

Where T can be any numeric type including vectors.

Parameters

ParameterTypeDescription
falseValTValue returned when condition is false
trueValTValue returned when condition is true
conditionboolSelection condition

Return Value

Returns trueVal if condition is true, otherwise returns falseVal.

Example

bwsl
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

bwsl
// Instead of:
// float result = condition ? valueA : valueB;
// Use:
float result = select(valueB, valueA, condition);

Two-Sided Normals

bwsl
// Flip normal for backfaces
float3 normal = select(surfaceNormal, -surfaceNormal, gl_FrontFacing);

Clamping Alternative

bwsl
// Custom clamping behavior
float clamped = select(x, minVal, x < minVal);
clamped = select(clamped, maxVal, clamped > maxVal);

Safe Division

bwsl
// Avoid division by zero
float result = select(fallback, a / b, abs(b) > epsilon);

Conditional Blending

bwsl
// Blend based on mask
float3 color = select(colorA, colorB, mask > 0.5);

Material Selection

bwsl
// 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:

glsl
condition ? trueVal : falseVal

When compiled to HLSL:

hlsl
condition ? trueVal : falseVal

When compiled to SPIR-V:

Uses OpSelect instruction.

See Also