I'm trying to rotate an image in webgl. If the texture has the same width as height there is no problem, but if width is for example 256px and height only 32px the image gets skewed.
It seems as if only the texture is rotating and not the vertices. However usually when only the texture is rotating it's corners gets clipped as they move outside the vertices. That doesn't happen here so I'm a bit confused.
Here is my vertex shader code:
precision lowp float;
attribute vec3 vertPosition;
attribute vec3 vertColor;
attribute vec2 aTextureCoord;
varying vec3 fragColor;
varying lowp vec2 vTextureCoord;
varying lowp vec2 vTextureCoordBg;
uniform vec2 uvOffsetBg;
uniform vec2 uvScaleBg;
uniform mat4 uPMatrix;
uniform vec2 uvOffset;
uniform vec2 uvScale;
uniform vec3 translation;
uniform vec3 scale;
uniform float rotateZ;
uniform vec2 vertPosFixAfterRotate;
void main()
{
fragColor = vertColor;
vTextureCoord = (vec4(aTextureCoord.x, aTextureCoord.y, 0, 1)).xy * uvScale + uvOffset;
vTextureCoordBg = (vec4(aTextureCoord, 0, 1)).xy * uvScaleBg + uvOffsetBg;
mat4 worldPosTrans = mat4(
vec4(scale.x*cos(rotateZ), scale.y*-sin(rotateZ), 0, 0),
vec4(scale.x*sin(rotateZ), scale.y*cos(rotateZ), 0, 0),
vec4(0, 0, scale.z, 0),
vec4(translation.x, translation.y, translation.z, 1));
gl_Position = (uPMatrix * worldPosTrans) * vec4(vertPosition.x + vertPosFixAfterRotate.x, vertPosition.y + vertPosFixAfterRotate.y, vertPosition.z, 1.0);
}
The rotation is sent from javascript to the shader through the rotateZ uniform.
You have to do the scaling before the rotation:
Scale matrix:
mat4 sm = mat4(
vec4(scale.x, 0.0, 0.0, 0.0),
vec4(0.0, scale.y, 0.0, 0.0),
vec4(0.0, 0.0, scale.z, 0.0),
vec4(0.0, 0.0, 0.0, 1.0));
Rotation matrix:
mat4 rm = mat4(
vec4(cos(rotateZ), -sin(rotateZ), 0.0, 0.0),
vec4(sin(rotateZ), cos(rotateZ), 0.0, 0.0),
vec4(0.0, 0.0, 1.0, 0.0),
vec4(0.0, 0.0, 0.0, 1.0));
Translation matrix:
mat4 tm = mat4(
vec4(1.0, 0.0, 0.0, 0.0),
vec4(0.0, 1.0, 0.0, 0.0),
vec4(0.0, 0.0, 0.0, 0.0),
vec4(translation.x, translation.y, translation.z, 1.0));
Model transformtion:
mat4 worldPosTrans = tm * rm * sm;
See the result and focus on scale.x
and scale.y
, in compare to the code snippet in your question:
mat4 worldPosTrans = mat4(
vec4(scale.x * cos(rotateZ), scale.x * -sin(rotateZ), 0.0, 0.0),
vec4(scale.y * sin(rotateZ), scale.y * cos(rotateZ), 0.0, 0.0),
vec4(0.0, 0.0, scale.z, 0.0),
vec4(translation.x, translation.y, translation.z, 1.0));