p3d_TextureMatrix usage?

Until now I was sending the texture transform matrices manually towards my shaders using something like :

np.setShaderInput("texmat_%d" % index, np.getTexTransform(stage).getMat())

I’m trying to use instead the built-in texture matrices p3d_TextureMatrix[] but so far I can’t understand how the matrices are organized in the array. It seems that only the first entry is set, even if all the texture stages have a tex matrix applied.

They should correspond to the texture stages. Do you have a test case that shows otherwise?

Not yet only tested with my full app, I will make a simple one (if the problem is not in my own code :slight_smile: )

Here is the test case and actually the results are even weirder than I thought :

import os

from panda3d.core import Texture, TextureStage, CardMaker, Shader, load_prc_file_data
from direct.showbase.ShowBase import ShowBase

load_prc_file_data("", "gl-version 3 2")
def shader():
    return Shader.make(Shader.SL_GLSL,
                       vertex="""
#version 410

uniform mat4 p3d_ProjectionMatrix;
uniform mat4 p3d_ModelViewMatrix;

in vec4 p3d_Vertex;
in vec4 p3d_MultiTexCoord0;

out vec4 texcoord;

void main() {
    gl_Position = p3d_ProjectionMatrix * (p3d_ModelViewMatrix * p3d_Vertex);
    texcoord = p3d_MultiTexCoord0;
}
""",
                       fragment="""
#version 410

uniform mat4 p3d_TextureMatrix[2];
uniform sampler2D p3d_Texture0;
uniform sampler2D p3d_Texture1;

in vec4 texcoord;

out vec4 frag_color;

void main() {
    vec4 texcoord_tex0 = p3d_TextureMatrix[0] * texcoord;
    //vec4 texcoord_tex0 = texcoord;    
    vec4 tex0 = texture(p3d_Texture0, texcoord_tex0.xy);
    vec4 texcoord_tex1 = p3d_TextureMatrix[1] * texcoord;
    //vec4 texcoord_tex1 = texcoord;
    vec4 tex1 = texture(p3d_Texture1, texcoord_tex1.xy);
    frag_color = tex0 * tex1;
}
""")


base = ShowBase()
cm = CardMaker('card')
card = render.attachNewNode(cm.generate())
card.setPos(-0.5, 3, -0.5)
card.set_shader(shader())

tex = loader.loadTexture('maps/smiley.rgb')
ts = TextureStage('first')
card.setTexture(ts, tex)
card.setTexScale(ts, 1, -1)

tex = loader.loadTexture('maps/noise.rgb')
ts = TextureStage('second')
card.setTexture(ts, tex)
card.setTexScale(ts, 2, 2)

card.ls()

base.run()

If I don’t use the texture matrices, the output is :

If I use the texture matrix of the first texture, the smiley is inverted :

If i use the texture matrix of the second texture, the noise texture disappears :

If I use the texture matrix for both textures, the result is even weirder :

Same problem on Mac and Linux so it’s not a driver problem. It looks like all the texture matrices are written in the first slot of the matrix array.

Yeah, thanks for the clear test case, this has a straightforward fix:

For the record, texture stages without sort value are in indeterminate order, so you should generally always give them a distinct sort value.

Thanks for the fix but also thanks for the info, that something I overlooked until now.

Side question, if a texture stage has no transform matrix applied, will there still be an entry in the TextureMatrix ?

Yes, it will then contain the identity matrix.