bsguru
bsguru

Reputation: 472

Rotating an image based texture in opengl android

I am drawing an image based texture using opengl in android and trying to rotate it about its center.
But the result is not as expected and it appears skewed.

First screen grab is the texture drawn without rotation and the second one is the one drawn with 10 degree rotation.

enter image description here

Code snippet is as below:

    mViewWidth = viewWidth;//View port width
    mViewHeight = viewHeight;//View port height
    float ratio = (float) viewWidth / viewHeight;
    Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
    .....
    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, 0f, 0.0f, 1.0f, 0.0f);
    Matrix.setRotateM(mRotationMatrix, 0, 10, 0, 0, 1.0f);

    Matrix.multiplyMM(temp, 0, mProjectionMatrix, 0, mViewMatrix, 0);
    Matrix.multiplyMM(mMVPMatrix, 0, temp, 0, mRotationMatrix, 0);
    GLES20.glUniformMatrix4fv(mRotationMatrixHandle , 1, false, mRotationMatrix, 0);

And in shader:

....
"  gl_Position = uMVPMatrix*a_position;\n"
....

The black area in the first screen grab is the area of GLSurfaceView and the grey area is the area where I am trying to draw the image.

The image is already at origin and I think there is no need to translate before rotating it.

Upvotes: 0

Views: 1371

Answers (1)

Reto Koradi
Reto Koradi

Reputation: 54642

The basic problem is that you're scaling your geometry to adjust for the screen aspect ratio before you apply the rotation.

It might not be obvious that you're actually scaling the geometry. But by calculating the coordinates you use for drawing to adjust for the aspect ratio, you are effectively applying a non-uniform scaling transformation to the geometry. And if you then rotate the result, it will get distorted.

What you need to do is apply the rotation before you scale. This will require some reorganization of your current code. Since you apply the scaling before you pass the coordinates to OpenGL, and then do the rotation in the shader, you can't easily change the order. You either have to:

  • Apply both transformations, in the proper order, to the input coordinates before you pass them to OpenGL, and remove the rotation from the shader code.
  • Apply both transformations, in the proper order, in the shader code. To do this, you would not modify the input coordinates to adjust to the aspect ratio, and pass a scaling factor into the shader instead.

For the first option, applying a 2D rotation in your own code is easy enough, and it looks like you only have 4 vertices, so there is no efficiency concern. Still the second options is certainly more elegant. So instead of scaling the coordinates in your client code, pass a scaling factor as a uniform into the shader. Then, in the GLSL code, apply the rotation first, and scale the resulting coordinates.

Another option is that you build the complete transformation matrix (again based on applying the individual transformations in the correct order), and pass that matrix into the shader.

Upvotes: 1

Related Questions