Texture translation is not working!

Hi, guys! I want to move the texture around on fixed vertexes using shaders. The images are from cameras. Rotations work well, but nothing happens when applying translation. Could anyone figure out the reason for me please?
The vertex shader is:

const char s_v_shader_glm[] =
        " #version 320 es \n "
        " layout(location = 0) in vec4 vPosition; \n "
        " layout(location = 1) in vec2 vTexCoord; \n "
        " uniform mat3 move; \n "
        " out vec2 TexCoord; \n "
        " uniform mat4 mvp; \n"
        " void main() \n "
        " { \n "
        " gl_Position = mvp * vec4(vPosition.xyz, 1); \n "
        " TexCoord = vec2(move * vec3(vTexCoord, 1)); \n "
        " } \n ";

The fragment shader is:

const char s_f_shader_b_ec[] =
        "#version 320 es \n"
        " precision mediump float;\n "
        " in vec2 TexCoord; \n "
        " out vec4 fragColor; \n "
        " uniform sampler2D myTexture; \n "
        " uniform sampler2D myMask; \n "
        " uniform vec4 myGain; \n "
        " void main() \n "
        " {\n "
        " fragColor = vec4(texture(myTexture, TexCoord).bgr, texture(myMask, TexCoord).r) * myGain; \n "
        " }\n ";

And I’m applying transformation using code like:

GLint locMove;
glm::mat3 altered = glm::mat3(glm::rotate(glm::rotate(glm::rotate(glm::translate(glm::mat4(1), glm::vec3(100.0f, 100.0f, 0.0f)), glm::radians(0.0f), glm::vec3(1.0f, 0.0f, 0.0f)), glm::radians(0.0f), glm::vec3(0.0f, 1.0f, 0.0f)), glm::radians(0.0f), glm::vec3(0.0f, 0.0f, 1.0f)));
locMove = glGetUniformLocation(handle, "move");
glUniformMatrix3fv(locMove, 1, GL_FALSE, glm::value_ptr(altered));

The effects of rotation and scaling are obvious, but no translation is performed, which drives me crazy! Could someone help me ?! Thanks for advance!

Why would you think that translations should work?
What type of matrix do you need to support storing translations in them?

I think it should work because the rotation works and vertex transformation works the same way.
I am not that familiar with opengl es, I think translation needs two offsets for x and y directions for a plane surface, which could be contained within a 3x3 matrix.

With vertex transformation, you’re using 4D coords/matrices to operate on a fundamentally 3D space.

It appears you’re intending to use 3D coords/matrices to operate on a fundamentally 2D space. That’s not the same. That’s different.

You can do this, but you have to build your 3x3 matrices properly.

I’m no GLM guru, but it appears you’re using GLM to build a 4D matrix (with rotations/translations) meant to transform coords in a 3D space and then expecting that to be converted properly to a 3D matrix meant to transform coords in a 2D space. However, I believe glm::mat3() just keeps the upper-left 3x3 part of the 4x4 matrix (the rotation piece) chucking the extra row/column (which contained the translation), whereas you want a different type of 4x4-to-3x3 conversion to occur – one that populates the 3rd row and 3rd column of the 3x3 matrix differently).

Probably something like…:

| m11 m21 m31 m41 |          | m11 m21 m41 |
| m12 m22 m32 m42 |  --->    | m12 m22 m42 |
| m13 m23 m33 m43 |          | 0   0   1   |
| m14 m24 m34 m44 |         


| m11 m21 m31 m41 |          | m11 m21 m31 |
| m12 m22 m32 m42 |  --->    | m12 m22 m32 |
| m13 m23 m33 m43 |          | m13 m23 m33 |
| m14 m24 m34 m44 |         

Yes, I said “vertex transformation works the same way” which is not precise. In fact, the code is on the website “10.8 - Transformations on Texture Maps — LearnWebGL” which is related to shifting textures on 2D surfaces. I also tried introducing a vec2 variable into the vertex shader, by adding the variable’s x and y element to the out vec2 TexCoord variable, like:

uniform vec2 move;
TexCoord = vec2(vTexCoord.x + move.x, vTexCoord.y + move.y);

which didn’t take any effect either. I tried with 3x3 matrix writing down every elements, too, which still did not work.

Hmm… Doesn’t make sense to me either.

Again, I’m no GLM guru. If you haven’t already, I’d dump the 3x3 matrix and verify that:

  • the XY translation is in the last column (not the last row), and
  • the (0,0,1) is in the last row (not the last column).

When in doubt, just transpose the matrix and retry. Just do it! We’ve all been there :slight_smile: Then figure out why it works.


Yes, you are right. Thank you by correction.
I’m messed up by the confusion of basic ideas. The mat3 matrix initialized in my way should be transposed. Too stupid to realize that! Can’t believe trapped in this by more than a day.

No, don’t beat yourself up. We’ve all done it. It’s easy to get your head twisted around when you’ve got 2-3 differences coming in on a language/library barrier:

  1. row-major vs. column-major component storage order,
  2. operator-on-the-left (M*v) vs. operator-on-the-right (v*M) operation order.
  3. transpose vs. not when passing matrices from one to the other.

And on top of that, you’re flipping from 4D homogeneous coords to 3D homogeneous coords. Plenty here to get twisted around with.

Lots of net posts out there on this confusion. But here’s one echoing a good recommendation that I tend to go back to: Ignore all that storage order, operation order, and transpose monkey business, and focus on the memory order of floats in the matrix:

For programming purposes, OpenGL [4x4] matrices are 16-value arrays with base vectors laid out contiguously in memory.

The translation components occupy the 13th, 14th, and 15th elements of the 16-element matrix, where indices are numbered from 1 to 16 …

Or in your case, for a 3x3 homogeneous matrix, translation is the 7th and 8th components in memory, where the indices are numbered from 1 to 9.