【OpenGL ES】渲染管线

article/2025/7/23 19:42:43

1 前言

        渲染管线是指图形渲染流程,涉及到的概念非常多,主要包含图元、片段、光栅化、空间、变换、裁剪、着色器、片段测试、混合等。渲染管线主体流程如下:

        为方便读者理解渲染管线,本文将先介绍顶点数据、图元与片段、空间与变换、着色器等渲染管线基础概念,再介绍渲染管线、片段测试、混合等内容。

2 顶点数据

        模型的顶点数据主要属性有位置坐标、纹理坐标、法线向量、颜色等,OpenGL ES 接收的顶点序列是按照图元类型有序组织的,通过 glVertexAttribPointer 函数输入顶点数据,如下:

void glVertexAttribPointer(int index, // 顶点属性的索引值, 如: 位置属性索引为0, 颜色属性索引为1int size, // 每个顶点在待设置属性下的数组大小, 如: 位置用三维坐标表示, 则size为3; 颜色用rgba表示, 则size为4int type, // 顶点属性的数据类型, 如: GLES30.GL_FLOATboolean normalized, // 当被访问时, 固定点数据值是否应该被归一化int stride, // 连续顶点属性之间的偏移量, 0表示紧密排列在一起的Buffer pointer // 顶点属性序列
)

3 图元与片段

        三维空间中的物体,都由点线面构成。由于三点共面(四点不一定共面),因此组成面的最小元素是三角形,如下是 Unity3D 中的标准模型,可以看到这些模型都是由一系列三角形网格构成。

  • 图元:组成模型的基本元素称为图元,主要有点、线、三角形;
  • 片段:图元经插值,使其内部与屏幕中的像素点一一对应,映射后的像素点的集合称为片段;
  • 光栅化:由图元经插值得到片段的过程称为光栅化;

        对于线段类型图元,输入顶点序列 abcdef,根据图元类型,组装成的线段如下:

         对于三角形类型图元,输入顶点序列 abcdef,根据图元类型,组装成的三角形如下:

         图元使用详见 →绘制三角形。 

4 空间与变换

        如下图,近平面远平面间棱台称为视锥体,表示可见区域范围,视锥体以外的空间将被裁剪丢弃,视锥体内的模型通过透视变换投影到近平面上,近平面上得到的平面图形就是屏幕上要显示的模型的图形。 

         空间及变换如下,MVP矩阵变换详见→MVP矩阵变换,透视变换详见→透视变换原理。

        1)空间

  • 模型空间:模型的出厂空间,为方便建模使用的局部空间,一般以模型的中心为原点;
  • 世界空间:场景空间,为方便摆放各个模型的位置及朝向而定义的全局空间,一般以场景中心为原点;
  • 观察空间:以相机位置为原点的世界空间;
  • 裁剪空间:进行透视分割,并剔除视锥体外面的顶点,根据 x, y, z 的值是否在 [-1, 1] 之间判断是否淘汰顶点;
  • 设备空间:近平面空间,以近平面中心为原点,值域:[-1, 1];
  • 屏幕空间:以屏幕左上角为原点。

        2)变换

  • 模型变换:对模型施加的变换,主要包含平移、旋转、缩放变换;
  • 观察变换:对坐标轴施加的变换,坐标轴由一组基向量变换到另一组基向量上,属于相似变换+平移变换;
  • 投影变换:投影分为正交投影和透视投影,透视投影需要经过透视变换透视分割两个步骤(透视变换原理);
  • 透视分割:也叫透视除法,将 [x, y, z, w] 映射到 [x/w, y/w, z/w, 1];
  • 视口变换:根据视口(Viewport)大小,将近平面上的点映射到屏幕上,属于缩放变换。

5 着色器

  • 顶点着色器:对顶点的位置坐标进行 MVP 矩阵变换;
  • 片段着色器:对像素点的颜色属性进行计算,纹理贴图、光照计算、阴影计算都可以在此阶段完成。

        OpenGL ES 1.x 为固定渲染管线,2.x 之后支持可编程渲染管线,使用 GLSL 语言编程,语法详见→GLSL 中文手册。

