Simple texture rotation shader

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By etalot

Hi.
I need sample texture rotation shader. Please share if you have.

:bust_in_silhouette: Reply From: SIsilicon

To rotate a texture in a shader, you have to rotate its texture coordinates. This solution should work for both 2D and 3D.

vec2 rotateUV(vec2 uv, vec2 pivot, float rotation) {
    float sine = sin(rotation);
    float cosine = cos(rotation);
    
    uv -= pivot;
    uv.x = uv.x * cosine - uv.y * sine;
    uv.y = uv.x * sine + uv.y * cosine;
    uv += pivot;

    return uv;
}
  • uv is the texture coordinate you’re initially using.
  • pivot is the point the uv will rotate about.
  • rotation is how much you’re resting the uv in radians.

So all you have to do is use the new uv from this function to sample the texture with. The following example rotates a texture by 45° (a quarter of π in radians).

shader_type canvas_item;

void fragment() {
    COLOR = texture(TEXTURE, rotateUV(UV, vec2(0.5), PI/4));
}
uv.x = uv.x * cosine - uv.y * sine;
uv.y = uv.x * sine + uv.y * cosine;

You’re changing uv.x, then using uv.x to calculate uv.y - this stops it working. Need to create a new vec2 for the new values since uv.x needs to be unchanged to calculate uv.y.

JESTERRRRRR | 2020-12-03 22:37

I see you included a pivot- nice touch. But how do you know where you’re pivoting from? Where is a UV centered? Is there a way to visualize where you’re rotating around inside the godot shader editor?

Erich_Lamontagne | 2021-04-19 16:45

:bust_in_silhouette: Reply From: bemyak

@SIsilicon 's answer didn’t work for me.
I changed it a little bit and now it is OK:

shader_type canvas_item;
render_mode unshaded, blend_disabled;

uniform float speed = 1.0;

vec2 rotateUV(vec2 uv, vec2 pivot, float rotation) {
	float cosa = cos(rotation);
	float sina = sin(rotation);
	uv -= pivot;
	return vec2(
		cosa * uv.x - sina * uv.y,
		cosa * uv.y + sina * uv.x 
	) + pivot;
}

void vertex() {
	VERTEX = rotateUV(VERTEX, 0.5/TEXTURE_PIXEL_SIZE, TIME * speed);
}

UPDATE: changed fragment function to vertex for performance reasons

:bust_in_silhouette: Reply From: burstina

previous examples didn’t work for me, probably because I used to rotate a mask.
This one works great

vec2 rotateUVmatrinx(vec2 uv, vec2 pivot, float rotation)
{
	mat2 rotation_matrix=mat2(	vec2(sin(rotation),-cos(rotation)),
								vec2(cos(rotation),sin(rotation))
								);
    uv -= pivot;
    uv= uv*rotation_matrix;
    uv += pivot;
    return uv;
}

I don’t know logic beyound rotation_matrix whatabout, I’ll take it as an axiom :slight_smile: