当前位置: 代码迷 >> 综合 >> unity shader 基础 之 九十 渲染路径、阴影、高级纹理
  详细解决方案

unity shader 基础 之 九十 渲染路径、阴影、高级纹理

热度:50   发布时间:2023-11-21 16:13:07.0

9.1 渲染路径

在project setting 里面可以设置默认的渲染路径,但是在每个摄像机上面也可以设置,从而覆盖默认的渲染路径

常见的LightMode:

9.1.1 前向渲染

前向渲染的光照模型分为两种:一种是LightMode="ForwardBase"  一种是LightMode="ForwardAdd"

FB:只渲染一次,只进行最亮的逐像素光照渲染,以及所有逐顶点光照和SH光照

需要添加的宏定义:

#pragma multi_compile_fwdbase 获取相应的光照变量

 FA:其它每个逐像素的光照,都要渲染一次

需要添加的宏定义:

#pragma multi_compile_fwdadd、#pragma multi_compile_fwdadd_fullshadows

9.1.2 延迟渲染

延迟渲染是把数据渲染到G-Buffer中,通过两个pass来完成,第一个pass不进行光照计算,只进行把数据处理后存储到G-Buffer中,这个G-Buffer包含多个渲染纹理用来分别存储法线、位置、深度信息等,在第二个pass中进行光照计算

延迟渲染不受光源的影响,只和屏幕的大小有关,屏幕大,则数据多,延迟渲染对硬件有一定的要求,需要支持MRT,因为它把不同的数据存储到不同的RT里面

9.2 光源类型

一个物体能接受的逐像素光源是有限的的,这个设置在quality面板,默认接受除最亮的平行光之外的四个逐像素光照,这个和shader mode也是有关的,不同的shader mode 处理光照的能力是不同的,也就是说如果你有其它满足逐像素光照条件的光源(比如 render mode 设置为 important),就会按照光照强度的排列顺序,从高到低依次渲染,直到达到逐像素的光源限制数量或者逐像素光源的数量

9.3 光源衰减

在内置渲染管线中,光源的衰减和光源强度、与光源的距离两者有关,在URP、HDRP中,光源的衰减只和光源强度有关,和距离无关,这一系列都是内置渲染管线

unity的光源衰减是通过对一张光源衰减图根据距离进行采样获得的,然后与漫反射、高光反射的和相乘

平行光没有衰减,所以衰减系数为1

_LightMatrix0 是从世界空间到光源空间的旋转矩阵,通过距离的平方,采样,然后通过 UNITY_ATTEN_CHANNEL 来获取衰减的值

9.4 阴影

阴影分为两个部分,一个是投射阴影,一个是接收阴影

9.4.1 投射阴影

unity 使用的是屏幕空间阴影投射方式,通过摄像机的深度贴图和一张shadow map,生成一张屏幕阴影贴图(包含了屏幕空间的阴影信息)

摄像机的深度贴图,在延迟渲染中是本来就存在的,但是在前向渲染中,如果通过base pass和 add pass 得到,比较浪费性能,所以通过LightMode 为 shadow caster 的pass 专门来渲染深度纹理信息,它记录了离摄像机最近的表面信息,比如点的位置,法线等

另一张是shadow map  ,这是一张把摄像机放在光源位置,得到的一张深度图,它也是只记录了离它最近的表面信息,这张shadow map 是一个RT,所以屏幕空间纹理技术,需要设备支持MRT

最后一张是屏幕空间阴影贴图,包含了场景中阴影信息的,首先,我们通过摄像机的深度贴图得到该点的世界空间坐标,从而获得到光源距离,然后用该点的xy对shadow map 进行纹理采样,获取到shadow map 中存储的深度值,如果该深度值小于 原来的距离,则说明 该点处于阴影中,那么绘制阴影贴图的时候,就要按阴影来绘制

Coding Labs :: Deferred Rendering Shadow Mapping

Unity5.X中屏幕空间阴影投射技术(Screenspace ShadowMap)如何产生阴影图? - 知乎

V2F_SHADOW_CASTER :定义阴影投射的变量

TRANSFER_SHADOW_CASTER_NORMALOFFSET(V2F)

SHADOW_CASTER_FRAGMENT(V2F)

默认的物体的投射阴影只投射物体的正面,可以开启two  side 开启双面阴影投射

9.4.2 接收阴影

物体要接收阴影,就是对阴影贴图纹理进行采样,然后和(漫反射+高光反射)*shadow

SHADOW_COORDS(TexcoordsIdx):声明一个插值器

TRANSFER_SHADOW(V2F):根据不同的平台,转换顶点坐标从模型坐标转换到光源空间,存储到上面声明的插值器中

SHADOW_ATEENUATION

缺点:

上述可以通过级联阴影解决

9.4.3 统一管理光照衰减和阴影

 UNITY_LIGHT_ATTENUATION(atten,v2f,v2f.worldPos)

atten 就是我们最后的值,这个方法把衰减和阴影相乘的值赋予到attention 上,然后我们就可以直接用了

#param multi_compile_fulladd 只在base pass中计算一次逐像素的阴影

如果想在additional 里面叠加其它逐像素的光照阴影的话,就要添加变量#param multi_compile_fulladd_fullshadows

9.4.4 透明物体的阴影

透明物体的阴影 主要是shadow map的生成上,要进行透明度测试,fallback 采用内置的Transparent/VertexLit

10.1 立方体纹理

立方体纹理六张图,物体可以对其采样,从而在表面形成一层倒影

unity 把当前场景渲染到cubemap,

Camera.RenderToCubemap

10.1.1 反射

通过反射方向 对 立方体纹理进行采样

然后采样结果和漫反射结果混合

texCUBE(cubemap,reflectDir).rgb,对立方体纹理采样

10.1.2 折射

这里直接用的是第一次折射方向,对立方体纹理采样,实际上应该是第二次折射方向

折射满足 斯涅耳定律

 refract(-normalize(worldViewDir),normalize(worldNormal),refractRatio)

第三个参数是两种介质的折射率的比值

上述计算的是折射方向

10.2 渲染到纹理

渲染到纹理一共有三种方法

1.创建一张RT,然后让摄像机渲染到该RT上

2.使用GrabPass 生成一张】

3.在OnRenerImage函数里获取当前屏幕图像

10.2.1 镜子效果

对屏幕图像采样,然后翻转x 的uv坐标

10.2.2 玻璃效果

玻璃效果就是对像素进行一个扰动

首先使用GrabPass得到当前的裁剪空间下的坐标,并不是NDC坐标,取值范围是[near,far]

o.screenPos=ComputeGrabScreenPos(o.worldPos)

然后对法线贴图进行采样,得到的是切线空间下的切线

然后用该切线对裁剪空间下的屏幕坐标进行偏移,然后得到该屏幕坐标的NDC坐标,范围在[0,1]之间 ,再用这个坐标对折射贴图采样,得到的是折射贴图的颜色

然后把法线转换到世界空间下,得到反射贴图的颜色,最后混合

切线空间-世界空间的旋转矩阵,先得到世界空间下的法线和切线,然后再通过叉乘得到副切线,然后按列排列

10.2.3 程序纹理

生成一个texture2D

 

  相关解决方案