Tetrahedral Mesh Normals Generation

I have a data for a 3D function plot (equally distributed values of f(x, y) in a rectangle). I’ve built a 3d tetrahedral(a.k.a pyramidal) mesh for these values.

Now I have to calculate normals for this mesh, but I want them to be smooth. I came up with 2 approximate algorithms, but both of them produce similar artifacts like this:

(look at the top right part of the plot)

Problem is not vertex normals, but the interpolation used.
With the fixed path, colors with lighting are calculated on vertices, then interpolated between vertices, and that can not capture highlights correctly.
You have to use a shader to interpolate normals and then calculate lighting per pixel.
These tutorials will help :
http://www.lighthouse3d.com/opengl/glsl/index.php?dirlightpix

Oh. Are there any approximate solutions without shaders (not all cards support shaders)? (from what you’ve said, I guess the answer is no, unless I change the mesh, but still…)

Thank you!
I wasted a lot of time trying to come up with a solution to the problem for which the solution does not exist %)

With OpenGL, no there are not unless you heavily subdivide geometry to attenuate this artifact.
Most of current hardware supports shaders and even the oldest ones that support them would be enough to do this.

You can also use lower exponents for specular highligts, it will make interpolation artifacts less noticeable.

But maybe there is something to improve in your algorithm after all.
It looks like the 5th vertice, the one within a quad, gets a wrong normal. How do you calculate its position and normal ?
I would do something like this :

• at regular grid points, z = f(x, y)
• within each quad, add a 5th vertex, lets call it S, z = average of all four neighbors.
• each grid vertex has its normal defined from the average of plane normals from each of the 8 adjacents triangles. Don’t forget to renormalize after average !
• each S vertex has its normal defined from average of 4 adjacent vertex. Don’t forget to renormalize after average !
This is will bring the result as near as possible as the per-fragment lighting. Increase mesh subdivision if needed.

If the S vertex is defined also with z = f(x, y), then its normal should also be average of 4 adjacent triangles. With also renormalization after.

Zbuffer
Yes, what you wrote is exactly the algorithm I had implemented.
I also tried different modifications, but all of them failed.