OpenGL Texture transformation with texture.matrixAutoUpdate = false

I would like to manually set the texture matrix as I do on my OpenGL app:

glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(0.5, 0.5, 0.0);
glScalef(scaleX * objHeight, scaleY * objWidth, 1.0);
glRotatef(angle, 0.0, 0.0, 1.0);
glScalef(1.0 / objHeight, 1.0 / objWidth, 1.0);
glTranslatef(-0.5, -0.5, 0.0);
glTranslatef(offsetX, offsetY * -scaleX, 0.0);

So, as a Threejs newbie, I tried

texture.matrixAutoUpdate = false;
texture.matrix.identity();
texture.offset.set(0.5, 0.5);
texture.repeat.set(1.0 / (scaleX * objHeight), 1.0 / (scaleY * objWidth));
texture.rotation = deg2rad(angle);
texture.repeat.set(objHeight, objWidth);
texture.offset.set(-0.5, -0.5);
texture.offset.set(offsetX, offsetY * -scaleX);
texture.updateMatrix();

but I get a uniform bad dark brown color instead of my texture.
The UV are correct. If I don’t apply any transformation, the texture shows up well.

Do you know how to apply that OpenGL transformation to the texture?

I don’t think you will be able to apply this 1:1 to three. You could ask for the gl context from the renderer and try to apply these yourself (say in onBeforeRender perhaps). Otherwise, the texture you set the transform on may or may not apply it, depending on what texture it is. It’s all somewhat confusing, but depending on the material, and which slot you put the texture in (diffuse, or specular for example) one transform will be honored, and the other wont.

Using my OpenGL method (here above) I’m able to properly rotate a texture over a surface, for example here I rotate it by 45°.

Using the Three.js method

texture.center.set(0.5, 0.5);
texture.rotation = deg2rad(45);

I get a wrong rotation. Everything is distorted. That’s why I need to access the texture matrix and modify it. Is anyone who knows how to do?

See here, I answered a similar question last year, might be relevant to your scenario:

1 Like

Hi marquizzo, I know that sample. You change the geometry so the UV coordinates. If you look at my OpenGL code here above, my calculation includes the object size too therefore its ratio too. So it’s something similar to yours. Anyway, I think there should be a shorter way to do it without modifying the UV.

I just need to rotate and scale the texture matrix sequentially as I am used to do on my OpenGL app. But on Threejs the transformation of the texture matrix has its own sequence, that I don’t know. I even tried to change the sequence of my functions as from

texture.rotation = deg2rad(angle);
texture.repeat.set(scaleX, scaleY);

to

texture.repeat.set(scaleX, scaleY);
texture.rotation = deg2rad(angle);

but the result is just the same. So Threejs uses its own sequence internally.
I even tried to manually set the texture matrix

console.log(texture.matrix);
texture.matrixAutoUpdate = false;
const newM = new THREE.Matrix3();
newM.set( 2, 0, 0,
          0, 2, 0,
		  0, 0, 2 );
texture.matrix.set(newM);
texture.updateMatrix();
console.log(texture.matrix);

but the 2 logs always say texture.matrix is always
1,0,0,
0,1,0,
0,0,1

Your solution could work for simple cases.

In case of multiple textures over the same mesh, e.g. a first texture rotated and a second texture nor rotated, this method doesn’t work.

Also I think we should not rebuild the uv at any texture rotation because it’s a time consuming task.