OpenGl ES 2.0 Learn For Android(三)初探三维的世界

OpenGl ES 2.0 Learn For Android(三)初探三维的世界

哈哈,昨天冬至,加班,然后告白被拒,新工作年度述职结束。现在窗外下着雨。新的一年马上到了,希望会有更好的开始。切勿悲喜过更甚,人生何处不相逢。

之前的话,介绍了OpenGL ES的顶点着色器,片段着色器,世界的坐标系,纹理。今天的话,会来讲三维的世界。

前三篇的内容在这里。
OpenGl ES 2.0 Learn For Android
OpenGl ES 2.0 Learn For Android(一)世界是三角形的
OpenGl ES 2.0 Learn For Android(二)给三角形贴上图片

1. 三维世界

先来聊聊opengl的透视除法。之前讲到,三维的世界里,照理说,三维向量(x,y,z)就足够了,但是opengl里面常用的四维向量(x,y,z,w)。这是因为,我们的视野里能看到三维的世界,是眼睛会对世界进行映射,有远近的概念。但是手机屏幕是二维的,它本身没有办法直接绘制一个三维的世界。那么,艺术家们是如何在平面上画出三维的图,让眼睛产生三维的错觉的呢?

美术里,有一个消失点(或者灭点)的概念。也就是,事物在视角里产生的直线,在远处会相交于一点。这个读者有兴趣可以再看。

如果我把屏幕中央的点作为消失点。那么在同一线段上的点,如果离我们的距离越远,就会离屏幕中心越近。


绘图技巧-消失点

opengl里的绘图技巧也是如此。它讲三维世界里的每个坐标,都除以w分量。w分量越大,也就是说离视角越远。从而达到在平面上展现三维世界的效果。我们前三篇,一直在讲归一化坐标系。说道世界都在[-1,1]里面。那么,三维坐标系里的物体,要显示出来,需要进行以下步骤。


opengl坐标系变换

简单的理解的话,透视除法就是把三维坐标除以w分量,映射到[-1,1]的世界里。所以(x,y,z)的取值需要在[-w,w]里。视口变换,就是[-1,1]里的坐标画到我们物理屏幕上。这个都不用我们操心,glViewport会自动帮我们做好这个事情。

2. 透视投影和视锥体###

这边的话,涉及一些线性代数的事情。原谅我吧,我虽然有些印象,但是想了想,还是不能很好的描述。我想其中需要抓住的关键点:
1.投影。
2.单向平移(这个是矩阵乘法最简单的一项了)
3.矩阵左乘和右乘
4.视锥体的概念
5.然后有兴趣,或者数学知识还记得比较清楚,可以看看的frustumM推导方法。
我贴两篇我觉得比较合适的博客:
1.OpenGLES Android篇零基础系列(四):透视投影(PerspectiveProjection)与正射投影(OrthographicProjection)
2.正交投影与变换
2.透视投影详解
其实我也看不很懂了,但是不影响我们直接使用接口。所以,不是很需要强求。主要还是动手,边动手边理解。

3. 旋转一个三角形###

链接的过程就不再重复。我们还是从一个最简单的三角形开始。相较第一篇的顶点着色器,我们只多加一个参数u_Matrix,一个四阶的矩阵。
废话不多说,直接贴代码。

    uniform mat4 u_Matrix;
    attribute vec4 a_Position;
    void main()
    { 
        gl_Position =  u_Matrix * a_Position;
    }

画三角形的方法不变,矩阵的赋值方式为

     // Assign the matrix
     glUniformMatrix4fv(uMatrixLocation, 1, false, mMVPMatrix, 0);

这边mMVPMatrix就是通过定义好视锥体,然后对物体进行平移,旋转得到的。

      //定义视锥体
      Matrix.perspectiveM(projectionMatrix, 0,45, (float) width / (float) height,  1f,10f);
      //物体的平移旋转的矩阵
      setIdentityM(modelMatrix, 0);
      //平移
      translateM(modelMatrix, 0, 0f, 0f, -2.5f);
      //旋转注释掉了,大家可以打开玩看效果
//        rotateM(modelMatrix, 0, -60f, 1f, 0f, 0f);
//        rotateM(modelMatrix, 0, -60f, 0f, 0f, 1f);
      //将视锥体和平移旋转的变换操作都放到结果mMVPMatrix中
      multiplyMM(mMVPMatrix, 0, projectionMatrix, 0, modelMatrix, 0);

方法操作我也贴两个博客:
1.OpenGL 矩阵变换
2.Android OpenGL20 setIdentityM,translateM,rotateM,multiplyMV等方法
看的时候难免一头雾水,跑过代码玩过之后就好理解了。

4. 效果图###

这个主要靠大家自己玩自己试。这边贴一个不旋转和x轴旋转60度的效果图对比一下。


不旋转

x轴旋转60度

demo地址:
https://github.com/YueZhiFengMing/LearnOpenGl/tree/master/Fourth3D

参考资料###

  1. 《OpenGL ES应用开发实践指南:Android卷》
  2. OpenGLES Android篇零基础系列(四):透视投影(PerspectiveProjection)与正射投影(OrthographicProjection)
  3. 正交投影与变换
  4. 透视投影详解
  5. OpenGL 矩阵变换
  6. Android OpenGL20 setIdentityM,translateM,rotateM,multiplyMV等方法

你可能感兴趣的:(OpenGl ES 2.0 Learn For Android(三)初探三维的世界)