游戏渲染管道

高级的渲染步骤是由管道(软件架构)实现,各个阶段会操作输入流中的数据项,并对输出流产生数据。

管道每个阶段独立于其他阶段,所以管道的最大有点在于非常适合并行化。

渲染管道分为3个概要阶段。但在这里多讲几个阶段(包含脱机工具创建场景的阶段):

  1. 工具阶段(脱机):定义几何和材质

  2. 资产调节阶段(脱机):资产调节管道处理几何和材质数据,生成引擎可用的格式

  3. 应用程序阶段(CPU):识别潜在可视的网格实例并把它们和材质提交给GPU

  4. 几何处理阶段(GPU):变换顶点、照明,并投影至齐次裁剪空间

  5. 光栅化阶段(GPU):三角形转换成片段并着色。期间片段会进行多种测试,最终和帧缓冲混合

工具阶段

在Maya、3ds Max、SketchUp等工具中制作三维模型。美术也需要定义材质(包括贴到网格表面的纹理设置,以及其他高级特性比如选用哪个着色器、着色器的输入参数。。。)

资产调节阶段

导出、处理、链接多个种类的资产,生成一个整体,并已准备就绪供引擎导入。

应用程序阶段

主要进行三个方向的处理:

  • 可见性判断。仅把潜在可见的物体提交给GPU。

  • 提交几何图元给GPU。

  • 控制那些不可编程但可配置的GPU管道参数及渲染状态。

可见性判断

首先进行平截头体剔除,用物体的包围体积(通常是球体)与平截头体的六个平面进行运算。每个平截头体的六个平面向外移动球体半径的距离,如若球的中心点在平截头体内部,则视为是在平截头体里面无需剔除,否则就应该剔除。

但目前游戏能达到非常大的规模,所有物体进行平截头体剔除有点不太现实,所以可以通过“场景图”的方式来进行剔除,即设计一些数据结构来管理几何物体,这类数据结构能短时间内判断是否在平截头体中,并在判断不在时迅速丢弃里面的物体。

四叉树是其中一个数据结构,把空间递归分割成象限,每层递归生成四个节点,直到每个子节点中含有n个物体。通常是每个子节点中包含一个物体。进行平截头体判断的方式很简单,就是从根节点向叶节点遍历,检查节点是否在平截头体范围内,如果该节点不在则迅速停止判断,并且此节点的叶节点都不可能在平截头体范围内了。

八叉树是四叉树的三维版本。二元空间分割(BSP)则是空间递归分割一半。kd树和BPS的特殊情况,BSP每次分割可以任意方向,kd每次分割都是轴对齐,先切割x坐标,再切割y坐标,依次类推。

其次进行遮挡判断。

有几项技术,其中一项是潜在可见集(PVS),即将场景划分为几个区域,每个区域提供能看见的其他区域列表。

还有另一个方法:入口,每个区域用孔洞连接,每个孔洞(比如窗户/门户)和摄像机交互并向前延伸形成类似平截头体的效果,便可以和平截头体剔除一样确定哪些物体可不被渲染。

反入口则是相反概念,锥形视角也可视作是不可见区域,通过不可见区域来排除一定不可见的那些物体。

几何排序

为了增加GPU渲染效率,可以按照材质来排序几何物体,即先渲染材质A再渲染材质B。但是为了保证预先丢弃被遮挡的像素,有应该从前至后的顺序来渲染三角形,这样是更快的。那如何解决这一冲突呢,可以采用GPU的深度预渲染步骤,主要方式是渲染场景两次,第一次快速产生深度缓冲的内容,不透明物体用从前至后的顺序更新深度缓冲,第二次再用材质进行排序,用最少的状态改变渲染颜色。

渲染完不透明物体后再从后至前渲染半透明表面。也可使用次序无关透明,每个像素存储多个片段,场景渲染后无需排序直接渲染透明物体。但是因为每个像素要存储所有透明片段,所以存在高内存成本。

GPU管道

几乎所有GPU(图形处理器)都会把管道拆分为以下的子阶段:

顶点着色器负责变换及着色顶点。输出是变换和着色后的顶点。

几何着色器处理以齐次裁剪空间表示的整个图元(三角形、线段、点),包括剔除、修改、添加图元,包括阴影体积拉伸、立方体贴图的渲染、布料模拟等。

流输出即数据能从这里回到管道开始的地方做进一步处理,比如头发的渲染,顶点着色器进行物理模拟完之后交给几何着色器渲染,然后顶点数据重新流入管道开始的地方渲染。

