本文目录 22 个章节
SRP
1 渲染基础知识

1.1 图形渲染管线
《Render-Time Rendering Third Edition》一书中将计算机图形渲染的流程划分为3个阶段
应用阶段(Application Stage)
准备好要渲染的场景数据,如相机,模型,灯光等信息,为提高性能对不可见的物体进行剔除(Culling),最后设置好每个即将渲染的模型所对应的渲染状态。渲染状态包括但不限于材质,纹理,Shader等。
几何阶段 (Geometry Stage)
该阶段运行在GPU上
- 模型和视图变换 Model and View Transform
- 顶点着色 Vertex Shading 顶点着色阶段的目的即确认顶点处材质的光照效果。像顶点位置,法线等数据都会通过该阶段发送到光栅化阶段。
- 投影 Projection 该阶段就是将模型从三维空间投射到二维空间的过程 常见的投影方式有两种:正交投影,透视投影
- 裁剪 Clipping

当图元完全处于视体内部,直接进入下个阶段
当图元完全处于视体外部,直接丢弃
当图元部分处于视体内部,对图元进行裁剪并产生新的图元
裁剪阶段即对部分处于视体内部的图元进行裁剪操作。
- 屏幕映射 Screen Mapping

进入该阶段顶点坐标仍然是三维的,但x,y在经过上面的投影阶段已经是二维的状态。此时x,y与z坐标组成了窗口坐标系。
假设在一个窗口里对场景进行绘制,窗口最小坐标(x1, y1),最大坐标(x2, y2)。屏幕映射首先进行平移,随后进行缩放,在映射过程中z坐标不受影响。新的x和y坐标称为屏幕坐标系,并和z坐标进入光栅化阶段。
屏幕映射阶段即是将得到的坐标映射到对应的屏幕坐标系上。
光栅化阶段(Rasterizer Stage)
- 三角形设置 Triangle Setup 计算三角形表面的差异和三角形表面的其他相关数据
- 三角形遍历 Triangle Traversal 扫描三角形覆盖的像素区域,并将重合的像素生产片段(fragment)。
- 像素着色 Pixel Shading 逐像素处理着色运算
- 合并 Merging
图形系统一般都是使用双缓冲机制,也就是最终生产的图像会输出到后台缓冲区(backbuffer),然后交换至屏幕。合并阶段就是将前面所有片段操作(如:颜色缓冲区,alpha通道,模板缓冲区,深度测试结果等)所产生的片段颜色合并至后台缓冲区(backbuffer)。
1.2 GPU渲染管线

