Confusion over [[position]] attribute in fragment shader


I am currently working on getting occlusion working by using the depth map provided by the new iPad Pro in ARKit 4.

I have been going through the code in the chapter on multi pass rendering since it also uses a depth map to create shadows.

The following code has confused me:

float2 xy = in.shadowPosition.xy;
xy = xy * 0.5 + 0.5;
xy.y = 1 - xy.y;

This is often seen in shader code to map values from [-1, 1] to [0, 1]. However, in this instance I am not sure why this works!

I always assumed this position attribute was equivalent to gl_FragCoord and have been using it in the same way.

So to get normalized texture coordinates to sample an image like a depth map I would divide by the screen size:

vec2 st = gl_FragCoord.xy / u_resolution;

Why is in.shadowPosition.xy in the range [-1, 1] rather than [0 - screenSize] ? Is this something to do with using an orthographic projection matrix?

Just realised that shadowPosition is not declared with the [[position]] attribute. So the rasterizer won’t have performed the perspective divide and viewport transform.

So I assume this calculation is actually where we perform the perspective divide and transform the z-coordinate from homogeneous clip space to normalized device coordinates?

float current_sample = in.shadowPosition.z / in.shadowPosition.w;

I had assumed this was used to unproject the vertex…

The part that still confuses me is:

“Determine a coordinate pair from the shadow position that will serve as a screen
space pixel locator on the shadow texture. Then, you normalize the coordinates
from [-1, 1] to [0, 1]. Finally, you reverse the Y coordinate since it’s upside down.”

With this code:

float2 xy = in.shadowPosition.xy;
xy = xy * 0.5 + 0.5;
xy.y = 1 - xy.y;

Since this seems to imply we are going from NDC coordinates to screen space coordinates in the range [0, 1]. Does the rasterizer in fact perform the perspective divide for shadowPosition but not the viewport transform?

I’m not in that headspace at them moment, so I am actually slightly puzzled at that code too :slight_smile:.

Looking at the rendered data, shadowPosition is already in NDC due to the orthographic matrix, and the w is set to 1.0, so no point in dividing by it.

The rasteriser does not perform the perspective divide for shadow position. With orthographic matrices there is generally no perspective divide necessary anyway.

xy acts like uv coordinates which are from 0 to 1, and gets the texture data from the shadow map.

1 Like