前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android OpenGL ES(二)-正交投影

Android OpenGL ES(二)-正交投影

作者头像
deep_sadness
发布2018-08-30 10:55:36
1.5K0
发布2018-08-30 10:55:36
举报
文章被收录于专栏:Flutter入门Flutter入门Flutter入门

上文Android OpenGL ES(一)-开始描绘一个平面三角形中我们已经成功描绘了一个三角形。但是奇怪的是,按照我们的坐标。期望得到的应该是一个等腰三角形。但是最后的结果,确实一个扁平的三角形。

OpenGL ES世界的基本元素

着色器

坐标系。矩阵

纹理

...

本文主要涉及的部分是矩阵。

直接开始

我们先快速过一下矩阵的基础知识

矩阵基础知识

单位矩阵

单位矩阵.png

任何一个矩阵乘以单位矩阵,都依旧是器本身。

平移矩阵

平移矩阵.png

平移矩阵和单位矩阵和类似。但是向量x,y,z,1前乘这个平移矩阵后的结构就是平移矩阵中定义的偏移量。

这里需要注意的。第四个变量其实是w。而在OpenGL中,如果我们不去定义这个w。默认就是1.

OpenGL的坐标系

归一化设备坐标

我们之前定义的坐标系。是OpenGL中的坐标系。x,y,z都映射到了-1,1的范围内。这个范围内的坐标我们称之为归一化设备坐标。他是独立于屏幕实际的尺寸和形状的。

 private static float TRIANGLE_COORDS[] = {
            //Order of coordinates: X, Y, Z
            0.5f, 0.5f, 0.0f, // top
            -0.5f, -0.5f, 0.0f, // bottom left
            0.5f, -0.5f, 0.0f   // bottom right
    };

归一化设备坐标.png

但是显而易见的,我们的手机的宽高比,明显不可能是1:1。而我们设置视口(ViewPort)时,又使用了初始化传入的宽和高。

手机的宽高.png

设置viewport的代码

  @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        //在窗口改变的时候调用
        GLES20.glViewport(0,0,width,height);
    }
虚拟空间坐标系

我们应该停止直接在归一化坐标上工作,转而在虚拟空间坐标系中工作。 调整坐标空间。我们需要将虚拟空间坐标转换成归一化设备坐标,让OpenGL可以正确的渲染它们。 这种操作就是使用正交投影

正交立方体内的场景.png

一个正交投影.png

正交投影

正交投影其实可以当作是一个正视图。

我们可以调用这个方法来得到正交矩阵。

/ * float[] 目标数组。只要的有16个元素,才能存储正交投影矩阵
 * mOffset 结果矩阵起始的偏移量
 * left    x轴的最小范围
 * right   x轴的最大范围
 * bottom  y轴的最小范围
 * top     y轴的最大范围
 * near    z轴的最小范围
 * far     z轴的最大范围
**/
 Matrix.orthoM(mProjectionMatrix, 0, -aspectRatio, aspectRatio, -1, 1f, -1.f, 1f);

得到的矩阵如下图

正交投影矩阵.png

  • 和平移矩阵相似 回到开头我们复习的平移矩阵。是不是两者是否相似。 我们可以理解为,其实就是将坐标缩放和平移到我们的归一化坐标中。
  • 和平移矩阵不同 当时有一个地方不同的是z轴的正负。 原因是归一化的设备坐标系使用的是左手。而OpenGL使用的是右手。所以要转化成归一化坐标,就需要反过来。

代码实现

基于上一节的代码做下面的修改。

其实还是我们的上一节总结的套路。

着色器定义属性=>代码传递更新

我们需要着色器的代码中定义一个矩阵的常量。再将计算好的矩阵。传入其中

更新着色器的代码

在着色器中定义一个matrix,并与position相乘。

//定义一个matrix。相当于4x4的矩阵
uniform mat4 u_Matrix;
attribute vec4 a_Position;
void main() {
    //与position相乘
    gl_Position =u_Matrix* a_Position;
}
计算矩阵

onSurfaceChanged生命周期方法中,计算我们的投影矩阵。

   //投影矩阵
   private float[] mProjectionMatrix = new float[16];

   @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        super.onSurfaceChanged(gl, width, height);
        //主要还是长宽进行比例缩放
        float aspectRatio = width > height ?
                (float) width / (float) height :
                (float) height / (float) width;

        if (width > height) {
            //横屏。需要设置的就是左右。
            Matrix.orthoM(mProjectionMatrix, 0, -aspectRatio, aspectRatio, -1, 1f, -1.f, 1f);
        } else {
            //竖屏。需要设置的就是上下
            Matrix.orthoM(mProjectionMatrix, 0, -1, 1f, -aspectRatio, aspectRatio, -1.f, 1f);
        }
    }
激活属性。并传递值

在生命周期方法onDrawFrame中。

 @Override
    public void onDrawFrame(GL10 gl) {
        super.onDrawFrame(gl);

        //传递给着色器
        GLES20.glUniformMatrix4fv(uMatrix,1,false,mProjectionMatrix,0);

        //...
    }

结果

结果.png

和我们预想的结果一样。撒花~~

总结一下,我们从这这章节的内容了解到了下面这些使用的知识点:

  1. 矩阵的知识回顾
  2. 正交投影变换

但是我们现在还依然是平面的图。因为正交投影其实相当于正视图。

后面我们会先根据这章的内容画出其他图形。

然后再将其变成三维的样子。

整体的代码位置:https://github.com/deepsadness/OpenGLDemo5

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.05.05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • OpenGL ES世界的基本元素
  • 直接开始
    • 矩阵基础知识
      • OpenGL的坐标系
        • 归一化设备坐标
        • 虚拟空间坐标系
        • 正交投影
      • 代码实现
        • 更新着色器的代码
        • 计算矩阵
        • 激活属性。并传递值
      • 结果
      相关产品与服务
      对象存储
      对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档