2

I am trying to use GLSL to rotate an image (via glfx.js).

I have checked prior answers such as this and this but the results are still a skewed picture (first answer), or the answer is a bit too terse for my beginner level (the second).

The fragment shader I use looks like this:

uniform sampler2D texture;
uniform vec2 texSize;
varying vec2 texCoord;
uniform float degrees;
const float PI = 3.1415926535897932384626433832795;

float deg2rad(float deg){ return deg * PI / 180.0; }
void main() {
  vec2 coord = texCoord.xy;

  float sin_factor = sin(deg2rad(degrees));
  float cos_factor = cos(deg2rad(degrees));

  coord = coord * mat2(cos_factor, sin_factor, -sin_factor, cos_factor);
  coord = vec2(mod(coord.x, 1.0), mod(coord.y, 1.0));

  vec4 color = texture2D(texture, coord);
  float grey = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b;
  gl_FragColor = vec4(color);

However the resulting image (webcam shot of my ceiling) rotated by 30 degrees is skewed, and when rotated by 180 it is flipped around the X axis, but not the Y (i.e.: it is mirrored).

enter image description here

What do I need to fix so that the image is not skewed or flipped?

simone
  • 4,667
  • 4
  • 25
  • 47
  • What happens when you remove this line: `coord = vec2(mod(coord.x, 1.0), mod(coord.y, 1.0));` – teddybeard Oct 06 '21 at 17:54
  • @teddybeard - no repetition of the image, and no flipping (hopray) but no change in skewing – simone Oct 06 '21 at 19:09
  • Can you provide any `texParameteri` you are using. For example: `gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); ` – teddybeard Oct 06 '21 at 20:56

1 Answers1

1

This will change the rotation to be round the center of the image. It should fix the mirror issues and hopefully the skew as well:

uniform sampler2D texture;
uniform vec2 texSize;
varying vec2 texCoord;
uniform float degrees;
const float PI = 3.1415926535897932384626433832795;
const vec2 HALF = vec2(0.5);

float deg2rad(float deg){ return deg * PI / 180.0; }
void main() {
  vec2 coord = texCoord.xy;

  float sin_factor = sin(deg2rad(degrees));
  float cos_factor = cos(deg2rad(degrees));

  // move rotation origin from upper left to centre of image
  coord -= HALF.xy;
  // rotate image around image centre
  coord *= mat2(cos_factor, sin_factor, -sin_factor, cos_factor);
  // compensate for skew
  coord *= vec2(texSize.y / texSize.x, texSize.x / texSize.y);
  // move origin back to upper left to read from texture
  coord += HALF.xy;

  vec4 color = texture2D(texture, coord);
  float grey = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b;
  gl_FragColor = vec4(color);
teddybeard
  • 1,964
  • 1
  • 12
  • 14
  • Thanks - it fixes the mirroring, but not the skewing. In order to fix the skewing you have to account for aspect ratio - see https://gist.github.com/simonecesano/f4c2d2acecf5a8b7a0277b0431dc1384 - want to include it in the answer and I'll gladly accept it? – simone Oct 07 '21 at 16:46
  • Updated. Try `coord *= vec2(texSize.x / texSize.y, texSize.y / texSize.x);` as well. I'm having a hard time visualising which one is right. This also assumes that the correct values are being set for the `texSize` uniform in Javascript – teddybeard Oct 07 '21 at 19:52