User Clip Plane sailing

Posted on September 11, 2010

Hi all!

A little bit of a shorter post this week from me and also a little bit more technical in content.

GL ES 2.0

One of our upcoming projects is going to be (currently at least!) 100% GL ES 2.0 based, I ported our engine over quite a while back but only recently started looking at anything more advanced than vertex colour diffuse * diffuse texture shaders being applied.

It’s been enjoyable working on graphics code again and like we’ve seen working with iPhone and new mobile platforms previously there are a lot of déjà vu moments from early PC/console days (or not so long ago if you’re also working on DS / Wii as we are!).

Clipped!

We’re using a reflection pass in the title and so need to clip along a certain plane (to prevent geometry below the reflection plane from appearing in a ghost like fashion when we render using the reflection texture).

User clip planes aren’t supported GL ES 2.0 so we had to work out which option was nicest to resolve this.

This was something we’d gotten round on an Xbox 1 title by calculating the distance from the current vertex position to the clip plane and then passing that value into the pixel (fragment) shader to be texkill’d (i.e. the pixel wouldn’t be rendered) if the interpolated distance value was less than 0.

Another method I’ve heard of (which would work on hardware without pixel shaders also) was using alpha testing in a similar way by passing the distance from the clip place as a 1D texture coordinate which then looks up into a simple clamped alpha texture, the alpha test in the fixed function hardware would then cull the pixel.

One other method which sprung to mind writing this article but haven’t thought about much (or tried) would be to render the plane into the z-buffer (i.e. with colour / alpha writes disabled) and let the zbuffer clip the rest of the geometry for us. (Apologies if this has a major flaw I’ve not considered yet!)

Oblique

One method I recalled from a Game Programming Gem book but had never used before was Oblique Near-plane clipping which was written by Eric Lengyel and he covers in the following slides from GDC (PPT PDF).

The projection matrix in the rendering pipeline projects your vertices from their camera/view space positions into clip space which are then divided through by w to give normalised device coordinates. Once projected valid geometry will exist between a near and far plane which is defined by the projection, the final primitives rendered are clipped to these planes (and the other side planes of clip space) by the graphics hardware (generally).

The technique takes advantage of this clipping by adjusting the near plane to be the same as a clip plane we specify. This effectively gives us free clipping against our own clip plane – as it’s part of the matrix multiplication already being done!

As described in the GDC slides the far plane has to be adjusted by the algorithm to contain the original view frustum fully and in doing so the z-buffer precision will likely be reduced due to increased distance between the new ‘near’ and far planes.

You can find a GL implementation of a function to transform a GL perspective projection matrix to clip a specified plane here

http://www.terathon.com/code/oblique.html

The code assumes the projection matrix being  modified is a perspective projection, Aras Pranckevičius wrote a post removing Erics optimisation based on that assumption and providing a generic version of the algorithm that will work for orthographic projections just as well.

If you’re working with DirectX it’s worth noting you’ll need to adjust the algorithm to project the z values from 0 – 1 rather than -1 to 1 as with OpenGL, you’ll need to change the the 2.0 divide in Erics to code to a 1.0 and remove the +1 near the bottom of his code to get rid of this mapping.

A couple of other notes from Eric (taken from a thread on the technique)

  • Ensure your clipping plane normal points away from the camera position C. That is, the camera is on the negative side of the plane P. If the dot product (Px,Py,Pz,Pw) * (Cx,Cy,Cz,1) isn’t negative, then negate all four components of your clipping plane.
  • The clip plane should be specified in camera space so you’ll need to transform from whatever space the clip plane is specified in.

Additionally NVIDIA have also a related sample on their site.

Thanks!

Hopefully this technique was new and could be useful to a few people and might encourage further exploration into 3D maths for others, I really recommend the following books

Things we’ve been enjoying this week

Be Sociable, Share!

Tags:

Leave a Reply