6 渲染管线

        渲染管线是指:将模型的顶点序列、颜色系列、纹理序列、法线序列等数据输入到 OpenGL ES 中,到输出屏幕,这个阶段数据所经历的流程。渲染管线总体流程如下:

  • 裁剪:进行透视分割,并剔除视锥体外面的顶点,根据 x, y, z 的值是否在 [-1, 1] 之间判断是否淘汰顶点;
  • 屏幕映射:根据视口(Viewport)大小,将近平面上的点映射到屏幕上
  • 图元装配:根据输入顶点序列和和图元类型(mode)组装图元;
  • 光栅化:对图元内部进行插值,使其与屏幕中的像素一一对应;
  • 裁剪测试:指定一个矩形的剪裁区域,当启用剪裁测试后,只有在这个区域之内的像素才能被绘制,其它像素被丢弃;
  • Alpha 测试:检查片段的 Alpha 值,只有 Alpha 值满足条件的片段才会进行绘制;
  • 模板测试:在模板缓冲区中为每个像素保存了一个 “模板值” ,当像素需要进行模板测试时,将缓冲区中模板值与该像素的模板值进行比较,符合条件的通过测试,不符合条件的则被丢弃,不进行绘制;
  • 深度测试:在深度缓冲区中为每个像素保存了一个 “深度值”(顶点到相机的距离),当像素需要进行深度测试时,将缓冲区中深度值与该像素的深度值进行比较,符合条件的通过测试,并覆盖缓冲区中深度值,不符合条件的则被丢弃,不进行绘制;
  • 混合:在物体遮挡场景下,未开启混合时,前面的物体会遮住后面物体;开启混合后,根据物体的色光三元色和透明度进行混合。

        补充:只有开启模板测试时,才会尝试修改像素的模板值,模板测试被关闭时,在像素被绘制时也不会修改像素的模板值;无论是否开启深度测试,在像素被绘制时都会修改像素的深度值。

7 片段测试

        片段测试包含裁剪测试、Alpha 测试、模板测试。OpenGL ES 会对每个即将绘制的像素进行以上四种测试,每个像素只有通过一项测试后才会进入下一项测试,而只有通过所有测试的像素才会被绘制,没有通过测试的像素会被丢弃掉,不进行绘制。每种测试都可以单独的开启或者关闭,如果某项测试被关闭,则认为所有像素都可以顺利通过该项测试。

        1)裁剪测试

        指定一个矩形的剪裁区域,当启用剪裁测试后,只有在这个区域之内的像素才能被绘制,其它像素被丢弃。 

glEnable(GL_SCISSOR_TEST); // 启用剪裁测试
glDisable(GL_SCISSOR_TEST); // 禁用剪裁测试
glScissor(x, y, width, height); // 指定一个位置在(x, y),宽度为width,高度为height的剪裁窗口

        注意:OpenGL ES 窗口坐标是以左下角为 (0, 0),右上角为 (width, height)。

        视口变换也可以将像素只绘制到某一个特定的矩形区域内,但视口变换是将所有内容缩放到合适的大小后,放到一个矩形的区域内;而剪裁测试不会进行缩放,超出矩形范围的像素直接忽略掉。 

        2)Alpha 测试

        检查片段的 Alpha 值,只有 Alpha 值满足条件的片段才会进行绘制。

glEnable(GL_ALPHA_TEST); // 启用Alpha测试
glDisable(GL_ALPHA_TEST); // 禁用Alpha测试
glAlphaFunc(GL_GREATER, 0.5f); // 大于0.5通过Alpha测试

        glAlphaFunc 第一个参数取值如下:

GL_ALWAYS //始终通过,默认情况
GL_NEVER // 始终不通过
GL_GREATER // 大于设定值则通过
GL_LESS // 小于设定值则通过
GL_EQUAL // 等于设定值则通过
GL_GEQUAL // 大于等于设定值则通过
GL_LEQUAL // 小于等于设定值则通过
GL_NOTEQUAL // 不等于设定值则通过

        3)模板测试

        在模板缓冲区中为每个像素保存了一个 “模板值” ,当像素需要进行模板测试时,将缓冲区中模板值与该像素的模板值进行比较,符合条件的通过测试,不符合条件的则被丢弃,不进行绘制。 

glEnable(GL_STENCIL_TEST); // 启用模板测试
glDisable(GL_STENCIL_TEST); // 禁用模板测试
glStencilFunc(GL_LESS, 3, mask); // 小于3则通过, 第一个参数取值同Alpha测试
glClear(GL_STENCIL_BUFFER_BIT); // 复位模板值
glClearStencil(); // 指定复位后的模板值

        说明:mask 表示只比较 mask 中二进制为 1 的位,例如:某个像素模板值为 5(二进制 101),mask 的二进制值为 00000011,则只需较最后两位,5 的二进制最后两位为 01,小于 3,因此会通过测试。 

        使用 glStencilOp 函数可以指定每个像素的 “模板值” 会根据模板测试的结果和深度测试的结果而进行改变,如下:

// fail: 模板测试未通过时该如何变化;
// zfail: 模板测试通过,但深度测试未通过时该如何变化;
// zpass: 模板测试和深度测试均通过时该如何变化;
// 如果没有起用模板测试,则认为模板测试总是通过;如果没有启用深度测试,则认为深度测试总是通过
glStencilOp(fail, zfail, zpass); 

        fail、zfail、zpass 取值如下:

GL_KEEP // 不改变, 默认值
GL_ZERO // 回零
GL_REPLACE // 使用测试条件中的设定值来代替当前模板值
GL_INCR // 增加1,但如果已经是最大值, 则保持不变
GL_INCR_WRAP // 增加1, 但如果已经是最大值, 则从零重新开始
GL_DECR // 减少1, 但如果已经是零, 则保持不变
GL_DECR_WRAP // 减少1, 但如果已经是零, 则重新设置为最大值
GL_INVERT // 按位取反

         使用剪裁测试可以把绘制区域限制在一个矩形的区域内,但如果需要把绘制区域限制在一个不规则的区域内,则需要使用模板测试。如:绘制一个池塘以及周围的树木,然后绘制树木在池塘中的倒影。为了保证倒影被正确的限制在池塘水面,可以使用模板测试。具体的步骤如下:

glDisable(GL_STENCIL_TEST); // 禁用模板测试
draw_ground_trees(); // 绘制地面和树木
-------------------------------------------------------------
glEnable(GL_STENCIL_TEST); // 开启模板测试
glClear(GL_STENCIL_BUFFER_BIT); // 设置所有像素的模板值为0
glStencilFunc(GL_ALWAYS, 1, 1); // 设置模板测试总是通过
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // 池塘水面的像素的模板值修改为1,而其它地方像素的模板值为0
draw_pond_surface(); // 绘制池塘水面
-------------------------------------------------------------
glStencilFunc(GL_EQUAL, 1, 1); // 设置模板值等于1时才通过模板测试
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // 通过模板测试后不修改模板值
draw_reflection(); // 绘制倒影

        4)深度测试

        在深度缓冲区中为每个像素保存了一个 “深度值”(顶点到相机的距离),当像素需要进行深度测试时,将缓冲区中深度值与该像素的深度值进行比较,符合条件的通过测试,并覆盖缓冲区中深度值,不符合条件的则被丢弃,不进行绘制。 

glEnable(GL_DEPTH_TEST); //启用深度测试
glDisable(GL_DEPTH_TEST); // 禁用深度测试
glDepthMask(GL_TRUE); // 开启深度缓冲区写入
glDepthMask(GL_FALSE); // 禁用深度缓冲区写入
glDepthFunc(GL_LESS); // 深度小于缓冲区则通过测试, 默认值是GL_LESS, 取值同Alpha测试

8 混合

        在物体遮挡场景下,未开启混合时,前面的物体会遮住后面物体;开启混合后,根据物体的色光三元色和透明度进行混合。 读者可以在Visual glBlendFunc + glBlendEquation Tool 网站查看不同混合设置的混合效果,网站页面如下:

        1)混合函数

glEnable(GL_BLEND); //启用混合效果
glDisable(GL_BLEND); //禁用混合效果
// 设置混合因子, srcfactor: 源混合因子, destfactor: 目标混合因子
void glBlendFunc(GLenum srcfactor, GLenum destfactor);
// // 设置混合因子, srcRGB: 源rgb混合因子, destRGB: 目标rgb混合因子, srcalpha: 源alpha混合因子, destalpha: 目标alpha混合因子
void glBlendFuncSeparate(GLenum srcRGB, GLenum destRGB, GLenum srcalpha, GLenum destalpha);
// 设置混合方程: add、subtract、reverse_subtract、min、max
void glBlendEquation(GLenum mode);

        示例如下:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
glBlendEquation(GL_FUNC_ADD);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);

        2)混合因子

// 源颜色为: (sR, sG, sB, sA), 目标颜色为: (dR, dG, dB, dA)
GL_ZERO // (0, 0, 0, 0)
GL_ONE // (1, 1, 1, 1)
GL_SRC_COLOR // (sR, sG, sB, sA)
GL_DST_COLOR // (dR, dG, dB, dA)
GL_ONE_MINUS_SRC_COLOR // (1, 1, 1, 1) - (sR, sG, sB, sA)
GL_ONE_MINUS_DST_COLOR // (1, 1, 1, 1) - (dR, dG, dB, dA)
GL_SRC_ALPHA // (1, 1, 1, 1) * sA
GL_DST_ALPHA // (1, 1, 1, 1) * dA
GL_ONE_MINUS_SRC_ALPHA // (1, 1, 1, 1) * (1-sA)
GL_ONE_MINUS_DST_ALPHA // (1, 1, 1, 1) * (1-dA)
GL_SRC_ALPHA_STATURATE // (1, 1, 1, 1) * min(sA, 1-dA)

        说明:混合因子将作为 glBlendFunc、glBlendFuncSeparate 函数的入参。

        3)混合方程

        混合方程用于确定 srcFactor * srcRGBA(结果记为 S) 与 destFactor * destRGBA(结果记为 D)之间通过什么运算确定最终的混合颜色。

GL_FUNC_ADD // S + D
GL_FUNC_SUBTRACT // S - D
GL_FUNC_REVERSE_SUBTRACT // D - S
GL_MIN // min(S, D)
GL_MAX // max(S, D)

9 参考链接

  • OpenGL渲染管线解析
  • 深度测试,剪裁测试、Alpha测试和模板测试
  • GLSL 中文手册

http://chatgpt.dhexx.cn/article/WqFfhiPb.shtml

相关文章

渲染管线----通俗易懂向面试官介绍

本文通过简短的语言解释渲染管线,无论是第一次了解渲染管线,还是回顾,都有帮助。 一、完整渲染流程 在介绍渲染管线之前,先全局视角了解一下整个渲染引擎。 整个渲染分为五个阶段,如图 工具阶段、资产调节阶段、应用程…

学习笔记(一)渲染管线

目录 前言 一些疑问 一、什么是渲染管线? 二、为啥这玩意是个流水线? 1.CPU与GPU 2.CPU和GPU数据交互 3.CPU和GPU并行工作 Step1.应用程序阶段(The Application Stage) 一、把数据加载到显存中。 二、设置渲染状态。 三…

计算机图形学笔记(一)渲染管线概述

计算机图形学笔记(一)渲染管线概述 写在前面:因为之前有学习过图形学,博文是对过去知识的拾遗和对学习过程中的总结记录,所以在内容组织上可能不符合逻辑,某些比较熟悉的内容不会体现或简述;在整…

渲染基础-渲染管线(Render-pipeline)

一开始学习计算机图形学的小伙伴们肯定对于渲染管线有一点迷茫,至少当初我就有点迷茫,为了能对后来对计算机图形学感兴趣的萌新小伙伴起到一些帮助,在这里简单讲解一下渲染管线(Render-pipeline)。 该文章还有很多不足…

如何使用SPSS确定建立的回归模型能用于预测分析?

当需要研究一组随机变量与另一组变量的关系时,通常会运用回归分析。通过回归分析构建数学模型,探究两种或两种以上变量之间是否存在关系,若存在关系还可进一步预测未来的数据。 当自变量有多个而因变量只有一个时,则可构建spss多…

如何使用SPSS判断数据的正态分布

当我们应用统计方法对数据进行分析时,会发现许多计量资料的分析方法,例如常用的T检验、方差分析、相关分析以及线性回归等等,都要求数据服从正态分布或者近似正态分布,但这一前提条件往往被使用者所忽略。因此为了保证数据满足上述…

如何使用SPSS进行判别分析

今天将为大家讲解使用spss进行判别分析的相关步骤。 1.Discriminant Analysis判别分析主对话框 如图 1-1 所示 图 1-1 Discriminant Analysis 主对话框 (1)选择分类变量及其范围 在主对话框中左面的矩形框中选择表明已知的观测量所属类…

IBM SPSS Statistics定义变量使用介绍

IBM SPSS Statistics是一款强大的数据分析软件,它可以帮助我们解决很多复杂的统计学问题,使用SPSS的第一步就是要学会如何定义变量,下面让我们走进今天的SPSS入门教程。 一、进入变量视图 在定义变量之前,我们需要进入IBM SPSS …