裁剪即是把三角形在平截头体外的部分切掉。同样能剔除完全在平截头体外的三角形。此阶段可配置,比如除了平截头体的平面外可定义额外的裁剪平面。

屏幕映射即简单的顶点变换,把其从齐次裁剪空间变换到屏幕空间。

三角形建立&遍历即将三角形转换成片段(光栅化)。

在提前深度测试阶段能够检查片段的深度,若某片段确定会被帧缓冲内的像素遮挡,就可在此时丢弃该片段。值得注意的是,不是所有GPU都支持这项操作,过去的GPU的深度测试是在像素着色器之后进行,所以这里被称为提前z测试或者提前深度测试。

像素着色阶段里,输入时一组每片段属性(通过顶点属性插值获得),输出则是颜色矢量,代表片段颜色。

合并/混合/光栅运算(ROP)阶段中,负责执行多个片段测试,包括深度测试、alpha测试、模板测试等。此片段若通过所有测试,则与帧缓冲原来的颜色进行混合。为了让alpha混合显示正常,必须先将不透明几何物体渲染至帧缓冲,然后依次渲染透明物体。

可编程着色器

着色器从输入数据取得一个元素,并变换为输出数据的零个或多个元素。

  • 顶点着色器输入模型空间或者世界空间的顶点,输出变换和着色后的齐次裁剪空间的顶点。

  • 几何着色器输入一个有n个顶点(1是点,2是线段,3是三角形)的图元,输出一个经过阴影体积拉伸、立方体贴图的渲染、布料模拟等处理后的图元。

  • 像素着色器输入一个片段,输出的是将要写进帧缓冲的颜色。也可以丢弃这个片段,输出则是空。

抗锯齿

全屏抗锯齿/超采样抗锯齿(FSAA)

把场景渲染至比实际屏幕大的帧缓冲中,渲染完之后再向下采样至目标分辨率。

多采样抗锯齿(MSAA)

因为锯齿主要产生在三角形边缘而非内部,所以相对上个方法有所改良。

因为光栅化三角形可分为三个操作:1.判断三角形重叠(覆盖测试)。2.判断三角形遮挡(深度测试)。3.这两个测试之后着色。

非抗锯齿情况下的光栅化中每个像素都是基于一个点来做上面三个操作的,一般是选像素中央点。

但是MSAA中就是一个像素内采样多个点进行前两个测试,着色时就取这些采样点的子样本平均值来着色。

覆盖采样抗锯齿(CSAA)则是以上方法进一步优化,一次着色,N次深度测试,但是覆盖测试过程中会更多采样点进行测试,这样子能有更细致的色彩融合效果。比如1次着色,4次深度测试,16次覆盖测试。

形态学抗锯齿(MLAA)

正常尺寸渲染,通过扫描找出阶梯形状的图像模式,发现这些图像模式后通过模糊化降低混叠效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/337811.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【大数据分析与挖掘技术】Mahout聚类算法

