【问题标题】:Simple textured quad rotation in OpenGL ES 2.0OpenGL ES 2.0 中的简单纹理四边形旋转
【发布时间】:2019-11-12 23:37:30
【问题描述】:

编辑 6 - 完全重写与 cmets/正在进行的研究相关的内容

Edit 7 - 添加投影/视图矩阵.....

由于我对此没有深入了解,因此我从 Google 演示中添加了视图/投影矩阵 - 请参阅下面的代码:如果有人能指出我哪里出错了,我将不胜感激,因为我是当我将 ""gl_position = a_position * uMVPMatrix;" + 放入顶点着色器时仍然出现空白屏幕(使用 "gl_position = a_position;" + 我的四边形至少显示......)

在类级别声明:(四类)

    private final float[] rotationMat = new float[16];
    private FloatBuffer flotRotBuf;
    ByteBuffer rotBuf;
    private int muRotationHandle = -1;              // Handle to the rotation matrix in the vertex shader called "uRotate"

在类级别声明:(渲染器类)

    private final float[] mVMatrix = new float[16];
    private final float[] mProjMatrix = new float[16];
    private final float[] mMVPMatrix = new float[16];

设置纹理并执行(或应该执行)旋转的例程(这在我的 Quad 类中

public void setTexture(GLSurfaceView view, Bitmap imgTexture, float[] mvpMatrix){
        this.imgTexture=imgTexture;

      // get handle to shape's transformation matrix
        mMVPMatrixHandle = GLES20.glGetUniformLocation(iProgId, "uMVPMatrix");

        // Apply the projection and view transformation
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

//      Matrix.setRotateM(rotationMat, 0, 45f, 0, 0, 1.0f);    //Set rotation matrix with angle and (z) axis

//       rotBuf = ByteBuffer.allocateDirect(rotationMat.length * 4);
         // use the device hardware's native byte order
//       rotBuf.order(ByteOrder.nativeOrder());
         // create a floating point buffer from the ByteBuffer
//       flotRotBuf = rotBuf.asFloatBuffer();
         // add the coordinates to the FloatBuffer
//       flotRotBuf.put(rotationMat);
         // set the buffer to read the first coordinate
//       flotRotBuf.position(0);

//       muRotationHandle = GLES20.glGetUniformLocation(iProgId, "uRotation");  // grab the variable from the shader
//       GLES20.glUniformMatrix4fv(muRotationHandle, 1, false, flotRotBuf); //Pass floatbuffer contraining rotation matrix info into vertex shader
         //GLES20.glUniformMatrix4fv(muRotationHandle, 1, false, rotationMat, 1); //Also tried this ,not use floatbuffer

        //Vertex shader
        String strVShader =  
            //    "uniform mat4 uRotation;" +
                  "uniform mat4 uMVPMatrix;" +
                  "attribute vec4 a_position;\n"+
                  "attribute vec2 a_texCoords;" +
                  "varying vec2 v_texCoords;" +
                  "void main()\n" +
                  "{\n" +
                  "gl_Position = a_Position * uMVPMatrix;"+  //This is where it all goes wrong....         
                  "v_texCoords = a_texCoords;" +
                  "}";

        //Fragment shader

        String strFShader =
            "precision mediump float;" +
            "varying vec2 v_texCoords;" +
            "uniform sampler2D u_baseMap;" +
            "void main()" +
            "{" +
            "gl_FragColor = texture2D(u_baseMap, v_texCoords);" +
            "}";


        iProgId = Utils.LoadProgram(strVShader, strFShader);
        iBaseMap = GLES20.glGetUniformLocation(iProgId, "u_baseMap");
        iPosition = GLES20.glGetAttribLocation(iProgId, "a_position");
        iTexCoords = GLES20.glGetAttribLocation(iProgId, "a_texCoords");
        texID = Utils.LoadTexture(view, imgTexture);

    }

来自我的渲染器类:

public void onSurfaceChanged(GL10 gl, int width, int height) {
    // TODO Auto-generated method stub

    //Set viewport size based on screen dimensions      
    GLES20.glViewport(0, 0, width, height);

    float ratio = (float) width / height;
    Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);

}

    public void onDrawFrame(GL10 gl) {
    // TODO Auto-generated method stub

    //Paint the screen the colour defined in onSurfaceCreated
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

    // Set the camera position (View matrix)
    Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);


    // Calculate the projection and view transformation
    Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);

    quad1.setTexture(curView, myBitmap, mMVPMatrix);  //SetTexture now modified to take a float array (See above) - Note I know it's not a good idea to have this in my onDrawFrame method - will move it once I have it working!

    quad1.drawBackground(); 
}

