Unity渲染流程概述

article/2025/7/19 10:20:28

本篇的任务是回答:在Untiy的渲染流程中CPU和GPU分别做了什么。

渲染到设备屏幕显示的每一帧的画面,都经历几个阶段的加工过程:

  • 应用程序阶段(CPU):识别出潜在可视的网格实例,并把他们及其材质提交给GPU以供渲染。
  • 几何阶段(GPU):进行顶点变换等计算,并将三角形转换到齐次空间并进行裁剪。
  • 光栅化阶段(GPU):把三角形转换为片元,并对片元执行着色。片元经过多种测试(深度测试,alpha测试等)之后,最终与帧缓冲混合。

CPU的工作流程:

CPU

  1. 准备好需要被渲染的对象。也就是哪些物体需要被渲染,哪些物体需要被剔除(culled),剔除的常用方式包括视锥体剔除和遮挡剔除,并对需要渲染的对象进行排序。
  2. 设置每个对象的渲染状态。渲染状态包括所使用的着色器、光源、材质等。
  3. 发送DrawCall。当给定一个DrawCall时,GPU会根据渲染状态和输入的顶点数据进行计算。 

Unity的渲染顺序可以简单的理解为是从近到远(实际上要复杂的多)。根据渲染对象的排序,会为每一个渲染对象的每一个材质,生成一个渲染批次batch。在不考虑动态批处理和静态批处理的情况下,总的batch量就是每个渲染对象所包含的材质的总和。但是因为存在动态/静态批处理的情况,所以实际产生的batch数量要小于前面计算的总和。

在我一贯的测试过程中,SetPass call与渲染状态的切换是最吻合的,所以我将SetPass call简单的理解成设置渲染状态。但是,要说明的是,这只是我的个人想法,并没有其他支持。

SetPass call 和Draw call作为渲染命令队列的组成内容,担负着不同的任务。可以这样理解,SetPass call是告诉GPU接下来要用到哪些资源了,抓紧准备起来,而draw call则是把要求GPU根据顶点数据进行绘制。所以在执行SetPass call时,会向现存中传递大量的资源信息,包括纹理资源也是在这时候加载到缓存中,仅当下一个需要渲染的网格需要变更渲染状态时,才会产生SetPass call。所以,SetPass call和Draw call虽然是相伴产生的,但是两者却不一定对等。在某些情况下,一个batch可能会用到多个pass,比如mesh的反向描边。对于不同的pass,CPU将发送新的SetPass call 和Draw call。而在静态批处理中,因为顶点限制而不能在同一批次处理而被分割的紧邻的多个批次,因为使用的是相同的渲染设置,所以也只会产生一个SetPass call。

通常来说在优化时我们关注的是DrawCall,但也有不同的声音说,SetPass call更有意义。我觉得用哪个做分析从优化角度来说,差别不大。他们传递的都是指令和地址,真正耗时的是执行绘制阶段。并且两者的产生也基本是相伴的。

GPU的工作流程:

顶点着色器:

顶点着色器负责变换及着色/光照顶点。顶点着色器的输入来自于CPU,CPU输入的每个顶点都会执行一次顶点着色器,顶点着色器本身无法创建和销毁顶点,并且无法得到顶点与顶点之间的关系。正因为这样的独立关系,GPU可以利用自身的特性进行并行运算,所以顶点着色器的运算速度非常快。在此阶段也会进行透视投影、顶点光照、纹理计算、蒙皮。也可以通过修改顶点位置生成程序式动画(procedural animation),例如模拟风吹草动,碧波荡漾。

几何着色器:

几何着色器因为在手机端不支持,所以Unity开发程序员也许并不熟悉。几何着色器也是完全可编程的。几何着色器处理以齐次裁剪空间表示的整个图元(三角形,线段,点)。它能够剔除和修改输入的图元,也能生成新的图元。典型应用包括阴影的体积拉伸(shadow volume extrusion)、渲染立方体贴图(cube map)的六个面、在网格的轮廓边拉伸毛发(fur fin)、从点数据生成粒子四边形、动态镶嵌、把线段以分形细分(fractal subdivision)模拟闪电效果、布料模拟等。

