Android OpenGL ES 入门系列(五) --- 应用投影和相机视角
2018-01-20 21:05
711 查看
转载请注明出处
本文出自Hansion的博客
本章介绍如何创建投影和相机视图,并应用于GLSurfaceView中绘制的形状上。
在OpenGL ES环境中,利用投影和相机视角可以让绘制对象的显示更接近人眼看到的样子,这是一种视角模拟,它是通过对绘制对象坐标进行数学变换实现的。
投影(Projection):基于GLSurfaceView 的宽和高来调整绘制对象的坐标。如果没有该计算,绘制对象和GLSurfaceView的宽高比例不同,就会发生变形。投影转换通常只在OpenGL View的比例刚被建立或改变onSurfaceChanged()中计算
相机视角(Camera View):基于虚拟相机的位置调整绘制对象的坐标。而实际上OpenGL ES并没有定义相机对象,它是提供了一些方法通过转换绘制对象的显示来模拟相机视角。
投影变换的数据是在 GLSurfaceView.Renderer 类的 onSurfaceChanged() 方法中计算出来的。
以下代码首先获取到GLSurfaceView的宽高,并使用Matrix.frustumM()方法填充一个投影变换矩阵
public class MyGLRenderer implements GLSurfaceView.Renderer {
...
// 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 gl10, int width, int height) {
//glViewport用于告诉OpenGL应把渲染之后的图形绘制在窗体的哪个部位、大小
GLES20.glViewport(0, 0, width, height);
//计算宽高比
float ratio = (float) width / height;
//填充投影矩阵 mProjectionMatrix
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
...
}
对绘制对象仅使用投影变换,往往会导致看不到显示的东西,所以还需进行相机视角转换使绘制对象显示在屏幕上。
下面的代码在 onDrawFrame()方法中使用 Matrix.setLookAtM() 方法计算相机视角变换,再与之前计算的投影矩阵结合起来,然后将组合后的变换矩阵传递给绘制对象:
@Override
public void onDrawFrame(GL10 gl10) {
// glClear表示清除缓冲 传入GL_COLOR_BUFFER_BIT指要清除颜色缓冲
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// 设置相机视角
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// 计算投影和视图变换
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
// 绘制形状
mTriangle.draw(mMVPMatrix);
}
我们在Triangle中之前定义的顶点着色器vertexShaderCode中增加一个变量uMVPMatrix
然后修改draw方法,使其能接收组合后的变换矩阵,并应用于绘制对象上:
此时就是按着正确的比例显示图形了。
参考:
OpenGL
ES 2.0官方实例教程
本文出自Hansion的博客
本章介绍如何创建投影和相机视图,并应用于GLSurfaceView中绘制的形状上。
在OpenGL ES环境中,利用投影和相机视角可以让绘制对象的显示更接近人眼看到的样子,这是一种视角模拟,它是通过对绘制对象坐标进行数学变换实现的。
投影(Projection):基于GLSurfaceView 的宽和高来调整绘制对象的坐标。如果没有该计算,绘制对象和GLSurfaceView的宽高比例不同,就会发生变形。投影转换通常只在OpenGL View的比例刚被建立或改变onSurfaceChanged()中计算
相机视角(Camera View):基于虚拟相机的位置调整绘制对象的坐标。而实际上OpenGL ES并没有定义相机对象,它是提供了一些方法通过转换绘制对象的显示来模拟相机视角。
定义一个投影
投影变换的数据是在 GLSurfaceView.Renderer 类的 onSurfaceChanged() 方法中计算出来的。以下代码首先获取到GLSurfaceView的宽高,并使用Matrix.frustumM()方法填充一个投影变换矩阵
public class MyGLRenderer implements GLSurfaceView.Renderer {
...
// 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 gl10, int width, int height) {
//glViewport用于告诉OpenGL应把渲染之后的图形绘制在窗体的哪个部位、大小
GLES20.glViewport(0, 0, width, height);
//计算宽高比
float ratio = (float) width / height;
//填充投影矩阵 mProjectionMatrix
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
...
}
对绘制对象仅使用投影变换,往往会导致看不到显示的东西,所以还需进行相机视角转换使绘制对象显示在屏幕上。
定义一个相机视角
下面的代码在 onDrawFrame()方法中使用 Matrix.setLookAtM() 方法计算相机视角变换,再与之前计算的投影矩阵结合起来,然后将组合后的变换矩阵传递给绘制对象:@Override
public void onDrawFrame(GL10 gl10) {
// glClear表示清除缓冲 传入GL_COLOR_BUFFER_BIT指要清除颜色缓冲
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// 设置相机视角
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// 计算投影和视图变换
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
// 绘制形状
mTriangle.draw(mMVPMatrix);
}
应用投影和相机视角转换
我们在Triangle中之前定义的顶点着色器vertexShaderCode中增加一个变量uMVPMatrix然后修改draw方法,使其能接收组合后的变换矩阵,并应用于绘制对象上:
public class Triangle { //顶点着色器 private final String vertexShaderCode = "uniform mat4 uMVPMatrix;" + "attribute vec4 vPosition;" + "void main() {" + " gl_Position = uMVPMatrix * vPosition;" + "}"; // 用于访问和设置视图转换 private int mMVPMatrixHandle; ... public void draw(float[] mvpMatrix) { ... // 获取片元着色器的vColor成员 mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); // 得到绘制对象的变换矩阵句柄 mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); // 将投影和视图转换传递给着色器 GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); // 设置绘制颜色 GLES20.glUniform4fv(mColorHandle, 1, color, 0); // 绘制形状 GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount); // 禁用顶点属性数组 GLES20.glDisableVertexAttribArray(mPositionHandle); } }
运行结果
此时就是按着正确的比例显示图形了。
参考:
OpenGL
ES 2.0官方实例教程
相关文章推荐
- Android OpenGL ES2.0编程教程系列之投影和相机视图的应用(四)
- Android官方开发文档Training系列课程中文版:OpenGL绘图之应用投影与相机视图
- 使用Android OpenGL ES 2.0绘图之四:应用投影和相机视口
- 使用Android OpenGL ES 2.0绘图之四:应用投影和相机视口
- OpenGL ES系列四--相机、视景体、投影之间的关系
- Android Training - 使用OpenGL ES(4) - 应用投影和摄像视图
- Android OpenGL ES 入门系列(三) --- 定义形状
- Android---OpenGL ES之应用投影和摄像机视图
- OpenGL ES 入门 (三) 投影—— 译自《Beginning Android Games》
- Android OpenGL ES 入门系列(一) --- 了解OpenGL ES的前世今生
- Android OpenGL ES 入门系列(四) --- 绘制形状
- Android应用开发Camera系列(一):SurfaceView实现相机预览demo--新手上路
- Android OpenGL ES 入门系列(七) --- 响应触摸事件
- 【Android应用开发】 OpenGL ES -- 透视投影 和 正交投影
- Android OpenGL ES 开发(五): OpenGL ES 使用投影和相机视图
- 【Android应用开发】 OpenGL ES -- 透视投影 和 正交投影
- Android OpenGL ES 入门系列(六) --- 为绘制对象添加动作
- 【Android Developers Training】 65. 应用投影和相机视图
- Android官方开发文档Training系列课程中文版:构建第一款安卓应用之入门指南
- Android OpenGL ES绘图教程之四 :投影和相机视图变换