实习的悲惨事故,主要在两个细小得错误上花费了特别多的时间,两个都是出在宏定义的地方,先把这个东西高高挂起
#pragma multi_compile_fwdadd
写成了multi_comple_fwdadd,导致在写多光源部分找了很久没找到问题,一直以为是代码逻辑出错
光照
光照计算的思考方式
- 光源
- 模型表面材质结构
- 观察方向
光源
- 光源类型
- 聚光灯和点光有衰减
- 光源方向
- 光源颜色
- 灯光数据传递方式—RenderPath
- Forward 前向渲染
- Unity内置渲染管线Built-in
- Unity URP渲染管线
- 光照方面,能够在单个pass处理多个灯光
- Deferred 延迟渲染:以灯光为单位进行渲染,因为使用了MRT
- UE4默认路径
- Unity UDRP渲染管线
- Forward 前向渲染
RenderPath
决定了shader是以怎样的一个规则去计算灯光的
前向渲染:unity内置的渲染管线, unity URP渲染管线
延迟渲染:UE4默认渲染路径, Unity HDRP渲染管线
前向渲染:物体被重复叠加绘制多次(实时灯光的数量)
forwardadd函数
前向渲染的消耗问题,引擎edit -> project setting -> quality -> pixel light count,不调整会出现粗糙灯光
超过了light count的灯光,就会被当作顶点光源,只能在顶点shader里进行计算
需要shader里面写两个pass:
- forward base:主方向光,也处理超出数量的顶点灯光
- forward pass:结果通过 blend one one的方式进行叠加
延迟渲染:
主要两个阶段
- RenderDeferred gbuffer
这里使用了MRT — Multi Render Target
RT0 diffuse
RT1 金属度
RT2 法线数据
Depth 深度 - RenderDeferred lighting
以灯光为单位对场景进行渲染,因为把需要的信息已经提前渲染好了
延迟渲染对多光源友好,有一定使用瓶颈,占用带宽高,普通机型可能受不了,前向渲染就很轻量化
怎么判断是否是主方向光 — 光的亮度最大那个
模型表面材质结构
- 顶点法线
- 法线贴图
- 光滑度
- PBR理论框架
多光源的实现
通过forwardadd pass实现
第二个pass修改地方
1 | Tags{"LightMode"="ForwardAdd"} |
衰减的计算
1 |
|
法线贴图
思路:
切线是在模型导入的时候确定的,根据UV中U方向走向定义的
再通过法线和切线cross得到副切线,就构成了切线空间
在shader中关键点在tangent.w分量的处理,主要是用来处理不同平台法线反转的问题
压缩格式问题:PC上DXT/BC对法线贴图压缩,这样通道信息就会变更,只剩红色通道和alpha通道(所以红色不一定是错的)
在shader还需要解码操作,因为法线贴图范围是[0,1],但是法线数据需要[-1,1]
1 | vert(appdata v){ |
blinn-phong
在phong上进行了优化,使用了半程向量
半程向量是光照和视线方向的中间
1 | half3 half_dir = normalize(light_dir + view_dir); |
显示器的输出结果是在0-1的,但是shader的返回值可以很大,因此会有过曝