在opengl android

时间:2016-01-10 14:40:48

标签: android opengl-es rotation

我在android中使用opengl绘制基于图像的纹理,并尝试围绕其中心旋转它 但结果并不像预期的那样,而且看起来有些偏差。

第一个屏幕抓取是在没有旋转的情况下绘制的纹理,第二个是以10度旋转绘制的纹理。

enter image description here

代码段如下:

    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);

在着色器中:

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

第一个屏幕抓取中的黑色区域是GLSurfaceView的区域,灰色区域是我尝试绘制图像的区域。

图像已经处于原点,我认为在旋转之前无需翻译。

1 个答案:

答案 0 :(得分:1)

基本问题是,在应用旋转之前,您需要缩放几何体以调整屏幕宽高比

您实际上缩放几何图形可能并不明显。但是,通过计算用于绘制以调整宽高比的坐标,您可以有效地对几何体应用非均匀缩放变换。如果你然后旋转结果,它将变形。

您需要做的是在缩放之前应用旋转。这将需要对您当前的代码进行一些重组。由于在将坐标传递给OpenGL之前应用缩放,然后在着色器中进行旋转,因此无法轻松更改顺序。你要么:

  • 在将输入传递给OpenGL之前,以适当的顺序将两个变换应用于输入坐标,并从着色器代码中移除旋转。
  • 在着色器代码中以正确的顺序应用两种转换。为此,您不会修改输入坐标以调整宽高比,而是将缩放因子传递到着色器中。

对于第一个选项,在您自己的代码中应用2D旋转很容易,看起来您只有4个顶点,因此没有效率问题。第二种选择当然更优雅。因此,不是缩放客户端代码中的坐标,而是将缩放因子作为制服传递到着色器中。然后,在GLSL代码中,首先应用旋转,然后缩放生成的坐标。

另一种选择是构建完整的变换矩阵(再次基于以正确的顺序应用单个变换),并将该矩阵传递到着色器。