我现在已经删除了所有与旋转相关的东西,现在我只是尝试在顶点着色器中应用 uMVPMatrix 后显示一个静态四边形。但还是什么都没有:-(

如果我只是将该行改回“默认”:

    "gl_Position = a_position;\n"+

然后我至少可以显示我的纹理四边形(显然没有旋转,我希望如此)。

还需要指出的是,mvpMatrix 肯定被完整地接收到 setTexture 方法中是有效的(包含与我从 Google 开发人员代码中记录 mvpMatrix 内容时出现的相同数据)。我不确定如何检查着色器是否完好无损地接收它?我没有理由相信它不是。

真的很感激和所有的帮助 - 我一定是在某个地方出错了,但我就是找不到。谢谢!

编辑 2:在为这个问题添加了赏金之后,我想知道如何旋转我的带纹理的四边形精灵 (2D),并保留我必须将其渲染为基础的代码。 (即,我需要添加什么才能旋转以及为什么)。谢谢!

编辑 3 不适用

EDIT 4重新措辞/简化问题

EDIT 5添加错误截图

【问题讨论】:

  • 在 glUniformMatrix4v 中为假!= GL_FALSE。 false 是 c++ 关键字,GL_FALSE 是枚举。
  • 此外,您似乎从未在顶点着色器中应用您的 uMVPMatrix。如果你不需要应用这个,不要把它列为制服,也不要在修复中应用它。
  • 如果我输入 GL_FALSE,我只会得到“GL_FALSE 无法解析为变量”
  • 所以我在 V-Shader 中的行应该是 "gl_Position * vec4(a_position,1.0f);"+ 并且我不应该声明 uMVPMatrix(我确实意识到这没有在代码)。也许我应该忘记轮换!!!大声笑
  • 好吧,如果您没有将顶点位置转换为世界、视图或投影空间,那么您可以保持顶点着色器不变。可以通过说gl_Position = uRotation * a_position; 来应用旋转

标签: android rotation opengl-es-2.0 transformation


【解决方案1】:

编辑:编辑以支持使用 Android SDK 的 Java。

正如 Tobias 所指出的,OpenGL 中任何顶点变换的惯用解决方案都是通过使用矩阵运算来完成的。如果您打算继续使用 OpenGL 进行开发,重要的是您(最终)了解矩阵运算中涉及的底层线性代数,但通常最好使用数学库将线性代数计算抽象为更易读的格式。在 android 环境下,您应该使用 [matrix][1] 类操作浮点数组来创建旋转矩阵,如下所示:

// initialize rotation matrix
float[16] rotationMat; 
Matrix.setIdentityM(rotationMat,0); 

// angle in degrees to rotate
float angle = 90;

// axis to rotate about (z axis in your case)
float[3] axis = { 0.0,0.0,1.0};

// For your case, rotate angle (in degrees) about the z axis. 
Matrix.rotateM(rotationMat,0,angle,axis[0],axis[1],axis[2]);

然后你可以像这样将旋转矩阵绑定到着色器程序:

// assuming shader program is currently bound ...
GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(shaderProgramID, "uRotation"), 1, GL_FALSE, rotationMat);

您的顶点着色器(正在传递的程序 rotationMat)看起来像:

precision mediump float;
uniform mat4 uMVPMatrix;
uniform mat4 uRotation;
attribute vec2 a_texCoords;
attribute vec3 a_position;
varying v_texCoord;

