Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Tangent-space vectors not updated when texture rotation is in effect #808
When a texture rotation is applied to a model, its tangent-space vectors are not updated. This makes it seem as if the light source is rotated also, or as if the apparent depth is inverted (dents become bumps and vice-versa), depending on how you look at it.
The following code sample should reproduce this:
from panda3d.core import * from direct.showbase.ShowBase import ShowBase class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) self.disable_mouse() self.camera.set_y(-20.) # set up a light source p_light = PointLight("point_light") p_light.set_color((1., 1., 1., 1.)) self.light = self.render.attach_new_node(p_light) self.light.set_pos(50., -30., 30.) self.render.set_light(self.light) self.render.set_shader_auto(True) self.render.set_shader_input("light", self.light) # load a model with tangent-space vectors; it has a normal map (normal_sphere.jpg) # and a color map (Brick_105.jpg) assigned to it self.model = model = self.loader.load_model("Square.bam", noCache=True).get_child(0) tex_attrib = model.get_state().get_attrib(TextureAttrib) self.ts_color = tex_attrib.get_on_stage(0) self.ts_normal = tex_attrib.get_on_stage(1) model.reparent_to(self.render) model.set_h(180.) self.angle = 0. # set up a task to rotate the model textures each frame self.task_mgr.add(self.__rotate_tex, "rotate_tex") def __rotate_tex(self, task): self.angle += 1. mat = Mat3.ident_mat() mat = mat * Mat3.translate_mat(-.5, -.5) mat = mat * Mat3.rotate_mat(self.angle) mat = mat * Mat3.translate_mat(.5, .5) xform = TransformState.make_mat3(mat) self.model.set_tex_transform(self.ts_color, xform) self.model.set_tex_transform(self.ts_normal, xform) return task.cont app = MyApp() app.run()
You should see a static square model with rotating color and normal maps, as if the apparent 3D-surface itself were rotating. This illusion is broken by the fact that the shading rotates along with the textures instead of respecting the (stationary) position of the light source.
Here are the resources used by the sample:
The normal map used creates big dome-like bumps, while the light source is above and to the right of the model, so a shadow is generated at the bottom left hand side of each "dome". However, when a texture rotation is in effect, this shadow rotates along with the normal map.
As hinted at in this issue comment, this should be a bug in the ShaderGenerator.
The tangent and binormal vectors are meant to transform a normal from tangent space to model space. Since texture matrices change the tangent space, I suppose that the tangent frame should be transformed by the texture matrix as well.
I'm checking in something that fixes your use case, but I can't promise that it's entirely correct—in particular, I'm not sure that non-uniform scales are handled properly.
As an interesting side-effect of my change, you can use the Z coordinate in the texture scale independently to scale the effect of the normal maps. I don't know whether this is correct or whether we should be ignoring the third dimension entirely, but I suppose it could be useful.
If translation, rotation and uniform scales yield expected results, then most use cases should be covered, I think.
It's always nice to have an additional feature :) .
Thank you for fixing this!