Search Unity

How to know if a pixel is above or under a the geometrie?

Discussion in 'Shaders' started by unity3dx, Mar 28, 2013.

  1. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    I have this question for a long time. Let's say you have a plane and you want to display the pixels under the plane in black, and the ones above the plane in white. How I can know in the fragment shader at the time I calculate the color of the pixel, that its position is above or under the geometry?

    If someone found a solution to a similar problem I will be glad to heart about it.

    Or it can be simple as, if the pixel is located in the 3d space <0 I display it in black and in white otherwise.
     
  2. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,356
    This is the sort of thing that the depth buffer is good for. You render your plane first, with ZWrite On. Then you do your other geometry in two passes: one with ZTest LEqual, and the other with ZTest Greater. The former will clip geometry that goes behind the rendered plane, and the latter will clip it when it goes in front or at the same depth as the plane.

    If you don't actually want to draw the plane itself, but just write its depth, you can use a shader with ColorMask 0 to prevent it from drawing to the frame buffer at all.
     
  3. RC-1290

    RC-1290

    Joined:
    Jul 2, 2012
    Posts:
    639
    If you only need to know if a 'pixel' (fragment, actually) is above or below a simple plane in the y direction, you can pass that value as a simple shader property, and compare it with the worldPos.
     
  4. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    Daniel Brauer@: Interesting idea, but I need to have the Y coordinates, it is about water. I want to darker under the water, and maybe shade under the water depending on the Camera/Geometrie orientation... not something easy to do!

    rc-1290@: I see what you mean, but if I pass the Y threshold from C# or JS, how do I know in the Fragment shader that the current pixel is above or under. I do not have the x,y,z position of the pixel as if it was a raytracer for example... I only have to x/y screen coordinates, the normal, or the vertex x,y,z...

    If I want to have a water separation between the top and the bottom of the water, it has to be pixel by pixel. Now if I use a grid with animated waves, it gets even more complex...

    So I would like to find a way to estimate the Y coordinate for each pixel I draw... it is maybe impossible without Ray Tracing?


     
  5. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    Thanks Meth11, I will make some tests and if I find a solution that works will post the piece of code here.
     
  6. RC-1290

    RC-1290

    Joined:
    Jul 2, 2012
    Posts:
    639
    For a moving water surface you'll need to pass more than one value, so the technique I was talking about won't work, because the height values are different everywhere.

    I briefly used the built-in shadow casting functionality in my watersimulation. It had a pretty interesting effect, but it was a bit odd because I didn't add any underwater lighting, so the effect was too dark, and looked odd at the maximum range of the shadow. Improving the water surface graphics themselves had a bigger impact on the 'prettiness'.
     
  7. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    oK, if I do

    In the vertex shader:

    and in the pixel shader I do

    It is not working of course: here is what I get:

    $water01.jpg

    But what I want is more complex... I want to blur only what is under the water. Like this

    $water2.jpg

    A little bit more tricky... I have to find a smart way to do it because I want it to be fast...
    Any idea?
     
  8. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    Or another idea, is to make the water a cube instead of a plane, and check if I am inside the cube (draw inside the cube black for example)...
     
unityunity