void main(void)
{
    v_texCoord = a_texCoords;
    gl_Position = uMVPMatrix* uRotation * vec4(a_position,1.0f);
}

或者,您可以在此着色器程序之外预乘 uMVPMatrix* uRotation 并将结果传递给您的着色器程序以避免过多的重复计算。

一旦您习惯了使用这个更高级别的 API 进行矩阵运算,您就可以通过阅读 thisNicol Bolas 编写的精彩教程来研究内部运算是如何执行的。

【讨论】:

  • 嘿@SirDigbyChickenCaesa,谢谢你,我一定会看看你发送的tut链接。我以前听说过 GLM,但从未研究过。我假设这是 C 是否正确?如果是这样,我是否需要这样实现它(我假设使用 NDK?),如果是这样,我有什么方法可以仅使用 SDK/Java 进行这种轮换吗?再次感谢!!
  • 哇,对不起!我习惯于在使用 OpenGL 时考虑 C++ 的头部空间,以至于我忘记了你很可能在 Android 上使用 Java。我会寻找一个功能强大的 java 数学库,我会编辑这篇文章。
  • 哇,这并不像我想象的那么容易。我认为 vecmath 存在许可问题?还有其他选择吗?我从 Android 开发人员那里获得了在屏幕中心绘制一个旋转三角形的代码,但是对于我的一生,当我尝试将代码移植到我的代码时,我什么也没得到。当我将着色器中的“”gl_Position = a_Position;”行更改为“gl_Position = uMVPMatrix * a_Position;”时,我将发布一些代码.....再次感谢您
  • 我正在尝试调整的代码是:developer.android.com/training/graphics/opengl/index.html,效果很好。我可以设置更改代码以将角度设置为特定量等,但我看不到任何数学运算发生在哪里,或者它是如何计算实际旋转的。当我尝试实现它时,我什么也没得到,基本上只是一个空白屏幕 - 知道我可能会错过什么吗?我的结构与代码略有不同,因为我有自己编写的渲染方法(如上所述)........再次,任何帮助将不胜感激,我已经使用这个方法有一段时间了!谢谢
  • 哦,看来android有一个专门用于处理opengl中的矩阵运算的类。请参阅我修改后的答案。
【解决方案2】:

绕z旋转的旋转矩阵:

cos a -sin a 0
sin a  cos a 0
    0      0 1

如何记住如何构造它:
a 是以弧度为单位的角度,对于 a = 0,矩阵产生单位矩阵。 cos 必须在对角线上。一个罪前面必须有一个符号,切换符号与旋转的方向相反。

同样可以构造围绕 x 和 y 的旋转:

1      0     0
0  cos a sin a
0 -sin a cos a

 cos a 0 sin a
     0 1     0
-sin a 0 cos a

如果你不熟悉矩阵算术,这里有一些代码:

for (int i=0; i<4; i++) {
    vertices_new[i*5+0] = cos(a) * vertices[i*5+0] - sin(a) * vertices[i*5+1]; // cos(a) * v[i].x - sin(a) * v[i].y + 0 * v[i].z
    vertices_new[i*5+1] = sin(a) * vertices[i*5+0] + cos(a) * vertices[i*5+1]; // sin(a) * v[i].x + cos(a) * v[i].y + 0 * v[i].z
    vertices_new[i*5+2] = vertices[i*5+2]; // 0 * v[i].x + 0 * v[i].y + 1 * v[i].z
    vertices_new[i*5+3] = vertices[i*5+3]; // copy texture u
    vertices_new[i*5+4] = vertices[i*5+4]; // copy texture v
}

【讨论】:

  • 谢谢,请@TobiasSchlegel 详细说明您的代码中发生了什么,另外,您能否告诉我如何将其实现到我最初发布的代码中 - 谢谢。跨度>
猜你喜欢
  • 1970-01-01
  • 2013-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-31
相关资源
最近更新 更多