Convert object normal map

Godot Version

Godot 4.6

To start out with restrtsictions; I need to work in Mobile mode only for my specific project and not Compatability. The normal map I got seems to be in object space and I hope to convert it without having to rebake it.

In my Visual Shader, I tried using different vectors for the Tangent, Binormal and Normal inputs shown in the picture below

First problem was that it somehow takes the lighting in the front half of the model and reflects a copy onto the backside in respect to Model space. There is only one sun so this is not desired.

Second problem is that when I play it with an animation and skeleton, the lighting seems to be fixed to when it was in rest pose like a texture instead of real time lighting.

What’s strange is when moving the skeleton/object as a whole such as rotating it, the lighting reacts closer to expected with shadows coming up in the right places

By “convert” you mean “use in a shader”?

Normal, tangent and binormal cannot be constant. You need to calculate binormal and tangent per vertex from the vertex normal. Then project the object space normal onto that basis.

If I use the input node for normals, tangents and binormals, would they be in respect to model space or world space?

I’d be surprised if you needed to change the model’s vertex normals at all. You don’t want to bake the normal map texture but your trying to change it through vertex data? How did you come to this conclusion? How is the normal map not working as you intend?

The normal map I got was in object space. If I don’t do anything at all in the vertex data, this is what it would look like:

That’s why I had to create the 3 vectors in the first picture and plug them in to their repective sockets. However, when I start playing the animation the lighting stays fixed to the surface like it was a flat texture

They are part of the vertex data so they’ll typically be in objects space i.e. they’ll appear in the vertex exactly how they are stored in the vertex buffer. However tangents and binormals may not be present. You need to make sure your mesh data contains them.

I’m not sure if the original mesh had those two. Wouldn’t they be calculated by the UV map?

Also, maybe a workaround would be to reference the mesh’s respective bone transformations such as rotation and use the change to rotate the normals, tangents and binnormals. Though I’m not sure how to do that in the Visual Shader editor

Best to produce them in your modelling app and make sure they are exported. You can also generate them by enabling it in the import options although you’ll have a bit less control over their exact orientation.

The key thing is to construct a per-vertex basis out of those 3 vectors and transform the object space normal by it, all done in the vertex shader.

In Blender, I tried exporting the meshes as an FBX instead of GLTF and enabled export of tangents, but unfortunately it doesn’t seem to have changed anything in Godot. Is there a way to see the normals of the vertices in the viewport?

You can visualize them (or tangents/binormals) as color in the fragment shader.

Well do you construct a TBN matrix in the vertex shader and multiply the object space normal with it?

Also why do you need to use the object space normal map? Simply convert it to tangent space in Blender or some other app that can do it.

I didn’t make the model, I got it online. And it’s not just this one; I had to import hundreds of models that all use object space normal maps and I do not go through every single one of them. If I could make one Visual Shader that I could automatically apply to each model, it would be a lot easier down the road.

I’m not sure exactly how to make the specific TBN matrix needed for this case. Could you help me make one, or would you need to see my file?

You can always automate via batch processing.

Make 3 input nodes, set them to tangent, binormal and normal respectively and plug them into transform compose node.

That said, you may not need to do all this if you don’t assign to Normal Map output. You can instead simply convert the your object space normal map sample to camera space and assign it to Normal output in the fragment shader, completely overriding the vertex normals.

No luck onconverting from object to camera.

However, I think I figured out why there were mirrored reflections on my first pass. In Godot, whenever I imported a texture as a normal map, it would just get rid of the blue channel and leave just red+green. Since this is an object space normal map, this would cause the back half of the mesh to have the same normals in object space as the front half. Right now I’m trying to keep the texture as color first and figure out how to calculate it as a Normal. Right now it looks this:

Gotta figure out how to fix the weird banding/cutoff on its bottom left portion

No luck needed. Post the shader.

Import as a regular texture, not as a normal map.
You’ll also need to decode the sample component value range from (0, 1) to (-1, 1).

So the whole things would require doing the following in the fragment shader:

  • sample the object space texture
  • decode to (-1, 1) range
  • convert from object space to camera space by multiplying with the normalized 3x3 basis of the modelview matrix (assuming there is no non-proportional scaling on the object)
  • assign to Normal

Can you also post the mesh, the normal map and the mockup of the result you’re trying to achieve.

Btw none of those attempts look like what I described two posts ago.

wireframe

object normal map

Should look close to this. See how the lighting on the magnets are reacting properly when spinning

I think this was the TBN method in vertex shader, a lot of other attempts things got mixed in

I meant the actual mesh asset file.

Can’t upload mesh directly on this site. Here’s the link where I got it:

If you plan to have non-proportional scaling on the object, you’ll need to use the inverse transpose of the modelview matrix: