Search Unity

How to render fragments clipped by the near plane...

Discussion in 'Shaders' started by Cameron_SM, Dec 12, 2011.

  1. Cameron_SM

    Cameron_SM

    Joined:
    Jun 1, 2009
    Posts:
    915
    Very bizarre case, I know, but please bare with me.

    I'm doing some volume rendering. I have it working so that I can simply composite all of the volumes in one go like an image effect via a simple blit/screen-aligned-quad. Works great with convex, non-convex and multiple overlapping volumes. The only issue is I am limited to a global volume density color, no per-object goodness.

    :(

    So I got to thinking, if I could composite the volumes one at a time into the existing scene using shader replacement I could leverage z-testing and per-object mesh data to get unique per-mesh volume densities and colours (unless they overlap, then only the foreground colour will show, but I can work with that). Turns out that works, ~almost~ ...



    Game view on the left, Scene view on the right. Top/Bottom are separate screen grabs.

    The snag I hit here is, because using shader replacment means I'm now rendering actual 3D geometry rather than a screen aligned quad, if the volume mesh is clipped by the near clip plane then obviously it simply doesn't render anything. This makes for ugly holes in the volume and of course destroys the ability for the camera to be "inside" the volume and still render correctly as seen in the image above, looks fine in the top half, multiple overlappying volumes are rendered correctly, then in the bottom half you see what happens as I move the camera into the volume, it clips out and totally destroys the effect.


    :(

    I tried snapping/clamping the vertices of each volume to the nearclip plane in a vertex shader simply with:

    Code (csharp):
    1. o.pos  = mul(UNITY_MATRIX_MVP, v.vertex);
    2. o.pos.z = max(0.0, o.pos.z);
    Which ~kinda~ works when I also mess with o.pos.w, would probably work ok if the mesh was tessellated more, but in cases where the fog volume is a long cylinder mesh with 1 length segment it obviously distorts the mesh and pushes the verts way out of position. Truth is, I get a bit lost when dealing with view/projection spaces.

    I think there should be a way to flatten the vertices of an object to the near-clip plane so that the inside of the volume is still rendered by the fragment shader. I realise this could flatten heaps of vets to the same plane and cover the whole screen in flat ploys even when they're all meant to be behind the camera (like if the camera was in the middle of torus) but really this wouldn't matter as the density for any area behind the near-clip will be zero (and I'm rendering the replace shader with alpha) thus I really only care that I have something/anything to draw with in the fragment shader so I can render any volumes ahead of the camera but I can't get my brain to puzzle it out.

    I also found someone on the Ogre3D forums running into a similar problem some years ago for a different effect, but he didn't seem to discover a solution, or if he did he never posted about it.

    Any suggestions would be super helpful.

    Edit: Or... Is there any way to render to multiple RT's from a single shader?... Edit2: Nope, oh well.
     
    Last edited: Dec 12, 2011
  2. Cameron_SM

    Cameron_SM

    Joined:
    Jun 1, 2009
    Posts:
    915
    Nevermind, found an alternative way to get per-mesh color so I'll just stick with the screen space compositing.