在OpenGL ES环境中,投影和camera views允许你以一种更像用眼睛去看实际物体的方式来绘制对象。这种物理视觉模拟是通过对被绘制的对象的数学转换来完成的。
- 投影——这个转换基于GLSurfaceView的width和height来调整被绘制的对象的坐标。没有这个计算,被OpenGL ES绘制的对象会因为view的width和height的比例不相等而被扭曲。一个投影的转换需要在对OpenGL view进行建立或改变的renderer的onSurfaceChanged()方法中来计算。需要更多的OpenGL ES投影的信息,请参阅Mapiing Coordinates for Drawn Objects
- Camera View——这个转换将被绘制的对象的坐标根据一个虚拟的摄像机位置来进行调整。需要注意OpenGL ES没有定义一个真正地camera对象,但是提供来静态方法来通过改变被绘制的对象来模拟一个摄像机。一个camera view转换可能只会在创建你的GLSurfaceView的时候被计算一次,也可能随着用户行为或应用功能而动态改变。
这节课描述了怎么创建一个投影和camera view并将它们应用到你的图形绘制中。
投影转换的数据在你的GLSurfaceView.Renderer类中的onSurfaceChanged()方法中被计算。下面的代码获得了GLSurfaceView的width和height,然后使用它来构造一个投影转换Matrix(矩阵),使用Matrix.frustimM()方法:
// mMVPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
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(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
这段代码构建了一个投影矩阵mProjectionMatrix,你可以在onDrawFrame()方法中结合它和camera view进行转换。
注意:对绘制的对象只进行投影转换通常会导致非常空的显示。通常,你同时需要使用camera view转换来在屏幕上进行显示。
添加一个camera view转换作为renderer的绘制过程的一部分可以完整被绘制的对象的转换。在下面的示例代码中,camere view转换使用Matrix.setLookAtM()来计算然后和之前计算的投影矩阵来结合。然后结合的转换矩阵被传递给被绘制的图形。
public void onDrawFrame(GL10 unused) {
...
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
// Draw shape
mTriangle.draw(mMVPMatrix);
}
为了使用最终的矩阵,首先为之前定义的Triangle类中的顶点着色器添加一个matrix变量。
public class Triangle {
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
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
" gl_Position = uMVPMatrix * vPosition;" +
"}";
// Use to access and set the view transformation
private int mMVPMatrixHandle;
...
}
下一步,修改draw()方法来接受矩阵参数然后使用它。
public void draw(float[] mvpMatrix) { // pass in the calculated transformation matrix
...
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// Pass the projection and view transformation to the shader
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
在你正确地计算和应用投影和camera view转换之后,你的图像对象会被一个正确的比例绘制。
现在你已经有了一个在正确的比例显示形状的应用,是时候为你的图形添加动作了。