裁剪:

最常用的裁剪设置是CULL OFF/BACK/FRONT,分别是不剔除/背面剔除/正面剔除。这里的正反面与摄像机没有一分钱的关系,而是通过法线方向决定的。

屏幕映射:

这里注意一点,虽然屏幕映射是玩家不可配置和编程的,但是屏幕分辨率确实玩家可以设置的,较小的屏幕分辨率对光栅化阶段是有非常重要的优化效果的。

三角形遍历:

三角形遍历阶段把三角形分解为片段(光栅化)。通常每个像素会产生一个片元,除非是使用MSAA,那么每个像素就会产生多个片元。三角形遍历也会对顶点属性进行插值,以生成每个片元的属性,供像素着色器使用。

片元着色器:

片元着色器是完全可编程的。其工作是为每个片元着色。片元着色器也能丢弃一些片元,例如根据透明度做剔除。像素着色器可以对多个纹理进行采样并计算逐像素光照和任何会影响片元颜色的计算。此阶段的输入是一组片元属性,这些属性是在三角形遍历阶段通过对顶点属性插值所得。输出则是一个颜色矢量。

逐片元操作:

该阶段也称为合并阶段(merge stage)或混合阶段(blending stage),NVIDIA称之为光栅化运算阶段(raster operations stage,ROP)。此阶段不可编程,但是可以高度配置化。最常用的逐片元操作测试包括深度测试ZTest、Alpha测试、模板测试Stencil test,当片元通过了所有测试以后,其颜色就会与帧缓冲原来的颜色进行混合(Blend),混合的方式是可配置的,如Blend One One。在该阶段另一个重要的配置是深度写入ZWrite。

 

 

 

 

 

 

 

 

 

 

 

 


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

相关文章

Unity_渲染_灯光_前向渲染

前向渲染路径 前向渲染的作用和意义场景内有多个灯光,如何渲染每个灯光对物体的影响 前向渲染的作用和意义 前向渲染的作用:处理多光源的渲染,多光源渲染在unity 有2中渲染方式 前向渲染和延时渲染 .延时渲染主要用于主机,PC平台,不在本次讨论范围.主要来研究前向渲染前向渲染…

【Unity渲染】前向渲染和延迟渲染的区别及切换

前向渲染和延迟渲染通道的区别,主要在对于光源的处理上。 Unity默认是前向渲染通道,如果光源特别多,可以使用延迟渲染。 前向渲染 使用前向渲染路径时,被照亮的对象将在单独的通道中进行渲染。根据场景中的光源数量以及它们是否…

从FrameDebugger看Unity渲染

从FrameDebugger看Unity渲染(一) Unity如何渲染一个3D2D的游戏画面,今天通过FrameDebugger来看下Unity内置渲染管线的渲染策略, 后续再出一些URP渲染管线相关的文章。 对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白&#xff0c…

UnityShader入门精要——Unity中的渲染优化技术(二)

减少DrawCall数目 最常见的优化技术——批处理。实现原理为减少渲染每一帧所需的drawcall数目。使用同一个材质的物体可以一起处理。 优点缺点动态批处理切处理都是Unity 自动完成的,不需要我们自己做任何操作,而且物体是可以移动的限制很多&#xff0c…

Unity渲染顺序(2)

Camera 除了Screen Space - Overlay(屏幕空间覆盖模式)下的Canvas,场景中的其他物体需要渲染到屏幕中,都需要在指定的相机的绘制下。场景中可以创建多个相机,每个相机所拍摄的内容可能并不相同,在场景中有多相机的情况,不同的相机…

Unity渲染顺序(1)

添加排序层级 在Unity编辑器的右上角选择Layers 按钮,在下拉菜单中点击Edit Layers…选项,将显示当前Unity的Tags, Sorting Layers,和Layers 编辑选项。 Sorting Layers是Unity中对排序的层级的定义块,在面板中越靠后的排序层级越…

Unity的渲染流程

Unity中坐标空间的转换: Unity的渲染流程: 渲染到设备屏幕的每一帧画面都要经历如下几个阶段: 应用程序阶段(CPU):将材质和模型数据发送给GPU 几何阶段(GPU):进行顶点…

