1
\$\begingroup\$

I'm rendering a texture to a square.

I have to scale the texture because it is 10 times wider than it is tall.

In my fragment shader I divide both the X and Y texture coordinates (I'm using OpenGL), but I divide the x texture coordinates by 10 times more than the y coordinates and I get this nice looking image: enter image description here

Then I do some rotation of the texture (the square stays put). I rotate my texture coordinates using a matrix that looks like this:

[cosr sinr]

[-sinr cosr]

where r is the angle of rotation in radians of the player. (OpenGL uses column-major matrices).

When I rotate, of course I have to do something about scaling differently now, but I'm not sure what. For now, I'm doing nothing to adjust my scale factor for the orientation of the texture. Thus, if I rotate a little it looks like this:

enter image description here

And if I rotate by a lot it looks like this: (that green is the green circles from before)

enter image description here

What can I do to accurately adjust scale for changes in orientation in a way that makes mathematical sense?

\$\endgroup\$
2
  • \$\begingroup\$ What happens if you reverse the order you do the rotation and scaling? Does the problem go away? \$\endgroup\$ Feb 24, 2018 at 6:15
  • \$\begingroup\$ I hope this thebookofshaders.com/08 helps you \$\endgroup\$ Feb 24, 2018 at 14:20

1 Answer 1

1
\$\begingroup\$

I needed to use matrices. The same stuff that one would do for 3D, I applied to 2D for the textures.

Roughly as follows, multiplying the matrix first on the CPU then sending it to my shader. Note that OpenGL uses column-major matrices, and just like you would use 4x4 augmented matrices with a 1 at the end for transformations in 3D space, I use 3x3 augmented matrices to manipulate the 2D textures.

    mat3 textures_position_mat;
    mat3 textures_scale_mat;
    mat3 textures_orientation_mat;
    mat3 textures_transform_mat;

    glm_mat3_identity(textures_position_mat);
    textures_position_mat[0][2] = player.y / 1.0;
    textures_position_mat[1][2] = player.x / 1.0;

    glm_mat3_identity(textures_scale_mat);
    textures_scale_mat[0][0] = 1.0/10.0;
    textures_scale_mat[1][1] = 1.0/1.0;

    glm_mat3_identity(textures_orientation_mat);
    textures_orientation_mat[0][0] = cos(player_rotation_radians);
    textures_orientation_mat[0][1] = sin(player_rotation_radians);
    textures_orientation_mat[1][0] = -sin(player_rotation_radians);
    textures_orientation_mat[1][1] = cos(player_rotation_radians);

    glm_mat3_identity(textures_transform_mat);
    glm_mat3_mul(textures_orientation_mat, textures_scale_mat, textures_transform_mat);
    glm_mat3_mul(textures_transform_mat, textures_position_mat, textures_transform_mat);

    glUniformMatrix3fv(glGetUniformLocation(shader_perspective, "textures_transform_mat_input"), 1, GL_FALSE, textures_transform_mat);

My fragment shader looks like this. Note that at the end, the texture coordinates are located in the [0][2] and [1][2] positions as OpenGL is column-major.

mat3 textures_transform_matrix;

mat3 TexCoord_to_mat3;

mat3 foo_mat3;

//textures_transform_matrix = textures_transform_mat_input;

//textures_transform_matrix[0][2] = -textures_transform_matrix[0][2];

TexCoord_to_mat3[0][0] = 1.0;
TexCoord_to_mat3[1][1] = 1.0;
TexCoord_to_mat3[2][2] = 1.0;
TexCoord_to_mat3[0][2] = TexCoord.x;
TexCoord_to_mat3[1][2] = TexCoord.y;

//vec2 foo = vec2(-TexCoord.x + textures_transform_matrix[2][0], TexCoord.y + textures_transform_matrix[2][1]);
foo_mat3 = TexCoord_to_mat3 * textures_transform_mat_input;
vec2 foo = vec2(foo_mat3[0][2], foo_mat3[1][2]);

vec2 bar = vec2(TexCoord.x, TexCoord.y);
color = texture(ourTexture1, foo);  
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .