OpenGL ES Android 矩阵变换 [英] OpenGL ES Android Matrix Transformations
问题描述
我有一个实现 GLSurfaceView.Renderer 接口的渲染器;GLSurfaceView 的子类和一些代表我要绘制的对象的类.我有来自 http://developer.android.com/training/graphics/的代码opengl/motion.html我想扩展它并添加一些沿轴移动并且无法管理它.对象仅旋转.这是我的代码:
I have a renderer implementing GLSurfaceView.Renderer interface; a subclass of GLSurfaceView and some classes representing my objects I want to draw. I have the code from http://developer.android.com/training/graphics/opengl/motion.html I want to expand this and add some moving along axes and can't manage it. The object is only rotated. and here is my code:
public class NotMyCoolRenderer implements GLSurfaceView.Renderer {
public GLShip mTriangle;
private GLBackgroundStar mSquare;
private final float[] mMVPMatrix = new float[16];
private final float[] mProjMatrix = new float[16];
private final float[] mVMatrix = new float[16];
private final float[] mModelMatrix = new float[16];
private final float[] tempMatrix = new float[16];
public void onDrawFrame(GL10 unused) {
// Draw background color
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);
// Draw square
mSquare.draw(mMVPMatrix);
// Now moving on to triangle aka ship
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, 0.1f, 0f, 0);
Matrix.rotateM(mModelMatrix, 0, mTriangle.mAngle, 0, 0, -1.0f);
Matrix.multiplyMM(tempMatrix, 0, mVMatrix, 0, mProjMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mModelMatrix , 0, tempMatrix , 0);
// Draw triangle
mTriangle.draw(mMVPMatrix);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
// Adjust the viewport based on geometry changes,
// such as screen rotation
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
public class GLShip {
public volatile float mAngle;
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
" gl_Position = uMVPMatrix * vPosition;" +
"}";
public void draw(float[] mvpMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
NotMyCoolRenderer.checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
NotMyCoolRenderer.checkGlError("glUniformMatrix4fv");
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
我的期望是,在每次重绘时,对象将旋转 mAngle 并沿 Y 轴平移 1f.我只能看到旋转(也有点投影).我实际上对此有一些疑问:如何应用我的翻译矩阵和划分opengl功能的最佳实践是什么?modelMatrix 不应该存储在对象本身而不是渲染器中吗?矩阵运算应该在渲染器类中执行吗?我将它们归为一组,因为我猜它们都是相关的.
My expectations are that on each redrawing the object would be rotated by mAngle and traslated along Y-Axis by 1f. I can see only rotating (a bit projected too) though. I actually got some questions regarding that: how do I apply my translation matrix and what is the best practice of dividing the opengl functionality? Should not the modelMatrix be stored in the object itself rather than in renderer? Should the matrix operations be performed in the renderer-class? I have grouped them together since I guess that they are all related.
推荐答案
我一直在使用 Android 培训中的示例,以下方法终于适用于我.(基于 Android 培训 > 使用 OpenGL ES 显示图形 > 添加运动)
I´ve been working with the example from the Android Training, the following approach finally works for me. (Based on Android Training > Displaying Graphics with OpenGL ES > Adding Motion)
使用正确的顶点着色器:
Use the correct vertex shader:
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
" gl_Position = uMVPMatrix * vPosition;" +
"}";
在渲染器类中:
In the renderer class:
public class MyGL20Renderer implements GLSurfaceView.Renderer {
[...]
// create a model matrix for the triangle
private final float[] mModelMatrix = new float[16];
// create a temporary matrix for calculation purposes,
// to avoid the same matrix on the right and left side of multiplyMM later
// see https://stackoverflow.com/questions/13480043/opengl-es-android-matrix-transformations#comment18443759_13480364
private float[] mTempMatrix = new float[16];
[...]
在onDrawFrame中应用变换,从translation开始:
public void onDrawFrame(GL10 unused) {
[...]
Matrix.setIdentityM(mModelMatrix, 0); // initialize to identity matrix
Matrix.translateM(mModelMatrix, 0, -0.5f, 0, 0); // translation to the left
然后旋转:
// Create a rotation transformation for the triangle
long time = SystemClock.uptimeMillis() % 4000L;
float mAngle = 0.090f * ((int) time);
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);
结合旋转和平移,避免使用mModelMatrix
作为multiplyMM左右两边的同一个矩阵"(见2)
"as the same matrix on the right and left side of multiplyMM" (see 2)
// Combine Rotation and Translation matrices
mTempMatrix = mModelMatrix.clone();
Matrix.multiplyMM(mModelMatrix, 0, mTempMatrix, 0, mRotationMatrix, 0);
将模型矩阵与投影和相机视图结合起来;再次避免使用 mModelMatrix
作为multiplyMM左右两边的同一个矩阵"(见2)
"as the same matrix on the right and left side of multiplyMM" (see 2)
// Combine the model matrix with the projection and camera view
mTempMatrix = mMVPMatrix.clone();
Matrix.multiplyMM(mMVPMatrix, 0, mTempMatrix, 0, mModelMatrix, 0);
画出形状
Draw the shape
// Draw shape
mTriangle.draw(mMVPMatrix);
谢谢大家,感谢我从这个帖子中获得的所有有用的意见.
Thank you all, for all the useful input I could draw from this thread.
这篇关于OpenGL ES Android 矩阵变换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!