周五要面试,狠狠进行一个临阵磨枪。
PBR
- 物理原理和微表面理论
- 能量守恒:入射=反射+折射,金属无折射,非金属折射部分散射后出射→漫反射
- BxDF
- 渲染方程: 求入射方向半球积分。
- BRDF漫反射项:传统Lambert(无roughness/fresnel,Unity移动端用),基于物理Oren-Nayar/Disney(Unity)等
- BRDF镜面反射项:D(NDF法线分布函数)/F(菲涅尔)/G(几何函数) Microfacet Cook-Torrance BRDF 其中分母 4(n·l)(n·v):校正因子(correctionfactor),作为微观几何的局部空间和整个宏观表面的局部空间之间变换的微平面量的校正。 业内常用:D - GGX,F - Schlink(lerp((1-(v·h)^5,1,F0)),G - Schlink-GGX(UE)/Smith-GGX(Unity) 这里留一个毛老师的F0速查表,注意金属的F0是float3,非金属是float。
- 白炉测试:验证入射总能量为1的光线的反射光线分布是否归一化的测试
- 基于物理光照:漫反射(辉度环境映射)+环境光照(IBL)
- 环境光照Image Based Lighting:分解为预过滤环境贴图+环境BRDF 毛星云的白皮书: 【基于物理的渲染(PBR)白皮书】(一) 开篇:PBR核心知识体系总结与概览 【基于物理的渲染(PBR)白皮书】(二) PBR核心理论与渲染光学原理总结
SRP
My SRP
咱时间有限,官方文档的内容就不重复了,划重点:
- A Render Pipeline Instance. This is an instance of a class defines the functionality of your render pipeline. Its script inherits from RenderPipeline, and overrides its Render() method.
- A Render Pipeline Asset. This is an asset in your Unity Project that stores data about which Render Pipeline Instance to use, and how to configure it. Its script inherits from RenderPipelineAsset and overrides its CreatePipeline() method.
其中Instance的Render方法中有一个很重要的变量ScriptableRenderContext,用于执行绘图命令。需要将命令输入CommandBuffer类,然后调用Context的ExecuteCommandBuffer方法依次执行命令。
CommandBuffer和ScriptableRenderContext都用于记录我们的指令,我们可以创建多个CommandBuffer用于记录不同的指令,但是ScriptableRenderContext只有一个,并且是Unity为我们提供好的。每一个CommandBuffer可以有自己的名称(使用name属性设置),可以记录各种命令,可以使用Clear方法被清空。所有的CommandBuffer最终都需要合并到ScriptableRenderContext中,并且在调用Submit方法的时候被一次性执行。
c#补课时间:
- Var是C#3.5新增的一个关键字,用来代替某些具体的类型,由编译器自动判断变量类型,编译器可以根据变量的初始化值“推断”变量的类型。 必须在定义时初始化,必须是局部变量。
- C#中,方法的参数传递有四种类型:传值(by value),传址(by reference),输出参数(by output),数组参数(by array)。传址参数需要修饰符ref,输出参数需要修饰符out,数组参数需要修饰符params。
对比了一下URP的代码,首先是一些C#补课:
- sealed作为形容词是封闭的,未知的。sealed修饰类时说明该类将不能被继承或重写,修饰方法(函数或属性)时可防止扩充类重写此方法(函数或属性)。通常用于实现第三方类库时不想被客户端继承,或用于没有必要再继承的类以防止滥用继承造成层次结构体系混乱。恰当的使用sealed修饰符也可以在一定程度上提高运行效率,因为不用考虑继承类会重写该成员。
- Partial是局部类型的标志。 局部类型可以实现将一个类、结构或接口分成几个部分,分别放在在几个不同的.cs文件中(当然也可以放在同一个.cs文件中)。 在程序进行编译之后,将会合并成一个完整的类。
延迟渲染设置
这里直接使用了知乎的设置:
一共有 4 块颜色缓冲和一块深度缓冲。其中 GT0 使用 ARGB32 格式作为 Albedo。GT1 则直接照抄 Unity 使用 ARGB2101010 格式存储世界空间下的法线。GT2 使用 ARGB64 格式,RG 存 Motion Vector,BA 存 roughness 和 metallic,16 bit per channel 足够保证精度。GT3 使用 ARGBFloat 格式,其中 RGB 存储 emission color 而 A 存储 occlusion,因为之后想支持 HDR 和 Bloom 所以需要更高的精度。 Multi Render Target(MRT)技术允许像素着色器输出多个颜色,他们被暂存到一组纹理缓冲区中,以便后续光照阶段使用。 这个步骤需要现在pipeline的构造函数中创建gdepth和gbuffers4纹理,然后render函数中将其设置为rendertarget,并开放为全局变量。对应的shader在片元着色器通过SV_target0/1/2/3可以输出到不同渲染目标。