Convert object normal map

Are you still using Mobile renderer? I copied the shader but not getting the same results

There’s nothing fancy in the shader. It should work with any renderer.

Post the shader and the result. You might have missed something.

Looks fine to me.
Disconnect the metallic parameter and adjust your light direction.

Also try doing it without any animations, use the plain obj mesh until you get the look you want.

The left model is straight from the object file. THe one on the right is the original with animation. I’ve noticed that when I rotated the sun, the reflection spun in the opposite direction. So right from the normal map texture, I VectorDecompose to get the x, then did 1-x before putting it back together VectorCompose in order to get the right lighting direction.

It seems that the skeleton is partially the culprit for most of the faulty lighting. When I disabled it for one mesh, it seems to revert back to a 90 degree rotation. This would be the main cause of the weird normals as this initial object rotation is in the wrong orientation

When I try to rotate it back upwards, it DOES give the right lighting.

Afterwards, I reparented the mesh to the skeleton and it turned like this:

That’s when I found out that the top-most parent bone, in this case “Coil”, actually had an X rotation of -0.7. I reset it to 0 and added a keyframe and voila!

Unfortunately, after connecting the magnet part the lighting is still not taking into account the skeleton animation. The left is simply the object file I rotated, and the right is the original animated mesh during playback.

I believe it’s only calculating the normals from its initial object orientation and retaining it throughout the whole animation

I just noticed when I rotated the object file, the lighting was off. So for the TransformOp node, I switched it from AxB to BxA. There’s still the issue for the animation

Using object space normal maps won’t really work with skeletal animation because altering the normal in the fragment shader will override any normal deformation done by the skeleton in the vertex shader. That’s why tangent space normal maps are the de facto standard. You’ll have to adapt the asset to use tangent space normal map, and convert the map itself to tangent space. This would require building the tangents in a 3d app because your dae file doesn’t contain them. Godot can generate them on import but the generated ones may not be ideal for the asset and you’d still need to convert the normal map using those generated tangents. I think I already mentioned that.

So I tried baking a part of a tangent normal map in Blender, but it kept getting SUPER pixelated. Any tips?

How important is this to you?

Not much. Just mainly trying to see if I can get a good workflow for all the other models. If it’s too tedious, then I’ll take it as is. Even if I can’t use it for animated models, the shader you made is still better for static models than what I came up with initially. Thanks for helping out!

I’d then suggest to find assets that are properly set up for skeletal animation. The vertex normals on that mesh look wonky and producing tangent space normal maps may require manual modeling interventions, especially if you don’t have the hires version of the mesh.

You could make it work without mesh interventions by transforming the object space normal in the fragment shader using skeleton matrices. However Godot’s shader doesn’t expose those matrices (only their weights and indices) so you’ll need to extract them from the skeleton in a script and pass them every frame via a uniform array to the shader. Then do a weighted blend of those matrices and transform the object space normal using the result. This is the only way I can think of to reliably “deform” the normal with this asset setup. It’s a bit tedious though, and adds some per frame cpu cost and several per pixel matrix multiplications cost. May not be worth the effort if you can instead find asset alternatives that are technically properly set up.

Isnt object space the same as world space with the model at the origin with rotation set to zero?

So it would seem you need to compute the world transform of the mesh, then transform the normals into the world space?

Then you need to know whether the object space normals are actually intended to use the mesh normals or not, if they do then you might need to change the basis again from world space into tangent space.

A good trick i have found is from converting the standard material into a shader material. I think there is a setting in the Standard material for object space normals - you should set up that standard material then convert to a shader material and see what the code does in the shader editor. Maybe you could post it on here?

I think object space normal maps look nicer for detail preserving simplification type detail baking, the idea is that the vertex normals and tangent space are ignored.

So its probably a fact that for non animating meshes you do not need to calculate the tangent or the binormal, and the normal is over-written with the map normal.

So the object space normal map may be the normals from a higher level of detail model baked onto a texture and the render just ignores the cruder normal smoothing at the vertices for the lower res model and fakes the geometry of the high res model.

The number space is not compressed so there should be a blue channel, but you might still have normals in the (0,1) range and not the vec3(-1.0, -1.0, --1.0) -vec3(1.0,1.0,1.0) range.

The main problem is how to conform the normals from object space normal map to skeletal deformations. Above I described the way to do it. If you know a simpler way - I’m all ears.

I think the method you mentioned just before my first post - getting the transformation matrix from the gdscript (or c#) then setting that into the shader is correct.

This should work for the particular model because it does not appear to deform from animation in the pictures - the normals are looked up per pixel and then multiplied by the transformation matrix of the part :

vec4 norm_transformed = mat_bone_world * normal;

You need to get matrices of all bones in the skeleton. Then do a weighted average of 4 relevant ones.

The model seems to be just solid parts so the magnets for example only have one bone.

I think various engines in the past used detail preserving simplification on skinned meshes, where as you say, there are multiple bones influences per vertex, however there were problems with the details when the mesh animated and the method probably required corrective shape keys to preserve the shape when the model moved - and in fact they still do.

It doesn’t matter. The system doesn’t make that distinction. In a case like this only one matrix of maximal 4 may have the weight of 1 while other 3 will have 0, but this doesn’t get any special treatment. You need all matrices and then use matrix index/weight buit ins provided by the shader to blend the 4 matrices. You can do some if-ing if you’re sure there’s only one matrix affecting a vertex but I doubt this would make the shader code more performant. Best to just do a weighted average of all 4. It’ll work for any weight distribution.

The other idea is linked here, the explanation in the second post.

Are you supposed to repeat the content in case adobe deletes the post?

The point in this approach is that the NORMAL variable must be in object space and not world space.

Converting the normal map is not the problem per se here. The problem with the asset the OP is using is calculating adequate tangents from a wonky mesh topology, whose hard edges do not correspond to seams in the uv map. It’d require tedious manual mesh interventions which OP is not willing to do.