p_0g_amm3_
p_0g_amm3_

Reputation: 451

How to rotate a translated texture around its center

I'm working on the following shader that

  1. translates (on y)

  2. rotates

  3. repeats (tiles)

a texture:

uniform sampler2D texture;
uniform vec2 resolution;

varying vec4 vertColor;
varying vec4 vertTexCoord;

uniform float rotation;
uniform float yTranslation;

void main() {
  vec2 repeat = vec2(2, 2);
  vec2 coord = vertTexCoord.st;

  coord.y += yTranslation;

  float sin_factor = sin(rotation);
  float cos_factor = cos(rotation);
  coord += vec2(0.5);
  coord = coord * mat2(cos_factor, sin_factor, -sin_factor, cos_factor) * 0.3;
  coord -= vec2(0.5);

  coord = vec2(mod(coord.x * repeat.x, 1.0f), mod(coord.y * repeat.y, 1.0f));

  gl_FragColor = texture2D(texture, coord) * vertColor;
}

Current behavior

Current

Desired behavior

I want the texture to always rotate around the center, no matter how far it has been translated.

Desired

Simply swapping the order of the steps results in weird behavior. What am I missing?

Upvotes: 0

Views: 316

Answers (1)

derhass
derhass

Reputation: 45322

Your problem statement in the question is really wrong: Your addtional comment (to a now deleted answer):

I have a boat that always stays in the center of the screen, the water texture (controlled by this shader) under it moves to make it look like the boat is moving. The movement of the water texture is controlled by rotation (for steering) and yTranslation (for how far the boat has moved forwards/backwards)

makes it clear that you're asking for a different thing, and the approach described in the question is simply not going to solve your problem.

When your boat moves and rotates, it will basically travel on a curve (and you want the inverse of that curve to travel through texture space). But your 2dof parameters rotation and yTranslation are not capable of describing the curve. Your problem needs at least another parameter xTranslation - so in the end, you need a 2D vector describing the position of your boat + an angle describing the rotation. And you need to properly accumulate this data at each simulation step:

  • update the rotation accordingly
  • calculate the 2D vector your ship is heading tom as defined by the current rotation
  • scale it according to the velocity of the movement
  • accumulate it onto the position vector.

Then, your shader simply has to 1. translate the texcoords by position (or -position, whatever you store) 2. Rotate around the pivot point (which is constant and only depends on how you layed out your texture space)

coord = vec2(mod(coord.x * repeat.x, 1.0f), mod(coord.y * repeat.y, 1.0f));

that's a waste of GPU ALU cycles, the TMUs will already do the mod for you with the GL_REPEAT wrap modes.

However, what you now have here is rotation, scaling and translation: so just use a single matrix for the whole texcoord transformation - the accumulation of the 2D position that I talked about earlier can nicely by done with the matrix representations. It will also remove the sin and cos from your shader, which is another huge waste right now.

Upvotes: 2

Related Questions