Unity 渲染原理

1 渲染流程 应用程序阶段(CPU):识别出潜在可视的网格实例,并把他们及其材质提交给 GPU 以供渲染。几何阶段(GPU):进行顶点变换等计算,并将三角形转换到齐次空间并进行裁剪。光栅化阶…

Unity标准化的场景渲染流程

笔者用的unity版本为2020.3.30f1c1,开一个HDRP模板场景,OK开始我们的操作。 第一步:删除场景中的所有东西只留下竹林玻璃房作为展示场景,将所有物体勾选Static,新增一个摄像机,如下图: 第二步&a…

Unity3D性能优化——渲染篇

大渣好,我又来了。 之前的文章中,我们了解了Profiler工具,以及在实际项目中unity的CPU优化分析及方法,本文我们主要了解在我们的项目中GPU的性能分析,以及对GPU性能进行优化的相关技术。 渲染优化 在了解优化渲染前&a…

Unity中的灯光和渲染

一:Unity中的灯光 ——Directional Light:模拟太阳光。它与位置无关,是平行光,可以调整旋转角度模拟昼夜 ——Spot Light:模拟车灯、手电筒的光、舞台灯光 ——Point Light:模拟灯泡 ——Area Light&#…

execv 函数的应用

execv函数族:系统来调用某程序模块 int execl(const char *path, const char *arg, ...); int execlp(const char *file, const char *arg, ...); int execle(const char *path, const char *arg, ..., char * const envp[]); int ex…

Linux 0.11-execve函数-35

Linux 0.11-execve函数-35 execve函数读取文件开头 1KB 的数据解析这 1KB 的数据为 exec 结构判断是脚本文件还是可执行文件准备参数空间设置 eip 和 esp,完成摇身一变累了吧,休息会 转载 execve函数 书接上回,上回书咱们说到,进…

Linux内核Hook系统调用execve

资源下载地址:linux内核hook系统调用execve函数-Linux文档类资源-CSDN下载 (已在内核为 4.19.0-amd64-desktop版本uos编译通过,并成功达到目的) 在Linux系统中,用户层程序无法直接控制系统内核,只能通过系…

执行新程序 execve()

新程序的执行 一:execve() 之所以叫新程序的执行,原因是这部分内容一般发生在fork()和vfork()之后,在子进程中通过系统调用execve()可以将新程序加载到子进程的内存空间。这个操作会丢弃原来的子进程execve()之后的部分,而子进程…

简单的execve流程

本文转载于网络 基于Linux0.11源码来叙述该功能,源码可以在oldlinux.org上自行获取 _sys_execve:lea EIP(%esp),%eax #取堆栈中存放系统调用的返回地址的地址pushl %eax #将该地址入栈call _do_execve #调用do_execve函数addl $4,%esp #丢弃该地址ret这边做了一个很…

Linux0.11系统调用之execve流程解析

Linux0.11系统调用之execve流程解析 前言execve功能介绍execve本质execve系统调用流程总结 前言 本文是基于Linux0.11源码来叙述该功能,源码可以在oldlinux.org上自行获取。 execve功能介绍 execve是用于运行用户程序(a.out)或shell脚本的…

5.execve()到底干了啥?

导语 很多童鞋有分析阅读Linux源代码的强烈愿望,可是Linux内核代码量庞大,大部分人不知道如何下手,以下是我分析Linux源代码的一些经验,仅供参考,有不实之处请大神指正! 1.要想阅读内核首先要进入内核&…

Linux系统编程(再论execve)

文章目录 前言一、execve的第三个参数二、进程空间三、命令行参数规范四、optstring规则的扩展定义总结 前言 本篇文章我们继续来研究一下execve这个系统调用,上篇文章已经讲解了前两个参数的意义了,那么这篇文章就来讲解一下第三个参数的具体含义。 一…

Linux0.11 execve函数(六)

系列文章目录 Linux 0.11启动过程分析(一) Linux 0.11 fork 函数(二) Linux0.11 缺页处理(三) Linux0.11 根文件系统挂载(四) Linux0.11 文件打开open函数(五&#xff09…