Monday, April 4, 2011

GPU Displacement Mapping

In these days I was studying some texture projection approaches. In order to make things more interesting I tried to combine this technique with Vertex Texture Fetch to achieve something like a geometry deformation effect.

The image below shows the result:

The red area represent the orthogonal texture projection. In the Vertex Shader I just fetch a displacement map to displace the vertices which are inside the projection area.

Considerations
This sample has been wrote in a couple of hours and it suffers from some limitations:
  • Only one projection is available.
  • The projection volume is not in Tangent Space.
  • Normals are not correct after the displacement.
The first point is trivial to solve and I won't discuss it. The second point is not a big challenge as well, the easier solution is to cast a ray and transforms the projection volume according to the intersection results. The last point seems more tricky than the previous ones. In order to get a correct normal after the displacement I need some extra informations in the vertex shader such the normals of the others shared vertices. The goal is to provide these extra informations as input to the vertex shader. Since I'm using DirectX 9, I thought a couple of approaches:
  • To render this technique in a single pass using a second data stream containing the adjacent triangles data. So, for each vertex I can transform and compute the average of the shared normals. The major drawback of this method is efficiency. This approach may fit better in per primitive stage (Geometry Shader) avoiding wasteful repeated computations.
  • To render this technique in two passes, storing in a texture the required vertex data and then gather any required vertex data through texture lookup. This approach avoids per vertex repeated computations but processes the geometry twice.
Another thought I've in mind is simply to use normal mapping. I guess even if the normal is not correct it won't be much noticeable in the result. Of course I have to prove that : )

That's it for now, any suggestions?