Intrinsics2 min read

gather

Gathers four texel values from a 2x2 footprint.

Reading Time
2 min
Word Count
190
Sections
12
Try It Live

Test gather in a live shader

Open the playground, start from a visual preset, and wire gather 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 gather function retrieves a single component from four texels in a 2x2 footprint around the sampling location. This is useful for custom filtering operations.

Signature

bwsl
gather :: (texture2D tex, sampler samp, float2 uv, int component) -> float4 {...}

Parameters

ParameterTypeDescription
textexture2DThe texture to sample
sampsamplerSampler state
uvfloat2Texture coordinates
componentintColor component (0=R, 1=G, 2=B, 3=A)

Return Value

Returns a float4 containing the specified component from four texels:

  • .x = bottom-left texel
  • .y = bottom-right texel
  • .z = top-right texel
  • .w = top-left texel

Example

bwsl
pipeline CustomFilter {
fragment {
// Gather red channel from 2x2 footprint
float4 reds = gather(tex, input.uv, 0);
// Custom bilinear interpolation
float2 f = fract(input.uv * textureSize);
float bottom = lerp(reds.x, reds.y, f.x);
float top = lerp(reds.w, reds.z, f.x);
float result = lerp(bottom, top, f.y);
output.color = float4(float3(result), 1.0);
}
}

Common Use Cases

Custom Bilinear Filter

bwsl
// Manual bilinear with custom weights
float4 texels = gather(tex, uv, 0);
float2 uvFraction = fract(uv * texSize);
float filtered = dot(texels, computeWeights(uvFraction));

Edge Detection

bwsl
// Sobel filter using gather
float4 samples = gather(grayTex, uv, 0);
float horizontal = samples.y + samples.z - samples.x - samples.w;
float vertical = samples.z + samples.w - samples.x - samples.y;
float edge = sqrt(horizontal * horizontal + vertical * vertical);

Shadow Map Filtering

bwsl
// Gather depth values for custom PCF
float4 depths = gather(shadowMap, shadowUV, 0);
float4 comparisons = step(fragmentDepth, depths);
float shadow = dot(comparisons, float4(0.25));

Height-Based Operations

bwsl
// Gather heights for normal calculation
float4 heights = gather(heightMap, uv, 0);
float dx = (heights.y + heights.z) - (heights.x + heights.w);
float dy = (heights.z + heights.w) - (heights.x + heights.y);

Depth of Field

bwsl
// Gather for circle of confusion
float4 colors = gather(sceneTex, uv, component);
float4 cocs = gather(cocTex, uv, 0);
// Weighted blend based on CoC

Performance

gather is often more efficient than four separate texture samples when you need values from a 2x2 block, as it uses a single texture fetch.

Texel Order

The returned components follow a counterclockwise order starting from bottom-left: (bottom-left, bottom-right, top-right, top-left).

Compiled Output

When compiled to GLSL:

glsl
textureGather(tex, uv, component)

When compiled to HLSL:

hlsl
tex.GatherRed(sampler, uv)  // or GatherGreen, GatherBlue, GatherAlpha

When compiled to Metal:

metal
tex.gather(sampler, uv, component)

See Also

  • sample - Basic sampling
  • load - Direct texel access