SPSS使用过程中出现的问题整理 包括因子分析 感谢各位大佬们

spss使用方法整理 包括因子分析 一、遇到问题:spss导入excel数据显示:对于当前服务器语言环境而言,文本值过长二、SPSS数据分析-从EXCEL导入三、因子分析在SPSS中的操作过程及结果解读 一、遇到问题:spss导入excel数据显示:对于当前服务器语言环境而言,文…

通过SPSS使用命令语法实现快速删除变量的步骤

当我们面对一个庞大的数据集的时候,我们想要对该数据集进行一些操作,可能会觉得比较繁琐。为了快速精准的实现数据过滤操作, SPSS是自带了语法功能,通过语法即可快速实现复杂操作。今天小编将通过快速删除变量的操作,让…

SPSS入门教程—相关性分析使用方法

IBM SPSS Statistics为用户提供了三种相关性分析的方法,分别是双变量分析、偏相关分析和距离分析,三种相关分析方法各针对不同的数据情况,接下来我们将为大家介绍如何使用SPSS相关性分析中的距离分析。 一、数据简述 距离分析和其他两类相关…

使用IBM SPSS Statistics的新手应该如何入门

一、什么是IBM SPSS Statistics? IBM SPSS Statistics 是一款强大的统计软件平台,它所提供的数据分析功能,可以帮助企业、个人对各类数据进行切实可行的洞察分析,从而获取有效信息。 二、为什么要进行SPSS数据分析? …

【SPSS】包含多元线性回归、聚类分析、判别分析、主成分、相关系数、非参数秩检验的spss使用方法,含有相关例题,可以解决“数学建模”中数据建模的大部分问题

记录《多元统计分析》关于spss软件的使用,本篇教程不涉及具体模型的推导,通过例题来带领大家入门spss软件,学习软件基本的使用,解决常见数模问题。 本篇所有数据都可以在百度网盘上下载: 链接:https://pan.…

关于SPSS软件的使用

最近由于调研的需要,需要使用spss软件:Statistical Product and Service Solutions,“统计产品与服务解决方案”软件 1.首先是定义变量: 选择左下角“变量视图”,我们调查问卷的每一道题都可以作为一个变量&#xff0c…

spss登录本地计算机,SPSS基本使用

1.定义变量 名称不能用$,后面加.,保留字会歧义,不区分大小写 标签是对变量的补充说明 测量 : 名义:代表不同的类别,不能比较大小。如 性别 度量:可以比较大小 如距离、长度 有序:分类变量(大小之间有等级顺序)如:满意,很满意,不满意。。。。 2.SPSS导入数据库文件时,…

spss安装使用

1.下载spss24 百度云链接如下: 64位安装包:https://pan.baidu.com/s/19_nW1eJh5HN8Q_PAEUzfTg 提取码:l5fc 32位安装包:https://pan.baidu.com/s/14wga9CrNnysTImOaO6JW-Q 提取码:ayl5 安装教程下载&#xff…

SPSS使用命令语法之复制与粘贴讲解

在繁杂的数据中,我们常常束手无策,很难精准地完成数据统计和数据分析,但是IBM SPSS Statistics可以很好地协助我们完成这些工作。 IBM SPSS Statistics 作为一个强大的统计软件平台,不仅可以通过用户友好型界面,分析目…

spss使用教程

描述性统计结果 步骤从上到下 分析描述统计描述 制作矩阵散点图 4. 图形 5. 旧对话框 6. 散点图/点图 7. 矩阵散点图 求相关系数和p值

minecraft编程java_Minecraft编程基础课程(一)

《minecraft》(《我的世界》)是一款风靡全球的高自由度沙盒游戏,整个游戏没有剧情,玩家在游戏中自由建设和破坏,透过像积木一样来对元素进行组合与拼凑,轻而易举的就能制作出小木屋、城堡甚至城市,玩家可以通过自己创造…

2022年01月世界编程语言排行

2022年01月世界编程语言排行 2022年1月TIOBE指数 一月标题:2021年度Python编程语言 Python赢得了久负盛名的TIOBE编程语言奖。祝贺!这是连续第二次。该奖项授予一年内获得最高收视率增长的编程语言。C#在历史上第一次获得了这个头衔,但Pyt…