绿色阶段完全可以编程
蓝色阶段可配置,不可编程
灰色阶段完全固定,不可配置,不可编程
后续知识路径:
Unity中的固定管线
- Deferred Rendering
- Forward Rendering
Unity中的可编程管线
- High Definition Render Pipeline
- LightWeight Render Pipeline
- 自定义渲染管线
2 SRP概述
可编程渲染管线是一个可以通过代码控制渲染的方式的管线。
2.1 解决了什么问题
问题
传统Unity提供了一系列的内置管线供我们使用。包括前向渲染和延迟渲染。这些渲染方式是传统渲染黑盒子的缺点:
- 只能按照他们本身设计的程序执行
- 很一般,它们需要做每一件事,而不能掌控任何流程
- 不可配置。只能在预设的位置注入一些指令
- 拓展性和可修改性有限,内部较小的修改可能导致外部较大的变化 由于改变破坏项目的行为产生Unity无法修复的Bug
解决
SRP Core API 解决了上面描述的问题。其将渲染流程从原来的黑盒转向可控制、预制件、可编程的方向。
2.2 概念与过程
SRP Asset
SRP Asset本身是一个ScriptableObject,我们可以对其进行保存和版本控制。在GraphicsSetting中进行设置,Unity会使用SRP提供的渲染设置。SRP Asset提供了配置渲染管线的接口,当Unity实现第一次渲染的时候,其会调用InternalCreatePipelineCreatePipeline,Asset会返回一个SRP Instance。
[ExecuteInEditMode]
public
class
BasicAssetPipe
:
RenderPipelineAsset
{
public
Color clearColor = Color.green;
#
if
UNITY_EDITOR
// Call to create a simple pipeline
[UnityEditor.MenuItem(
"SRP-Demo/01 - Create Basic Asset Pipeline"
)]
static
void
CreateBasicAssetPipeline
(
)
{
var
instance = ScriptableObject.CreateInstance<BasicAssetPipe>();
UnityEditor.AssetDatabase.CreateAsset(instance,
"Assets/BasicAssetPipe.asset"
);
}
#
endif
protected
override
RenderPipeline
CreatePipeline
(
)
{
return
new
BasicPipeInstance(clearColor);
}
}
SRP Instance
SRP Asset控制配置,但是SRP Instance是真正的渲染的切入点,渲染的逻辑都在SRP Instance中。SRP Instance中包括一个Render function,此方法包括两个变量:ScriptableRenderContext(Command Buffer用于排列渲染相关操作)、Camera(需要渲染的摄像机)。
public
class
BasicPipeInstance
:
RenderPipeline
{
private
Color m_ClearColor = Color.black;
public
BasicPipeInstance
(
Color clearColor
)
{
m_ClearColor = clearColor;
}
protected
override
void
Render
(
ScriptableRenderContext context, Camera[] cameras
)
{
// clear buffers to the configured color
var
cmd =
new
CommandBuffer();
cmd.ClearRenderTarget(
true
,
true
, m_ClearColor);
context.ExecuteCommandBuffer(cmd);
cmd.Release();
context.Submit();
}
}
SRP使用Unity中的CommandBuffers提供相关操作,CommandBuffers中的顺序是根据context传入的数据排序。SRP渲染最后一步需要调用context.Submit()方法,这一步执行render context中相关指令。
SRP Context
SRP渲染使用了延迟执行的方法。如果我们创建了一系列指令并执行它们。用于创建指令的的对象叫ScriptableRenderContext作为一个参数传给Render方法。
SRP中的Culling
- 视锥剔除:只计算在摄像机近裁剪面和远裁剪面之间的游戏物体
- 遮挡剔除:计算那些物体被遮挡了,并将被遮挡的物体进行剔除。
Unity开始渲染第一步是计算哪些可以渲染。这包括选择一个摄像机和进行剔除操作。剔除操作返回一个被摄象机渲染的游戏物体和光照的列表。SRP将在之后的渲染管线中使用这些游戏物体。SRP提供了很多关于剔除的相关API。
//Parameters controlling culling process in CullingResults
ScriptableCullingParameters cullingParams;
Camera.main.TryGetCullingParameters(
out
cullingParams);
//doing culling for each camera
CullingResults cullingResults =
new
CullingResults();
cullingResults = context.Cull(
ref
cullingParams);
SRP中的 Drawing
在SRP中draw需要在culling步骤完成之后进行。
在渲染管线中可配置的部分很多,有一些我们需要在工作之前进行确认:
- 渲染管线的目标硬件、
- 想实现的特殊视觉效果
- 项目的类型
具体的选项:
- HDR vs LDR
- Linear vs Gamma
- MSAA vs Post Process anti-aliasing
- Physically-based Materials vs Simple Materials
- Lighting vs No Lighting
- Lighting technique
- Shadowing technique
实例1:过滤:Render Buckets and Layers
无光照,渲染一些不透明的物体
游戏物体有很多的类别,Unity使用队列的方式对其渲染。这些队列来自Unity存放GameObjects的buckets。当SRP渲染场景的时候,可以指定buckets的范围。
在buckets,可以使用标准的Unity Layers进行过滤。
var
opaqueRange =
new
FilteringSettings();
//FilteringSettings.renderQueueRange : Render objects whose material render queue in inside this range
//这里的渲染队列在[0,GeometryLast]之间是为不透明对象,在[GeometryLast,5000]之间被视为半透明对象。
opaqueRange.renderQueueRange =
new
RenderQueueRange(
0
, (
int
)RenderQueue.GeometryLast);
//layerMask - Only render objects in the given layer mask
//Include all layers
opaqueRange.layerMask = ~
0
;
//??????不懂
实例2:绘制设置:物体如何被绘制出来的
通过前面的filtering和culling的过程,SRP决定了那些是需要渲染的对象,但是还需要进行如何绘制的设置.SRP提供了大量的可选择配置来渲染那些通过了过滤的游戏物体。用于配置的结构体叫做 DrawRenderSettings:允许我们进行配置:
Sorting - 渲染游戏物体的顺序,比如从前向后或从后向前
Per-Renderer flags - 那些内置的设置要Unity传给Shader,这包括像预置的光线探针(probe)、预置的光线贴图
Rendering flags - SRP batching的算法,像instancing 或者 non-instancing
Shader Pass - 当前渲染批次使用哪个Shader pass
//Setting for DrawRenderers.describes how to sort visible objects are sorted and which shader passes to use.
//SortingSettings - This struct describes the methods to sort objects during rendering.
var
ds =
new
DrawingSettings(
new
ShaderTagId(
"Opaque"
),
new
SortingSettings(Camera.main));
ds.enableInstancing =
true
;
//what kind of per-object data to setup during rendering. pass lightprobe and lightmap data to each renderer
ds.perObjectData = PerObjectData.LightProbe | PerObjectData.Lightmaps;
创建一个DrawingSettings对象,并设置这个对象的一些属性。
在完成上面的两个步骤后就可以进行绘制了
Free Camera
添加一个Free Camera组件,可以让摄像机通过键盘和鼠标进行简单的的移动,在Play Mode下进行移动和旋转。
Camera Switcher
Camera Switcher组件可以定义一系列相机,然后在Play Mode中通过Debug Window在这些相机之间进行切换。
2.3 Unity 渲染管线框架
Build-In Render 内置渲染器(默认)兼容太多,反而不能面面俱到,效果不好
Scriptable Render Pipline 可编程渲染管线技术,是Unity提供的新渲染系统,可用C#脚本定制Unity的渲染过程,但自己定制渲染管线对编程要求很高,难度大,所以Unity提供里2个预制的管线,基本上涵盖了我们所有的需求,使用时不需要太底层的技术要求!
High Definition Render Pipeline (HDRP): 高分辨率渲染管线,适用于PC或主机上的AAA级别游戏,同时支持Forward and Deferred 渲染。专注于高端图形渲染,针对高端硬件配置,像PC、XBox 和Playstation,其面向高逼真度的游戏、图形demo和建筑渲染、超写实效果,以及所需的最佳图形效果。同时针对高端图形处理时,它要比内置渲染器要快得多,但如果用来做low poly风格的作品就有点杀鸡用牛刀了,纯属浪费资源和时间;但要想得到完成利用HDRP的完美表现能力,需要大量的贴图,漫反射贴图、高光贴图、金属贴图、平滑贴图、AO贴图、法线贴图、凹凸贴图、高度贴图…So,要做HDRP流程需要非常长的时间和庞大的制作团队,还有充足的预算!建议5人以下的小团队慎入!
Universal Render Pipleline 通用管线流程(URP前身为Lightweight Render Pipeline — LWRP轻量级渲染管线),专注于性能,适用于移动端,URP是选了不会错的渲染管线,它被设计为能够在任何平台上都能提供最好的性能,所以除非有特殊需求只能在HDRP或者SRP解决的,其他都应该选择URP,不管是移动端、主机、PC等,URP都能提供高性能的渲染,目前URP能做的也非常多,它拥有很多HDRP相同的功能,但为了在所有平台达到更好的性能,其做了一定的缩减,但这并不意味着URP做不出漂亮的游戏;
LWRP使用Forward渲染。LWRP使用LWRP和LWRP-VR两种模板。LWRP同样使用自己的Shader,与Unity内置shader不兼容。
这两个内置管线都以package包的形式发布,都包含了Shader Graph编辑器和Post Processing后处理器。
总之
- Build-In Render Pipeline内置渲染管线是Unity提供的固定的、不可编程控制的原始的渲染管线;
- SRP是Unity提供的,一种渲染管线的实现方案——用户可以用C#编程控制渲染过程
- HDRP和URP是Unity基于SRP的方式,提供的两种渲染管线的框架,是SRP实现的两种方案
URP HDRP区别
这两种管线流程都利用里Unity新的可编程渲染管线技术,Unity正在把他们变成新的标准,shader graph,visual effect graph这些新功能都是他们的专属,这两个都是创作shader和粒子特效很棒的工具,也支持VR,不过HDRP做逼真风格的VR性能要求非常高!因为Unity实际上把所有东西渲染2次(因为有两个镜头),所以延迟渲染现在只有HDRP支持,不过对URP的支持官方已经在路上。
两者最大的区别是对光照的支持,HDRP提供高级和丰富的光照功能,比如实时全局光照(RealTime GI),能够模拟光线反射、体积光、能模拟光穿过空气中的粒子,还有重头戏的光线跟踪,一种新的光线反射和阴影渲染技术,其原理是跟踪光线在场景中放射的路径,模拟光线在真实世界里与物体交互的效果,这技术对硬件性能非常高,但能产生非常逼真的效果,可以直接用来做电影级别的预渲染作品。
Global Illumination(全局光照,缩写GI),是3D计算机图形中使用的一组算法通用名称,旨在为3D场景添加更逼真的照明效果。
另外一个区别是Shader,HDRP提供一系列高端的shader特效,例如高度、细节和parallax Maps,分别用于纹理的位移、细节和深度模拟,它还支持子面散射,用于模拟光线穿过很薄的物体,比如皮肤和衣物,它提供了高级的shader,像是stacklit,能够让你同时使用多个材质的属性,比如子面散射、彩虹色、各向异性和模糊参数化。
对于后处理效果,两者不相伯仲,HDRP独占的最重要效果,包括AO(环境光遮蔽)、自动曝光(模拟人眼适应不同光线条件的能力)、屏幕空间反射(模拟基于屏幕上可见物体的反射);URP的AO支持已经在做了,但好东西不是都在HDRP,2D光照和阴影就是URP独占的,所以如果你在做2D游戏,就选URP!
另外两个管线都支持一个很Cool的特效—相机堆叠,让你能够同时用多个相机渲染。
3 总结

4 Ref
https://blog.csdn.net/Game_Builder/article/details/102805829
https://blog.csdn.net/u013477973/article/details/83312809
https://gameinstitute.qq.com/community/detail/127854
https://www.jianshu.com/p/177927be1a62
https://blog.csdn.net/weixin_41622043/article/details/107623694
https://blog.csdn.net/u013477973/article/details/83312809
https://zhuanlan.zhihu.com/p/99142987
https://zhuanlan.zhihu.com/p/93203710 (SRP翻译系列汇总)