Intrinsics2 min read
sample_grad
Samples a texture using explicit gradients for LOD calculation.
Reading Time
2 min
Word Count
193
Sections
12
Try It Live
Test sample_grad in a live shader
Open the playground, start from a visual preset, and wire sample_grad into the fragment stage to see how it behaves with real values.
Open PlaygroundLive Demo
The sample_grad function reads a texture using explicit screen-space gradients to compute the mip level, providing precise control over filtering.
Signature
bwsl
sample_grad :: (texture2D tex, sampler samp, float2 uv, float2 ddx, float2 ddy) -> float4 {...}
sample_grad :: (textureCube tex, sampler samp, float3 dir, float3 ddx, float3 ddy) -> float4 {...}
Parameters
| Parameter | Type | Description |
|---|---|---|
tex | texture* | The texture to sample |
samp | sampler | Sampler state |
uv | float2 | Texture coordinates |
ddx | float2/3 | Rate of change in screen-space x |
ddy | float2/3 | Rate of change in screen-space y |
Return Value
Returns the filtered texel value with LOD computed from the gradients.
Example
bwsl
pipeline ParallaxMapping {
@fragment_only
fragment {
// Calculate base UV derivatives before parallax offset
float2 baseDx = ddx(input.uv);
float2 baseDy = ddy(input.uv);
// Apply parallax offset
float2 parallaxUV = input.uv + parallaxOffset;
// Sample with original derivatives to prevent mip artifacts
float4 color = sample_grad(albedoTex, parallaxUV, baseDx, baseDy);
output.color = color;
}
}Common Use Cases
Parallax Mapping
bwsl
// Prevent gradient discontinuities at parallax edges
float2 dx = ddx(uv);
float2 dy = ddy(uv);
float2 offsetUV = parallaxOcclusionMap(uv, viewDir);
float4 albedo = sample_grad(albedoTex, offsetUV, dx, dy);Triplanar Mapping
bwsl
// Consistent LOD across projection planes
float2 dxXY = ddx(worldPos.xy);
float2 dyXY = ddy(worldPos.xy);
float4 projXY = sample_grad(tex, worldPos.xy, dxXY, dyXY);Flow Maps
bwsl
// Smooth flow animation without mip popping
float2 flowUV1 = uv + flow * time;
float2 flowUV2 = uv + flow * (time + 0.5);
float2 dx = ddx(uv);
float2 dy = ddy(uv);
float4 sample1 = sample_grad(tex, flowUV1, dx, dy);
float4 sample2 = sample_grad(tex, flowUV2, dx, dy);UV Distortion Effects
bwsl
// Sample distorted UVs with original gradients
float2 distortedUV = uv + distortion;
float2 originalDx = ddx(uv);
float2 originalDy = ddy(uv);
float4 color = sample_grad(tex, distortedUV, originalDx, originalDy);Anisotropic Manual Control
bwsl
// Custom anisotropic filtering direction
float2 majorAxis = normalize(flowDirection) * anisotropy;
float4 result = sample_grad(tex, uv, majorAxis, float2(0.0, 1.0));Gradient Continuity
The primary use of sample_grad is to maintain correct filtering when UV coordinates have been modified (parallax, distortion) but you want mip selection based on the original surface coverage.
When to Use
Use sample_grad when:
- Applying UV offsets that shouldn't affect mip level
- Implementing parallax/relief mapping
- Flow map animations
- Any UV manipulation that could cause gradient discontinuities
Compiled Output
When compiled to GLSL:
glsl
textureGrad(tex, uv, ddx, ddy)
When compiled to HLSL:
hlsl
tex.SampleGrad(samplerState, uv, ddx, ddy)
See Also
- sample - Basic sampling
- sample_lod - Explicit LOD
- ddx - X derivative
- ddy - Y derivative