OpenGL ES|应用投影和相机视角
在OpenGL ES环境中,投影和相机视角允许你以接近人眼观察物体类似的效果来绘制图形,这种类似物理视角的效果通过物体坐标系的数学变换来实现.
投影-这种变换通过调整基于GLSurfaceView的宽高的绘制对象的坐标.如果没有计算和变换,通过OpenGL ES绘制的对象因为与视图窗口比例不同而发生变形.当OpenGL视图被创建或者在OnSurfaceChanged()被renderer调用而改变时,投影变换会被计算.更多关于OpenGL ES 投影和坐标映射关系的资料,请看: Mapping coordinates for drawn objects.
相机视角-这种变换通过一个虚拟的相机位置来调整绘制物体的坐标.需要重点指出是OpenGL ES 并没有提供一个真正的相机对象,而是通过提供公共方法通过变换绘制对象来提供类似相机的模拟效果.相机视角变换只会在GLSurfaceView创建的时候计算一次,或者因为用户动作或者程序功能而动态 的改变.
这一课讲解了如何创建投影和相机视角并把他们应用到GLSurfaceView中的图形中去.
定义投影
投影变换的数据是在GLSurfaceView.Renderer类的OnSurfaceChanged()方法中被计算出来的.下面的示例代码使用GLSurfaceView的宽和高,并通过调用Matrix.frustumM()方法填充投影变换矩阵:
// 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 能够与相机视角变换组合,这个知识点会在下一课中讲解.
注意:仅仅只是对绘制对象应用投影变换的结果是什么也展示不了,通常,为了在屏幕上显示任何图形,你还必须应用相机视角变换.
定义相机视角
完成给绘制对象添加相机视角变换的过程只是在renderer中绘制流程的一部分.在下面的代码示例中,通过使用Matrix.setLookAtM()来计算相机视角变换,然后将它与之前的投影矩阵组合起来,组合起来的变换矩阵被传递给绘制图形:
@Override
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);
}
为了使用上面的投影矩阵和相机视角变换组合的矩阵,首先:把matrix变量添加到之前定义 Triangle中的顶点着色器:
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);
}
一旦你正确计算并应用投影和相机视角变换,你的图形会按正确的比例绘制,看起来像这样:
现在,你的应用已经能能按正确比例展示图形,是时候给你的图形动起来!
下一篇:OpenGL ES|添加动画