GLSL: How to rotate a texture using a direction vector?

Hi, I’m currently looking for a way to draw a fragment rotated, meaning that I could pass a variable to the shader and it would draw the vertex texture rotated X degrees, always on the Y axis, just like a billboard. I don’t want the vertex to be displaced, only the texture. For example this:

So what I’ve done yet is to pass a direction vector to the vertex shader and (I think) I managed to get the Y rotation angle and apply a rotation matrix to the texcoord like this:

vec2 rot_vector_xz = vec2(-1.0, -1.0);
float angle = acos(1.0 - dot(vec2(0.0), rot_vector_xz));
mat2 RotationMatrix = mat2( cos(angle), -sin(angle),
sin(angle), cos(angle) );
texCoord1 = inTexCoord * RotationMatrix;

Unfortunately, it does not seem to do the trick. The texture is always rotated by 0 it seems. I must have the math wrong. Anybody’s got the math skills to help me figure it out?

Thx for reading.

First, unless you are animating this then you are better off just making better texture coordinates.

Second, it will be way easier to just pass two direction vectors (one for x and one for y) rather than doing potentially expensive trig in the shader.

In the end, you don’t really even need a matrix. It’s doing exactly the same thing as multiplying by two direction vectors (in fact they are right there in the matrix, you can see them).

…wait, are you trying to rotate the texture in 3D? That won’t work, really… you’ll need a whole 4x4 projection matrix for that. For the same reason you need one to project 3D stuff onto the computer screen.

My advice above is purely for 2D rotation in the triangle plane.

For the matter tough, I AM animating this in the fragment shader. I have a textureAtlas with like 4 sprites aligned on the X axis and it’s correctly scrolling them in a loop using the Time uniform and mod() call.

What I’m trying to do is a 2D rotation on the Y-axis, so basically, I don’t know if technically what I want is to project it in 3D, but rather just spinning on itself left or right by an amount of radians or something. It’s like exactly the same image but turned on itself for 90 degrees, for example. Do you understand more what I’m after? It’s just a matter of rotating the UV coordinates no?

If it’s just a matter of rotating the UV coordinates then two vectors are all you need and you can just pass them to the shader.

OK so basically, I do the rotation using the CPU in Java and then I set them in the FloatBuffer under whatever free slot I have got, right? Or did you mean to simply overwrite the texcoord FloatBuffer directly?

myMaterial.setVector3(“xAxis”, xAxisVector);
myMaterial.setVector3(“yAxis”, yAxisVector);

Uhm, yeah but that would only work if it was per material, not per vertex like I want. Because each vertex needs a different texture orientation, so I guess I’ll do the same but pass it in the vertex buffer instead?

EDIT: OK instead of playing guess games, let me draw exactly what the complete problem is. Only then you can understand really what I’m trying to accomplish and why your previous solution might not be what I’m after. BRB in 10 minutes.

I don’t know if you’ll understand better with this, but here’s a drawing of what the complete problem is.

N = Normal
T = Tangeant
Red dots = Vertices
Orange smileys = Texture

So basically, as you can see, I’d like a way to make it so the GLSL shader draws the texture aligned with a direction vector, like for instance, the XZ normal vector (or as I said before, Y-axis rotation like a billboard). The problem I’m facing is more complex than just rotating the UV coordinate. The vertices sent to the GPU are coming from a triangle strip and I found out after half an hour of head scratching that the texture coordinates are sometimes sent facing Z+ sometimes X- sometimes Z- you get the idea, it’s pretty much random, probably based on the triangle strip vertex buffer indexes being reused by the adjacent triangles.

Basically, what I’m thinking now is that I could overwrite the texCoord in the vertex FloatBuffer leaving the GLSL shader absolutely unchanged. I proved it could work by manually inputing new texCoords making the texture have the correct orientation. It’s just not something I can manually set as a constant because as I said all triangles have random vertex order, meaning I have to find a way to compute the texCoord for each vertex.

At the moment it looks like this:

Do you think you could help on this?

EDIT: Following up with the above (same post) theory I posted, I have found an almost 100% working solution using for instance the face normal as a direction vector for the texture. It’s probably not optimal and could highly benefit from the hundreds of GPU cores to calculate this instead… or not, maybe it’s better that it’s calculated once by the CPU and set in the buffer once and for all, especially if these triangles are static in the scene I suppose, but anyhow, here’s what I tried and it seems like it’s almost perfect, I found only 2 triangles out of 100 that are not good, but I think I can fix the formula, I probably inverted the (?:slight_smile: or something. I have to go to bed now, I’m sleeping on my keyboard :stuck_out_tongue:

Vector2f[] texCoord = new Vector2f[3];
float max_y = Math.max(vertices[0].y, Math.max(vertices[1].y, vertices[2].y));
texCoord[0] = max_y == vertices[0].y ? new Vector2f(1,0) : (max_y == vertices[1].y ? new Vector2f(0,1) : new Vector2f(0,0));
texCoord[1] = max_y == vertices[0].y ? new Vector2f(0,0) : (max_y == vertices[1].y ? new Vector2f(1,0) : new Vector2f(0,1));
texCoord[2] = max_y == vertices[0].y ? new Vector2f(0,1) : (max_y == vertices[1].y ? new Vector2f(0,0) : new Vector2f(1,0));

triangle_mesh.setBuffer(VertexBuffer.Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));