0
\$\begingroup\$

I want to utilize shaders to not only discard fragments if they are on one side of a predefined plane but also render a contour along the intersection.

My fragment shader currently does something along the lines of:

float dot = dot(world_coordinate, normalize(clipping_normal.xyz)) - clipping_normal.w;
if (dot > 0.0f) 
    discard;

this works but without the desired contour. I tried comparing the dot product against values close to 0.0 but this results in a contour with varying width depending on view etc...

This is what I am trying to achieve. Notice that the white contour/edge of where the plane intersects the sphere is of consistent width:

cross-section

So below is what the result I currently see:

my-result

With the fragment shader:

in vec4 color;
in vec3 world_position; 

out vec4 frag_color;

void main()
{    
    float dist = (dot(clipping_plane.xyz, world_position) - clipping_plane.w) / 
              dot(clipping_plane.xyz, clipping_plane.xyz);

    if(dist >= 0.0f && dist < 0.05f)
        frag_color = vec4(0.0f, 0.0f, 0.0f, 1.0f);
    else if(dist < 0.0f) 
        discard;
    else
        frag_color = ComputePhong(color);
}
\$\endgroup\$
  • \$\begingroup\$ Why not just "if z is close to zNear -> draw contour". The shields do something similar in overwatch when close to any wall, and they look decent \$\endgroup\$ – Bálint Feb 28 at 11:52
  • \$\begingroup\$ Your question isn't clear. In the first image it looks like there is some geometry filled into the gap. In the second image it seems to match the shader fairly well. Can you elaborate on how what you are doing differs from what you want? \$\endgroup\$ – Jay Mar 1 at 0:01
  • \$\begingroup\$ I updated the question with more information. I now use a different calculation to determine whether the position is on the plane (A,B,C,D plane form) but didn't really fix the issue. \$\endgroup\$ – graphics_guy Mar 1 at 9:21
  • 1
    \$\begingroup\$ You can use screenspace partial derivatives to get a more consistent line thickness, but this will only help you in places where the mesh itself is drawn at least as wide as the line. If you're looking at the mesh edge-on, so the drawn polygon is narrower than the line you want to draw, you're out of luck. For cases like that, you'll need to draw the line in a separate pass - either as a post effect, or as its own strip of geometry. \$\endgroup\$ – DMGregory Mar 2 at 1:41
  • \$\begingroup\$ Thank you for a very informative post. I'm not extremely well versed in shader techniques so I wouldn't really know how to go about drawing the line in a separate pass as a post effect (specifically how to store the contour data from the fragment shader for later use). I have for now resorted to using a CPU bound slicing algorithm to generate the contour(s) and am rendering them in a different pass as simple line loops... \$\endgroup\$ – graphics_guy Mar 4 at 10:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.