目录 一、聚类的基本概念 二、常见的Mahout数据结构 (一)向量(Vector) (二)文本文档 三、聚类算法种类 (一)K-means (二)模糊K-means (…

中国电子学会2022年6月份青少年软件编程Scratch图形化等级考试试卷一级真题

一、单选题(共25题,共50分) 1.广场中有声控喷泉,当声音的音量大于60的时候,喷泉就会喷出水,现在的音量为30,下列哪个选项可以让喷泉喷出水?(2分) A. B. C. D. 答案解析&#x…

搭建开源数据库中间件MyCat2-配置mysql数据库双主双从

mycat2官网:MyCat2 前言:mycat2下载地址无法访问,不知道是不是被DNS污染了,还是需要搭梯子访问,所以我只能找到1.21的版本进行安装。搭建mycat2的前提是搭建数据库主从复制。 架构:双主双从 配置&#xf…

基于OpenSSL的SSL/TLS加密套件全解析

概述 SSL/TLS握手时,客户端与服务端协商加密套件是很重要的一个步骤,协商出加密套件后才能继续完成后续的握手和加密通信。而现在SSL/TLS协议通信的实现,基本都是通过OpenSSL开源库,本文章就主要介绍下加密套件的含义以及如何在O…

通信入门系列——连续卷积定理、循环卷积、离散卷积定理

本节目录 一、连续卷积定理 1、时域卷积定理 2、频域卷积定理 二、循环卷积 三、离散卷积定理本节内容 一、连续卷积定理 卷积定理在信号分析中占有重要的地位,包括时域卷积定理和频域卷积定理。在信号分析领域,通常采用基于卷积定理的时频域分析&#…

vectorCast——CBA功能实现代码手动覆盖

选择被测文件,点击右键,选择add coverage analysis.选择添加覆盖分析后,会自动打开CBA。此时就可以在代码里选择没有覆盖的代码,勾选后填写未覆盖分析并保存,就可以实现代码覆盖了。查看覆盖率报告。 手动覆盖代码完成…

结构体内存对齐(面试重点)

结构体内存对齐 1. 结构体类型的声明1.1 结构体的概念1.1.1 结构的声明1.1.2 结构体变量的创建和初始化 1.2 结构的特殊声明1.3 结构的自引用 2. 结构体内存对齐2.1 对齐规则2.1.1 练习1:2.1.2 练习2:2.1.3 练习3:2.1.4 练习4: 2.2 offsetof宏的使用2.3 为什么存在内存对齐?2.…

Vue2的双向数据绑定

Vue2的双向数据绑定 Observer:观察者,这里的主要工作是递归地监听对象上的所有属性,在属性值改变的时候,触发相应的watcher。 Watcher:订阅者,当监听的数据值修改时,执行响应的回调函数&#x…

基于Springboot的民宿在线预定平台(有报告)。Javaee项目,springboot项目。

演示视频: 基于Springboot的民宿在线预定平台(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Spring…

通过完善价值观评价,建立企业多维度评价体系

一、背景A公司是一家互联网公司,主要负责技术开发、软件应用方面的工作,致力于长期的软件研发、服务器开发、游戏端开发等,依托于专业技术实力和长期的实践积累,公司不断整合各类资源、深入开发技术,规模不断扩大&…

详解Redisson

第1章:Redisson简介 大家好,我是小黑,咱们今天来聊聊Redisson,Redisson不只是简单地对Redis进行了封装,它还提供了一系列高级的分布式Java数据结构,像是分布式锁、原子长整型这种。 首先,Redi…

02_Collection

文章目录 集合Java的集合类 Collectioniterator方法 集合 在Java中,指的就是存放数据的容器,是一个载体,可以一次容纳多个对象。 解决Bug的两种方法: 打印 System.out.println();log.info(); debug 检查数据 Java的集合类 Co…

项目管理十大知识领域之项目干系人管理

一、项目干系人管理的概念解析 项目干系人管理是指在项目执行过程中,对项目相关方的需求进行识别、分析和管理的过程。项目干系人管理的核心在于有效地沟通、协调和满足各方的需求,以确保项目能够顺利实施并达到预期的成果。在现代项目管理实践中&#…

conda国内加速

1、配置国内源 conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ 2、显示源地址 conda config --set show_channel_urls yes

Python实现GEE嵌套协方差结构仿真模型(GEE算法)项目实战

说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 广义估计方程(Generalized Estimating Equations, GEE)是一种用于分析具有重复…

CC工具箱使用指南:【按条件选择排序】

一、简介 此工具来自一个群友的需求,做完想想可能会有同样需求的人用得到,就稍改了一下做成公共版本。 具体需求是这样的: 1、按条件选择对部分图斑进行排序,比如说在所有地类中,只想对地类名称为【林地】的图斑进行…

【Elasticsearch】索引恢复(recovery)流程梳理之副本分片数据恢复

replica shard重启具体流程 replica shard node (generic threadpool) 也是因为应用新的集群状态触发recovery,进入index阶段进入translog 阶段。先尝试重放本地的translog到global checkpoint向primary shard发起start recovery的请求&…

C++参悟:正则表达式库regex

正则表达式库regex 一、概述二、快速上手Demo1. 查找字符串2. 匹配字符串3. 替换字符串 三、类关系梳理1. 主类1. basic_regex 2. 算法1. regex_match2. regex_search3. regex_replace 3. 迭代器4. 异常5. 特征6. 常量1. syntax_option_type2. match_flag_type3. error_type 一…

【Linux】第三十站:进程间通信

文章目录 一、是什么二、为什么三、怎么办四、管道1.什么是管道2.管道的原理3.接口4.编码实现5.管道的特征6.管道的四种情况 一、是什么 两个或者多个进程实现数据层面的交互 因为进程独立性的存在,导致进程通信的成本比较高 通信是有成本的,体现在要打破…

集美大学“第15届蓝桥杯大赛(软件类)“校内选拔赛 D矩阵选数

经典的状态压缩DP int dp[15][(1<<14)10]; int a[15][15]; void solve() {//dp[i][st]考虑到了第i行 并且当前考虑完第i行以后的选择状态是st的所有方案中的最大值for(int i1;i<13;i)for(int j1;j<13;j)cin>>a[i][j];for(int i1;i<13;i){for(int j0;j<…