measuring distance in fragment shader

Hello,


I'm trying to render circular endcaps to wide lines in a fragment shader, but the calculations are off. I think it is because of the difference in coordinates between the vertex shader and the fragment shader. In my vertex shader I am passing coordinates for two triangles which form a square, and I want this square to be rendered as a circle by the fragment shader. To do this I am passing the center coordinate for the circle in an extra structure argument out from the vertex shadfer, and then measuring the distance to the center in the fragment shader. But it is not working and without debugging printout it's hard to tell why.


My vertex shader output structure is like this:


struct CapVertexOut {

float4 position [[position]];

float4 center;;

float radius;

};


At the time of output from the vertex shader, both position and center are in device normalized coordinates (I hope). The radius is a value measured in screen coordinates (I think). Then my fragment shader input looks like this

fragment float4 cap_fragment(CapVertexOut interpolated [[stage_in]],
                             const device Color&  color [[ buffer(0) ]],
                             const device Uniforms&  uniforms    [[ buffer(1) ]]
                                ) {
    float2 worldPos = float2(interpolated.position.xy);
    float2 worldCenter = float2(interpolated.center.xy);
  
    if (distance(worldPos, worldCenter) > interpolated.radius)
        discard_fragment();
  
    return float4(color.value.x*color.value.w, color.value.y*color.value.w, color.value.z*color.value.w, color.value.w);
  
}



I've tried several variations on this, such as dividing the world and center coordinates by the display size and using the radius as a normalized device coordinate, but so far nothing is working. Sometimes it discards everything and sometimes nothing, depending on my variation. From reading about fragment shaders it seems like I might need to specify that the 'center' coordinate be transformed in the same way as the 'position' coordinate, if I am going to compare them. But how do I do that? I tried adding this to my struct definition of center, because I read that position coordinates had 'center_no_perspective' transformation.

float4 center [[center_no_perspective]];


But I am kind of just flailing around. Anyone know what might be wrong, or have suggestions for documentation which explains the difference between fragment and vertex shader coordinates and how to manage other structure variables like I am using? The Apple Metal docs are a bit too voluminous for me to parse.


Thanks!

Bob

Accepted Reply

Okay answered my own question -- I was not dividing the center coordinate by the w value, which was 8.

Replies

To add some more information to this -- by outputting different colors depending on the coordinate values, I've determined that my worldPos coordinates are ranging between 0 - displaySize*2 in both X and Y. I guess this is due to the retina screen? So I probably need to pass the screen scale factor in as a uniform also?

Those coordinates make sense.

But my center coordinate is strange - it ranges between -8.0 and 8.0 along either axis. Any idea why that might be?

Okay answered my own question -- I was not dividing the center coordinate by the w value, which was 8.