opengles(三) 相机和投影概念
来源:互联网 发布:部落冲突更新软件 编辑:程序博客网 时间:2024/06/02 05:21
透视投影和相机就是允许像你用眼睛看物体的方式绘制图像对象
由于转变调整坐标绘制的对象是基于他们在GLSurfaceView上显示的宽和高。没有这样的计算,被OpenGL ES 绘制的对象在不同分辨率的显示器上会是歪的,就像我们之前画的三角型一样。所以我们必须要把opengles坐标映射在手机屏幕上;
透视投影需要设置近平面的左、右、下、上的最大值和近平面、远平面的距离
具体做法就是把相关的矩阵与原来的三角型坐标向量进行相乘得到最终的向量坐标;
先定义透视投影(mProjectionMatrix)和相机(mViewMatrix)的矩阵数组:
private final float[] mMVPMatrix = new float[16]; private final float[] mProjectionMatrix = new float[16]; private final float[] mViewMatrix = new float[16];
再设置透视投影矩阵的值,这里要用到Matrix这个类的frustumM方法:
@Override public void onSurfaceChanged(GL10 gl, int width, int height) { GLES20.glViewport(0, 0, width, height); // 计算长和宽的比例,由于在OpenGLes坐标系里最大是1,具体的算法是: // x / width = 1 / height; // 所以 x = width /height; float ratio = (float) width / height;, Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7); }
在onDrawFrame中设置相机矩阵,同样用的是Matrix,最后把相乘后的矩阵传入:
@Override public void onDrawFrame(GL10 gl) { // 设置相机矩阵 Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0, 0, 0, 0, 1.0f, 0); // 透视投影矩阵与相机矩阵相乘,得到最后的矩阵mMVPMatrix Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); mTriangle.draw(mMVPMatrix); }
在vertex shader的source里添加矩阵与位置向量相乘的代码:
private static final String VERTEX_SHADER_SOURCE = "attribute vec4 vPosition;" + "uniform mat4 uMVPMatrix;" + "void main() {" + " gl_Position = uMVPMatrix * vPosition;" + "}";private static final String MATRIX_NAME = "uMVPMatrix";private int mPositionLocation, mFragColorLocation, mMatrixLocation;mMatrixLocation = GLES20.glGetUniformLocation(program, MATRIX_NAME);public void draw(float[] mvpMatrix) { GLES20.glUniformMatrix4fv(mMatrixLocation, 1, false, mvpMatrix, }
贴上全部的代码
public class MyRenderer implements GLSurfaceView.Renderer { private final float[] mMVPMatrix = new float[16]; private final float[] mProjectionMatrix = new float[16]; private final float[] mViewMatrix = new float[16]; private Triangle mTriangle; @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); mTriangle = new Triangle(); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { GLES20.glViewport(0, 0, width, height); float ratio = (float) width / height; Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7); } @Override public void onDrawFrame(GL10 gl) { Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0, 0, 0, 0, 1.0f, 0); Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); mTriangle.draw(mMVPMatrix); }}
public class Triangle { private static final String TAG = "Triangle"; // 三角形的三个顶点 private static final float[] TRIANGLE_VERTEX_COORD = {0, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f}; private static final int VERTEX_SIZE = 3; private static final int COORDS_PER_VERTEX = TRIANGLE_VERTEX_COORD.length / VERTEX_SIZE; private FloatBuffer mTriangleCoordBuffer; private static final String VERTEX_SHADER_SOURCE = "attribute vec4 vPosition;" + "uniform mat4 uMVPMatrix;" + "void main() {" + " gl_Position = uMVPMatrix * vPosition;" + "}"; private static final String FRAGMENT_SHADER_SOURCE = "uniform vec4 vColor;" + "void main() {" + " gl_FragColor = vColor;" + "}"; private int mVertexShader, mFragmentShader; private static final String POSITION_NAME = "vPosition"; private static final String COLOR_NAME = "vColor"; private static final String MATRIX_NAME = "uMVPMatrix"; private int mPositionLocation, mFragColorLocation, mMatrixLocation; public Triangle() { // 数组转化为buffer,提高opengles性能 mTriangleCoordBuffer = ByteBuffer.allocateDirect(TRIANGLE_VERTEX_COORD.length * 4) .order(ByteOrder.nativeOrder()).asFloatBuffer(); mTriangleCoordBuffer.put(TRIANGLE_VERTEX_COORD); // 设置从第一位开始读 mTriangleCoordBuffer.position(0); // 得到编译后的shader mVertexShader = getShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER_SOURCE); mFragmentShader = getShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE); // 创建并连接program int program = GLES20.glCreateProgram(); GLES20.glAttachShader(program, mVertexShader); GLES20.glAttachShader(program, mFragmentShader); GLES20.glLinkProgram(program); GLES20.glUseProgram(program); // 找到对应变量的index mPositionLocation = GLES20.glGetAttribLocation(program, POSITION_NAME); mFragColorLocation = GLES20.glGetUniformLocation(program, COLOR_NAME); mMatrixLocation = GLES20.glGetUniformLocation(program, MATRIX_NAME); } private int getShader(int type, String source) { int shader = GLES20.glCreateShader(type); GLES20.glShaderSource(shader, source); GLES20.glCompileShader(shader); // 获取编译的状态 final int[] compileStatus = new int[1]; GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0); Log.v(TAG, "代码编译结果:" + "\n" + source + "\n:" + GLES20.glGetShaderInfoLog(shader)); if (compileStatus[0] == 0) { Log.w(TAG, "编译失败!."); return 0; } return shader; } public void draw(float[] mvpMatrix) { // 由于性能方面的考虑,opengles默认读取不到缓冲区里的数据,需要先enable后再读 GLES20.glEnableVertexAttribArray(mPositionLocation); GLES20.glVertexAttribPointer(mPositionLocation, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, mTriangleCoordBuffer); GLES20.glUniformMatrix4fv(mMatrixLocation, 1, false, mvpMatrix, 0); GLES20.glUniform4f(mFragColorLocation, 0, 0.5f, 0, 1.0f); GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, VERTEX_SIZE); GLES20.glDisableVertexAttribArray(mPositionLocation); }}
最后的运行结果是:
阅读全文
0 0
- opengles(三) 相机和投影概念
- opengles 投影
- (4)应用投影和相机视口
- OpenGLES---模型/观察/投影矩阵
- opengles透视矩阵投影原理
- Android OpenGL ES2.0编程教程系列之投影和相机视图的应用(四)
- Applying Projection and Camera Views 运用投影和相机视图
- android openGL ES 20 投影、相机画等边三角形和正方形
- three.js中正交和透视投影相机的应用
- Camera Projection (相机投影)
- OpenGLES Android篇零基础系列(四):透视投影(PerspectiveProjection)与正射投影(OrthographicProjection)
- atitit.软件开发概念--过滤和投影 数据操作
- atitit.软件开发概念--过滤和投影 数据操作
- iOS中滤镜的使用(三)OpenGLES渲染
- OpenLayers 投影的概念
- Weblogic集群概念和配置(三)
- Weblogic集群概念和配置(三)
- 基于Android的OpenGL—在 GLSurfaceView上绘制三角形和使用投影和相机视图
- Go 中的 map 并发存取
- 基于Python语言使用RabbitMQ消息队列(六)
- opencv操作像素
- 使用GDB调试
- 淘淘商城第三天
- opengles(三) 相机和投影概念
- C语言共用体(Union)
- BufferedReader、LineNumberReader的作用与用法
- LeetCode (Reverse Linked List II)
- 关于dubbo理解
- hadoop window win10 基础环境搭建
- C++ Prime 之类类型转换(2)
- PHP性能优化
- 单页面多路由区域操作