SSS材质
SSS材质主要有两点,一种是透射效果,一种是光滑的表面效果。
SH球谐光照
使用IBL计算出来的间接光漫反射其实还是有一些粗糙,这里我们使用SH球谐光照来计算漫反射,性能更好。
计算球谐光照球谐光照不是通过贴图来实现的,而是通过计算得到七个四维参数(SHAr、SHAg、SHAb、SHBr、SHBg、SHBb、SHC)计算得来的。
SH计算工具在Editor文件夹内,分别放置下面两个脚本:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 ...
IBL基于图像的照明
IBL基于图像的照明:基于环境贴图技术,在贴图的基础上通过一系列计算将环境贴图的光照信息提取出来。并将这些信息重新储存回环境贴图中。
使用IBL贴图时,贴图分辨率不要过大,一般选择512即可,
应用IBL间接光镜面反射我们本节依然是使用CubeMap环境贴图,所以对于IBL的采样也是根据CubeMap来采样。
想要在CubeMap中提取出照明信息,只需要将它的导入设置中将Convolution Type改为Specular(Glossy Reflection)即可,然后再将Filter Mode改为Trilinear。
想要看到Unity提取出来的光照信息,需要修改环境贴图的Mipmap层级,在贴图的预览面板,我们只要滑动紫色的小方块旁边的扭就能预览光照了,一般在Mip2或Mip3就能看到效果。
想要拿到Mipmap,我们定义一个Roughness(粗糙度)属性,使用它来取得指定的Mipmap,
123456_Roughness("Roughness", Range(0,1)) = 0 float _Roughness;float mip_level = _ ...
环境贴图
之前的Phong光照模型,计算都是直接光照。除此之外还有间接光照:
间接光漫反射:光照被二次反弹之后的漫反射
烘焙Lightmap
使用Light Probe,它用到了下面介绍的SH球谐光照
间接光镜面反射:光照被二次反弹之后的镜面反射
使用Reflection Probe,它用到了下面介绍的环境贴图和IBL
本节和接下来两节介绍三种技术:
环境贴图:
实现间接光镜面反射,和Refection Probe差不多
IBL基于图像的照明:基于环境贴图技术,在贴图的基础上通过一系列计算将环境贴图的光照信息提取出来。并将这些信息重新储存回环境贴图中。
实现间接光镜面反射
实现间接光漫反射
SH球谐光照:通过球谐函数提取一张贴图的漫反射信息,它不会生成一张新的贴图,而是生成一些球谐数据,计算更快。
用来实现实现间接光漫反射
间接光照知识大纲
环境贴图环境贴图有以下类型:
Cube贴图中:
+Z代表了Front,-Z代表了Back,-X代表了Left,+X代表了Right,-Y代表了Bottom,+Y代表了Top
其中包括了LatLong经纬度全景贴图/ ...
Shadowmap
实时阴影ShadowMap实时阴影的计算:
ShadowMap:传统实时阴影我们假设场景中只有一个主光源平行光,我们假设在这个光源架设一个摄像机,顺着光的方向,这时会采集到一张“光源相机”的深度图,这个图就是ShadowMap。场景中的普通摄像机观察到的每一个片元,都会计算它在“光源相机”中的深度(Unity会提供一个unity_WorldToShadow的矩阵),如果当前片元的深度比ShadowMap的深度要小,那么说明当前片元能被光照亮。
打开Project Settings——Quality,从最下面的Shadows中将Shadow Distance改为15,Shadow Cascades关闭。然后进入Project Settings——Graphic,将High(Tier 3)的Use Defaults取消勾选,再将里面的Cascaded Shadows取消勾选。
然后我们使用下面阴影内置函数一,就能实现最基础的实时阴影。
此时打开Frame Debugger,选择到Shadows.RenderShadowMap展开看到里面的Shadows.RenderJob,就能观察到当前场 ...
色调映射和视差偏移
色调映射(Tone Mapping)普通LDR显示器的亮度范围在0-1之间(普通8bit显示器,每个通道2的八次方256),而Shader计算出来的颜色值很容易超过此范围,属于HDR(10bit,每个通道2的10次方)。
色调映射(Tone-Mapping)就是将高动态范围的图像亮度压缩到低动态的技术。
这里使用ACES色调映射:
接下来我们在Shader中模拟一下这个色调映射,一般情况下,色调映射技术是在后处理过程中应用的,这里仅作为学习。
先在Shader的顶点函数之前声明一个ACES计算函数
123456789float3 ACESFilm(float3 x){ float a = 2.51f; float b = 0.03f; float c = 2.43f; float d = 0.59f; float e = 0.14f; return saturate((x*(a*x + b)) / (x*(c*x + d) + e));}
然后在片元计算的函数中,先把基础的diffuse贴图从gamma空间转换到线性空间:
1 ...
法线贴图
默认情况下,一个模型走的是顶点法线,一个游戏模型的顶点一般很少,所以法线细节也偏低。
使用法线贴图后,在片元阶段就能应用逐像素的法线,这样对于物体表面细节的还原就更加真实。
上图显示的是物体顶点法线,其中蓝色的是法线,绿色的是切线(Tangent),红色的是副法线(或者叫副切线)。这三根线构成了当前顶点的切线空间,我们在切线空间中描述模型的表面信息,并传递到法线贴图中。一般情况下,我们可以认为法线指向z轴,切线指向x轴,父法线指向y轴
在PC端上,法线贴图一般会用DXT/BC进行压缩,只保留红通道,所以需要在Shader中使用UnpackNormal方法,这个方法不仅会还原法线贴图,同时还会将偏移值从[0,1]转到[-1,1],因为法线本来记录的就是每个像素的法线偏移量,取值是-1到1的。
一个物体的切线是引擎自动给出的,在Unity中,切线的方向跟物体uv的u方向一致。而物体的副法线是法线和切线通过叉乘计算出来的。
想要应用法线贴图,我们需要先在顶点着色器中将顶点在世界空间下的法线、切线、副切线信息传递到片元着色器中。
下面对于法线的应用,在ForwardBase和For ...
基本光照
光照计算光照计算由三个重要的组成决定:
光源数据:光源数据受光源类型影响,平行光、点光、聚光灯是不一样的。灯光数据的传递方式由RenderPath来决定。
光源方向LightDir
衰减范围Attenuation
光源颜色LightColor
模型表面材质结构:
顶点法线
法线贴图(像素级法线)
光滑度
PBR理论框架——描述自然界大多数物体的表面材质结构
观察方向
渲染路径前向渲染Unity的Built-in渲染管线和URP渲染管线都是前向渲染。但是URP使用的是forward+渲染,能够使用多盏灯光。
在前向渲染中,每个模型根据自己受光的灯光数量执行一个Pass,如果一个模型除了主光源(平行光)外还受4个其他光源的影响,那么这个模型就要多重复渲染4次,多产生4个DrawCall
Unity对于精细的逐像素光照是有限制的,在Project Setting——Quality里面,Pixel Light Count指定了逐像素光照的光源数量。其中
超出这个数量的灯光会使用逐顶点的光照,并且逐顶点的光照会在ForwardBase这个Pass里面绘制。在Unity中,会根据灯 ...
ASE入门4模板测试
在第二节Alpha Test例子中,我们已经提到,片元Shader计算完成后,进入输出合并阶段,会经过一系列的测试
Alpha Test —— Stencil Test —— Depth Test —— Blending —— Frame Buffer
模板测试发生在Alpha Test之后,深度测试之前
默认情况下,模板缓冲区的值都为零,我们强制让一个模型写入模板缓冲区(取值范围0~255),修改模板比较的规则,就能控制模型的显示。
ASE中的模板测试在ASE中,直接通过左侧的面板勾选Stencil Buffer开始模板测试
Reference :当前模型设置的模板参考值
Read/Write Mask :为了和模板缓冲区做比较用的Mask
Comparison :当前模型设置的模板参考值和模板缓冲区内的值的比较方法,有大于、大于等于、小于、小于等于等多种比较公式,图上的Always表示总是能通过比较。
Pass Front :当前模型前面的模板参考值通过后,对于模板缓冲区的操作,有
Keep :保持当前缓冲区的值不变
Zero :将当前缓冲区的值归零
Replace ...
ASE入门3顶点偏移
在顶点着色器中,使用模型的normal法线方向来在模型空间下偏移顶点的位置。来做出类似藤蔓生长的效果。同时使用ASE的Opacity Mask剔除掉藤蔓一些片元来模拟生长。
Local Vertex Offset在ASE的输出节点中,可以看到Local Vertex Offset插槽,这就是用来在模型空间下偏移顶点的。
Opacity Mask如果想要让ASE实现第二节中所讲的Alpha Test + Clip函数的功能,需要先将Render Queue设置为Alpha Test,会出现Mask Clip Value,这个是根据贴图的明度来剔除的阈值,我们这里设为0,这时ASE的输出节点中Opacity Mask就能使用了,我们可以给它一个黑白贴图,贴图中偏黑的部分就会被剔除。
在藤蔓生长的例子中,我们使用uv的v分量作为黑白贴图来剔除藤蔓的片元,因为v分量正好是顺着藤蔓生长的方向的。
同时,我们还需要将uv的v分量使用SmoothStep来提高一下对比度,使用这个值来控制顶点的偏移,这样藤蔓末梢的偏移就能平滑了。
上图并不是最终版本
Roughness和Smoothness ...