Help with normals in vertex shader


I’m writing a demo as part of an introductory course in OpenGL, and it includes a water surface. I managed to get a decent looking surface by creating a large, flat grid and then displacing its y coordinates with some sine and cosine functions. I calculated the normal for each vertex as the average height of the surrounding vertices. Worked nice, but was slow.

So I put it all into a shader. Everything works fine (and fast), except the normals. Since I only have access to the vertex I’m currently manipulating, I can’t calculate the normal by using the height of the surrounding vertices. The function I use to displace the vertex is too expensive to recalculate four times just to get the normal (it’s 0.30*(2.5 * sin(tfactor + (2*ecPos.x+ecPos.z)*PI/6.0) + 1.5 * sin(tfactor/2.0 + (-ecPos.z)*PI/11.0) -2.4 * cos(tfactor/5.0 + (ecPos.x-ecPos.z)*PI/8.0)) - yuck).

Any advice on how to proceed?

You can calculate the normal analytically.

Let’s call your complicated formula f(x,z).

Calculate the derivatives df/dx and df/dz. With that you get the slope of the tangents in x and z direction.

The normal is a simple cross product of the tangents, that is (1, df/dx, 0) x (0, df/dz, 1). Of course you have to normalize the result.

That’s still roughly three evaluations of f, but you won’t get much lower if you really want to calculate everything in the vertex shader.

One alternative would be to use geometry shaders, but I don’t think this is appropriate for an introductory course :wink:

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.