6
\$\begingroup\$

I've got an object in HLSL and I'm using hardware instancing to render multiple copies. But I've come a bit of a cropper when it comes to the vertex normals. Currently I am not using normal mapping (although planning to implement it soon), I'm just putting the normals inside the vertex structure. I can put the world matrix and get it out in HLSL just fine, but I need the inverse transpose if I want the world position of the vertex normal from object space. How can I invert a matrix in HLSL? Or am I going to have to send the matrix and it's inverse in the instance buffer?

Or is this somehing that normal mapping doesn't require?

\$\endgroup\$

3 Answers 3

8
\$\begingroup\$

Or is this somehing that normal mapping doesn't require?

That's right, normal mapping doesn't require this.

In most cases the best way to do normal mapping is to store the normal map normals in tangent space. That is, a normal in the normal map pointing in the same direction as the surface normal is <0,0,1>. (This is why many normal maps are mostly blue, since they are stored in tangent space.)

Instead of transforming every normal in the normal map into world space (as you're about to do), you can just transform the lights and camera into tangent space on the CPU before the draw call. Then no transformation of the normal map normals is needed.

This means that you will do perhaps 2-10 matrix multiplications on the CPU, saving thousands or millions of transformations on the GPU.

See this article for a more in depth explanation of normal mapping and tangent space: http://www.gamasutra.com/view/feature/1515/messing_with_tangent_space.php

\$\endgroup\$
1
  • \$\begingroup\$ I also came to this conclusion- that it would be easier to transform the lighting parameters into object space on the CPU, and then into tangent space on the GPU. After all, the object space is the same for each instance. \$\endgroup\$
    – DeadMG
    Apr 29, 2011 at 15:20
7
\$\begingroup\$

HLSL does not provide a function for invert but it does provide for transpose. So if your matrix is orthogonal you can just use transpose.
Also if you have scaling and is uniform you won't need the inverse transpose matrix. You can just use the world matrix to rotate your normal and then normalize it.
I apologize If I haven't understand your problem correctly.

\$\endgroup\$
3
  • \$\begingroup\$ So basically the only way to achieve this is to not have non-uniform scaling, or to hardware instance both the world matrix and the world inverse transpose. \$\endgroup\$
    – DeadMG
    Apr 25, 2011 at 20:07
  • 4
    \$\begingroup\$ Or to calculate your inverse transpose matrix on the CPU with D3DXMatrixInverse() and send it to the shader \$\endgroup\$
    – mayatrone
    Apr 25, 2011 at 20:09
  • 1
    \$\begingroup\$ Or don't perform any transform on the normal map normal at all, store it in tangent space, and transform the (very few) lights and camera into tangent space instead. \$\endgroup\$
    – Olhovsky
    Apr 27, 2011 at 23:22
5
\$\begingroup\$

Don't - you'll have to do it for each vertex for a regular vertex shader and this is a massive waste of GPU time. Anything complex like this that can be pre-calculated should be pre-calculated.

\$\endgroup\$
2
  • \$\begingroup\$ So I should hardware instance the world matrix and the world inverse transpose? \$\endgroup\$
    – DeadMG
    Apr 27, 2011 at 12:35
  • \$\begingroup\$ @DeadMG: No. See my answer for the typical way to avoid these transforms. \$\endgroup\$
    – Olhovsky
    Apr 27, 2011 at 23:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .