简体   繁体   English

OpenGL ES 2.0 中的简单纹理四边形旋转

[英]Simple textured quad rotation in OpenGL ES 2.0

Edit 6 - Complete re-write in relation to comments/ongoing research编辑 6 - 完成与评论/正在进行的研究相关的重写

Edit 7 - Added projection / view matrix.....编辑 7 - 添加投影/视图矩阵.....

As I'm not getting far with this, I added view/projection matrix from the Google demo - please see code below: If anyone can point out where I'm going wrong it really would be appreciated, as I'm still getting a blank screen when I put ""gl_position = a_position * uMVPMatrix;" + into my vertex shader (with "gl_position = a_position;" + my quad is displayed at least.......)由于我对此没有深入了解,我从 Google 演示中添加了视图/投影矩阵 - 请参阅下面的代码:如果有人能指出我哪里出错了,我将不胜感激,因为我仍然得到一个当我将 ""gl_position = a_position * uMVPMatrix;" + 放入我的顶点着色器时出现空白屏幕(使用 "gl_position = a_position;" + 我的四边形至少显示......)

Declared at class level: (Quad class)在班级宣布:(四班)

    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"

Declared at class lever: (Renderer class)在类杠杆上声明:(渲染器类)

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

Routine that sets texture and does (or is supposed to do) rotation (This is in my Quad class设置纹理并执行(或应该执行)旋转的例程(这是在我的 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);

    }

From my renderer class:从我的渲染器类:

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

I've now removed all rotation related stuff and am now just attempting to get a static quad to display after applying the uMVPMatrix in the vertex shader.我现在已经删除了所有与旋转相关的东西,现在我只是尝试在顶点着色器中应用 uMVPMatrix 后显示一个静态四边形。 But still nothing :-(但仍然没有:-(

If I simply change that line back to the 'default' :如果我只是将该行改回“默认”:

    "gl_Position = a_position;\n"+

Then I at least get my textured quad displayed (Obviously no rotation and I would expect that).然后我至少显示了我的纹理四边形(显然没有旋转,我希望如此)。

Also just to point out, that mvpMatrix is definately being received intact into the setTexture method is valid (contains the same data as appears when I log the contents of mvpMatrix from the Google developers code).还要指出的是, mvpMatrix 肯定会被完整地接收到 setTexture 方法中是有效的(包含与我从 Google 开发人员代码中记录 mvpMatrix 的内容时显示的数据相同的数据)。 I'm not sure how to check if the shader is receiving it intact?我不确定如何检查着色器是否完好无损地接收它? I have no reason to believe it isn't though.我没有理由相信它不是。

Really do appreciate and and all help - I must be going very wrong somewhere but I just can't spot it.真的很感激并提供所有帮助 - 我一定在某个地方出错了,但我就是无法发现它。 Thank you!谢谢!

EDIT 2 : Having added a bounty to this question, I would just like to know how how to rotate my textured quad sprite (2D) keeping the code I have to render it as a base.编辑 2 :在这个问题上添加了一个赏金,我只想知道如何旋转我的纹理四边形精灵 (2D) 保留我必须将其渲染为基础的代码。 (ie, what do I need to add to it in order to rotate and why). (即,我需要添加什么才能旋转以及为什么)。 Thanks!谢谢!

EDIT 3 N/A编辑 3 不适用

EDIT 4 Re-worded / simplified question编辑 4重新措辞/简化问题

EDIT 5 Added error screenshot编辑 5添加错误截图

在此处输入图片说明

Rotation matrix for rotation around z:绕 z 旋转的旋转矩阵:

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

How to remember how to construct it:如何记住如何构建它:
a is the angle in radians, for a = 0 the matrix yields the identity-matrix. a 是以弧度为单位的角度,对于 a = 0,矩阵产生单位矩阵。 cos has to be on the diagonal. cos 必须在对角线上。 There has to be one sign in front of one sin, switching the signs inverses the rotation's direction.在一个罪之前必须有一个符号,切换符号与旋转的方向相反。

Likewise rotations around x and y can be constructed:同样,可以构造围绕 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

If you are not familiar with matrix-arithmetic, here is some code:如果你不熟悉矩阵算术,这里有一些代码:

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
}

Edit : Edited to support Java using Android SDK.编辑:编辑为使用 Android SDK 支持 Java。

As Tobias indicated, the idiomatic solution to any vertex transformation in OpenGL is accomplished through the use of matrix operations.正如 Tobias 所指出的,OpenGL 中任何顶点变换的惯用解决方案都是通过使用矩阵运算来完成的。 If you plan to continue developing with OpenGL, it is important that you (eventually) understand the underlying linear algebra involved in matrix operations, but it is often best to utilize a math library for abstracting linear algebra computation into a more readable format.如果您打算继续使用 OpenGL 进行开发,那么您(最终)了解矩阵运算中涉及的底层线性代数很重要,但通常最好利用数学库将线性代数计算抽象为更易读的格式。 Under the android environment, you should manipulate float arrays with the [matrix][1] class to create a rotation matrix like this:在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]);

Then you can bind the rotation Matrix to a shader program like this:然后你可以将旋转矩阵绑定到一个着色器程序,如下所示:

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

Where your vertex shader (of the program being passed rotationMat ) would look something like:你的顶点着色器(被传递的程序的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);
}

Alternatively, you could premultiply uMVPMatrix* uRotation outside of this shader program and pass the result to your shader program to avoid excessive duplicate computation.或者,您可以在此着色器程序之外预乘uMVPMatrix* uRotation ,并将结果传递给您的着色器程序,以避免过多的重复计算。

Once you are comfortable using this higher level API for matrix operations you can investigate how the internal operation is performed by reading this fantastic tutorial written by Nicol Bolas .一旦您习惯使用这个更高级别的 API 进行矩阵运算,您就可以通过阅读Nicol Bolas编写的这篇精彩的教程来研究内部运算是如何执行的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM