Android OpenGL ES(二)-正交投影

上文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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏mwangblog

整数的存储:符号加绝对值表示法

1282
来自专栏bboysoul

1475: C语言实验题――一元二次方程 II

描述:求一元二次方程ax2+bx+c=0的解。a,b,c为任意实数。 输入:输入数据有一行,包括a b c的值 输出:按以下格式输出方程的根x1和x2。x1...

1253
来自专栏小樱的经验随笔

hihoCoder #1142 : 三分求极值

#1142 : 三分·三分求极值 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: ? 在直...

3509
来自专栏计算机视觉与深度学习基础

POJ2836

状压DP死活想不到啊,开始还以为是数据结构题,真是膜拜宋威大大。 包括点的矩形最小一定以这些点为顶点,所以枚举所有点对,构成所有状态。 由于不存在面积为0的矩形...

19910
来自专栏云霄雨霁

子字符串查找----各种算法总结

2450
来自专栏移动开发面面观

OpenGL ES——导入.stl格式的3D模型

2154
来自专栏数据结构与算法

BZOJ4517: [Sdoi2016]排列计数(组合数+错位排列)

Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 的值为 i,则称 ...

2947
来自专栏Phoenix的Android之旅

一张图看懂开发和运营的思维差别

用Dijkstra算法很简单,我们需要 · 用 6*6矩阵 source[6][6]表示点之间的距离,也就是图中的权值 · 自己与自己的距离为0,无直接连接的距...

801
来自专栏机器学习原理

我的机器学习numpy篇何为ndarray?ndarry创建生成正态分布ndarry属性修改形状ndarry运算ndarry切片矩阵转置聚合函数

前言: numpy是以矩阵为基础的数学计算模块,其基础为多维数组为ndarray 官方文档:(https://docs.scipy.org/doc/nump...

3978
来自专栏ml

nyoj-----幸运三角形

幸运三角形 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述         话说有这么一个图形,只有两种符号组成(‘+’或者‘-’...

30410

扫码关注云+社区

领取腾讯云代金券