Android OpenGL ES 学习(二) -- 图形渲染管线和GLSL

OpenGL 学习教程
Android OpenGL ES 学习(一) – 基本概念
Android OpenGL ES 学习(二) – 图形渲染管线和GLSL
Android OpenGL ES 学习(三) – 绘制平面图形
Android OpenGL ES 学习(四) – 正交投屏
Android OpenGL ES 学习(五) – 渐变色
Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序
Android OpenGL ES 学习(七) – 纹理
代码工程地址: https://github.com/LillteZheng/OpenGLDemo.git

上一章,我们学习了 OpenGL 的基本知识,这一章,一起学习OpenGL的渲染模式和渲染语言GLSL。
很多人跟我一样,学习 OpenGL 的时候,最痛苦的就是,着色器是怎么传递给 OpenGL 的?为啥要这样写,虽然照着 demo 写了,但是不知道为啥这样写。
因此,理解 OpenGL 的渲染管线,是非常重要的事情,因此,这一章,可以重点看,也需要你自行搜索资料一起看,毕竟我只是基于我的理解。

一. 图形渲染管线

在 OpenGL 中,任何食物都是在 3D 空间中的,而屏幕和窗口却是 2D 像素数组,而 3D 坐标转为 2D 的处理过程,则由 GL 的图形渲染管线(Graphics Pipeline ) 负责,实际上指的是一堆原始图形数据经过各种处理,最终出现在屏幕的过程。图形渲染管道有两个主要部分:

  1. 把 3D 坐标转换成 2D 坐标
  2. 把 2D 坐标转变成实际的有颜色的像素。

从 3D 坐标到转成 2D 有色的 2D 数据,管线会划分几个阶段,每个阶段都会把前一段的输出作为输入,这些阶段都是一些特定的函数,他们能在 GPU 上各自运行,从而快速处理你的数据,这些特定函数也叫着色器。

1.1. 渲染流程

刚才说道,从数据再到屏幕的有色像素,是由一个个着色器程序完成的,而 GL 中,有些是系统配置好的,而有些则可以由开发者去配置,从而实现高度配置化。如下图,蓝色部分是可以自己配置的:
在这里插入图片描述
从这里看出,OpenGL 需要使用顶点着色器,先绘制好轮廓,再通过图元装配,将顶点转换成图元,然后通过光栅化,将图片这种矢量图形,转成为栅格化数据,最后,使用片段着色器,将光栅化的数据,每一个像素进行运算,并绘制上对应的颜色,然后再展示到屏幕中。而我们可以配置的是:

  • 顶点着色器
  • 几何着色器 (可选,后面再学习这个)
  • 片段着色器
    现在是不是解惑了,为啥一般只需要写顶点着色器和片段着色器了。
    所以我们开发的重点,需要重点关注,顶点着色器,片段着色器,将数据传递到着色器上这三个重点就可以了。

1.2. 基本概念

  • 顶点:一个顶点(Vertex)是一个3D坐标的数据的集合,它包含坐标,颜色等数据;其中坐标在 GL 是3个分量的,但是为什么有 vec4 4个分量呢?是因为它为了进行缩放,平移等图形变换,这里等学习图形变换再细讲。
  • 顶点着色器:对顶点数据进行一系列操作的程序。
  • 图元片段: OpenGL ES 只有三种图元,点、线,三角形,它会把顶点数据数据计算成一个个图元,在这个阶段会进行裁减,透视分割和其他变换操作。
  • 几何着色器:几何着色器把图元形式的一系列顶点的集合作为输入,它可以通过产生新顶点构造出新的(或是其它的)图元来生成其他形状,比如点,线,三角形。
  • 光栅化:把图元映射为最终屏幕上相应的像素,生成供片段着色器(Fragment Shader)使用的片段(Fragment)
    • 片段着色器:主要目的是计算一个像素的最终颜色。
  • 测试和混合:检测片段的对应的深度(和模板(Stencil))值(后面会讲),用它们来判断这个像素是其它物体的前面还是后面,决定是否应该丢弃。

二. 坐标

与 Android 左边西不同,GL 的其实位置是在屏幕的中心,以(0,0)为中心店,x 坐标从做到有,y 从下到上,在 [-1,1] 之前取值,再映射到屏幕,而超出 [-1,1] 之外的,不会在屏幕上显示。如下图:

在这里插入图片描述

四. GLSL 语言

GLSL (OpenGL Shading Language)是着色器程序的编程语言,该程序会在 GPU 上执行,使得渲染管线具有可编程性。这里,你可以先简单浏览,等在编写 GLSL 的语言的时候,再来看一下。

4.1 GLSL 特有语法

GLSL 与 C 语言而非常相似,有基本的类型、函数、结构体,但没有指针;当然也有自己的一些特殊类型。

4.1.1 基本类型

在计算机图形中,向量和矩阵是变换的基础,这两种数据类型也是 GLSL 的核心,它的基本类型如下:

  • 浮点向量:vec2 ,vec3 ,vec4
  • 整数向量:ivec2 ,ivec3 ,ivec4
  • 无符号整型向量:uvec2 ,uvec3 ,uvec4
  • boolean向量:bvec2 ,bvec3 ,bvec4
  • 浮点矩阵:mat2,mat3,mat4,mat2x3…
  • 二维纹理句柄:sampler2D
4.1.2 修饰符

2.0 版本

  • const:(只读) 常量变量
  • attribute:只能用于顶点着色器,用于经常更改的信息
  • uniform: (始终如一的)用于不经常更改的信息,可用于顶点和片元着色器
  • varying:(易变的)用于修饰从顶点着色器向片元着色器传递变量。
    更多的解释,可以参考:https://zhuanlan.zhihu.com/p/52807564

3.0版本
在3.0版本,去掉了 attribute 和 varying,使用 in 和 out 和表示输入和输出。为了更好的关管理着色器的顶点数据,会使用 location 这一元数据指定输入变量,比如 layout(location = 0) 表示当前变量index为0的顶点数据,后面使用也是根据 index 。
例如:

4.2 内置变量

OpenGL 中,有几个内置变量,最常见的是在顶点着色器和片段着色器中

  • 顶点着色器(Vectex Shader):gl_position(位置) 和 gl_pointSize (大小)
  • 片段着色器(Fragment Shader):gl_FragColor (颜色值) < 3.0之后删除 >

更多3.0 和 2.0 的区别,参考 https://blog.csdn.net/afei__/article/details/88859449

4.3 函数和内置函数

GLSL 的函数使用,与 C 语言基本一直,在定义函数之前先申明类型。不同之处,在于 GLSL 在函数参数上提供了特殊的限定符(修饰符),这个跟 aidl 有点像,如:

  • in:默认模式,相当于传入参数只是 in 实参的一份拷贝,修改的值不会影响 in 参数本身,相当于java的 get
  • out:相当于 wirte-only,可写不可读,相当于 java 的set方法
  • inpuot:可读可写模式,直接改到实参,可以理解有 get 和set 方法。

GLSL 提供内置函数还是挺方便的,常见的有:

  • abs:绝对值
  • floor:向下取整
  • ceil:向上取整
  • mod:取模
  • min:最小
  • max:最大
  • clamp:中间值
  • dot:计算两个向量的点积
  • pow:计算标量的幂次

4.4 GLSL 编写工具

在 Android studio 中,下载 GLSL 的插件,就可以编写后,再拷贝到着色器代码了,有代码提示真的很不错:
在这里插入图片描述

OpenGL 的渲染框架

接下来,看看 GLSL 是如何把 着色器的值传递给 OpenGL 的渲染管线的,如下图:
在这里插入图片描述
从上面可以看到,管线可以分为 client 和 server:

Client:
这里是我们赋予着色器参数的动态值,以及调用的 OpenGL api ,这里指我们的程序代码。

Server:
Server 是整个渲染的核心,它运行再 GPU,Client 和 Server 只能通过 Attributes ,Uniforms 等类型通信。然后再通过着色器 Shader 将数据绘制渲染出来。

参考:
https://mp.weixin.qq.com/s?__biz=MzU5NjkxMjE5Mg==&mid=2247483771&idx=1&sn=9b122a361188aa4cc0d75549be0ee4a4&chksm=fe5a3054c92db942d350306739c2c775c95d107b8f2a213d6ddc9cbc5c042c702dc1d36c3581&scene=21#wechat_redirect
https://www.jianshu.com/p/48c52f862f42
https://www.jianshu.com/p/a818684333f2
https://zhuanlan.zhihu.com/p/52807564

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值