Intrinsics2 min read

sample_cmp

Samples a depth texture with comparison.

Reading Time
2 min
Word Count
225
Sections
11
Try It Live

Test sample_cmp in a live shader

Open the playground, start from a visual preset, and wire sample_cmp into the fragment stage to see how it behaves with real values.

Open Playground

Live Demo Pending

This intrinsic does not yet have a self-contained interactive preview. Compute-only and external-resource intrinsics need a different demo path than the current fragment and 3D showcases.

The sample_cmp function samples a depth/shadow texture and performs a comparison operation, returning a filtered comparison result useful for shadow mapping.

Signature

bwsl
sample_cmp :: (texture2D tex, float2 uv, float compareValue) -> float4 {...}
sample_cmp :: (texture2D tex, sampler samp, float2 uv, float compareValue) -> float4 {...}

Parameters

ParameterTypeDescription
textexture2DDepth texture
sampsamplerOptional explicit comparison sampler state
uvfloat2Texture coordinates
compareValuefloatDepth value to compare against

Return Value

Returns a float4 with the comparison result splatted across the components. The value is in [0, 1]; with filtering enabled, it represents the percentage of samples that pass.

Example

bwsl
pipeline ShadowMapping {
fragment {
// Transform position to shadow map space
float4 shadowCoord = lightMatrix * float4(input.worldPos, 1.0);
shadowCoord.xyz /= shadowCoord.w;
// Transform from [-1,1] to [0,1]
float2 shadowUV = shadowCoord.xy * 0.5 + 0.5;
float compareDepth = shadowCoord.z;
// Sample shadow map with hardware PCF
float shadow = sample_cmp(shadowMap, shadowUV, compareDepth).x;
// Apply shadow
float3 lighting = ambient + diffuse * shadow;
output.color = float4(baseColor * lighting, 1.0);
}
}

Common Use Cases

Basic Shadow Mapping

bwsl
// Hardware-filtered shadow lookup
float shadow = sample_cmp(shadowMap, shadowUV, depth).x;

PCF Shadows

bwsl
// Multi-sample soft shadows
float shadow = 0.0;
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
float2 offset = float2(x, y) * texelSize;
shadow += sample_cmp(shadowMap, uv + offset, depth).x;
}
}
shadow /= 9.0;

Cascaded Shadow Maps

bwsl
// Sample appropriate cascade
float shadow;
if (depth < cascade0End) {
shadow = sample_cmp(resources.shadowMap0, resources.shadowSampler, uv0, depth0).x;
} else if (depth < cascade1End) {
shadow = sample_cmp(resources.shadowMap1, resources.shadowSampler, uv1, depth1).x;
}

Variance Shadow Mapping (VSM)

bwsl
// Compare for VSM filtering
float2 moments = sample(resources.momentMap, resources.shadowSampler, uv).rg;
float p = step(depth, moments.x);
float variance = moments.y - moments.x * moments.x;

Hardware PCF

When the sampler uses linear filtering, sample_cmp performs hardware-accelerated Percentage Closer Filtering (PCF), averaging the comparison results of neighboring texels.

Sampler Setup

The texture must be bound with a comparison sampler configured for depth comparison. The comparison function (less, greater, etc.) is set in the sampler state.

Fragment or Explicit LOD

sample_cmp uses implicit LOD and is fragment-stage oriented. In vertex-style code, use an explicit-LOD sampling path where available.

Compiled Output

When compiled to GLSL:

glsl
texture(shadowSampler, vec3(uv, compareValue))

When compiled to HLSL:

hlsl
tex.SampleCmpLevelZero(shadowSampler, uv, compareValue)

When compiled to Metal:

metal
tex.sample_compare(sampler, uv, compareValue)

When compiled to SPIR-V, BWSL emits comparison sampling with implicit LOD and splats the scalar comparison result to float4.

See Also