I need to generate tangents in the vertex shader for a terrain . I’ve noticed that the tangents do not appear to be pre-calculated the same way for terrains as for standard geometries, and this is causing the normal maps in the terrain to appear drastically dulled down.

I was about to start working on my own implementation of generating tangents based on an article I found, but I am not an expert in this type of math, so I thought it might be a good idea to ask if anyone already has the code to generate tangents in a JME shader before I start.

Thanks Usually the terrain texture is axis-aligned as is the terrain geometry… so calculating tangent vectors is dead-simple.

Do you understand what tangent vectors are for? From my perspective, if one understands what they are for then the solution becomes nearly obvious.

I’m not quite sure honestly, it seems like they have something to do with putting the normals into world space, but I thought that was already happening with the blending between the worldNormal and the normal map, so I’m somewhat confused why the tangents are also necessary.

I’ve just noticed that without multiplying the terrain’s normal map by the tangents, the terrain material has duller shading and much less intense normal maps. But if I do multiply the terrain’s existent tangents the same way the stock PBR shader does it, then there is inaccurate lighting on parts of the terrain where the tangents contrast.

You should read articles on tangent space until you understand it before just randomly trying things. It will save you tons of time.

But the short answer is that the tangent defines part of the ‘tangent space’ coordinate axes along with the normal vector and binormal vector. You can think of these as x, y, z axis of the coordinate space on some point on the surface of the shape.

Without this, there is no way to know what the ‘normal’ vector data in a normal map means. Which way does normalMap(u,v).x point? Which way does normalMap(u,v).y point? etc… Who knows?!?

The tangent vector defines which way ‘x’ points. The binormal defines which way ‘y’ points. The ‘normal’ vector defines which way ‘z’ points.

From the normal and the tangent, the binormal can always be calculated because it’s always orthogonal to the other two.

In height map terrain, it’s pretty easy to calculate the tangent because it’s always going to be orthogonal to the normal and the z axis, ie: it’s the cross product between the normal and the z-axis. (Or z-axis and normal, I don’t remember the order off the top of my head but it’s easy to figure it out on a napkin.)

Edit: and if when reading that your are thinking “orthogonal what?!?” or “how did we get to cross product?!?” then I highly recommend brushing up on some basic 3D vector stuff before continuing.

3 Likes