前面用几篇文章介绍了标准光照模型的基础光照算法,世间事物是对立统一的,有光自然就有影,所谓阴影就是对光的遮挡。
因此本文就介绍一下通过材质模拟阴影的实现方法。
与光的反射相同,阴影自然也有光源的投影以及环境光的阴影,而后者一般称为环境遮挡(Ambient Occulusion)或者环境闭塞、环境隔绝。
光源投影
在Unity中计算投影的方式如下
这个Light Attenuation节点可以用来计算物体的投影以及点光源的衰减。
shader代码如下:
// shader的路径和名称 Shader "Shader Forge/shadow" { // 自定义Base Color Properties { } SubShader { Tags { "RenderType"="Opaque" } Pass { Name "FORWARD" Tags { "LightMode"="ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "AutoLight.cginc" // 使用Unity投影必须包含这两个库文件 #include "Lighting.cginc" // 同上 #pragma multi_compile_fwdbase_fullshadows #pragma target 3.0 // 输入结构 struct VertexInput { // 输入顶点的位置 float4 vertex : POSITION; }; // 输出结构 struct VertexOutput { // 输出顶点的投影位置 float4 pos : SV_POSITION; // Unity封装的投影用座标信息 LIGHTING_COORDS(0,1) }; // 顶点shader VertexOutput vert (VertexInput v) { VertexOutput o = (VertexOutput)0; o.pos = UnityObjectToClipPos( v.vertex ); // Unity封装的投影信息处理函数 TRANSFER_VERTEX_TO_FRAGMENT(o) return o; } // 像素shader float4 frag(VertexOutput i) : COLOR { // 取出投影 float shadow = LIGHT_ATTENUATION(i); return float4(shadow, shadow, shadow, 1); } ENDCG } } FallBack "Diffuse" }
而在UE4中,实现投影的材质节点图如下:
原理是将UV向光的物体切线方向进行偏移,再对mask贴图(比如高度贴图)进行采样,最后和Lambert相乘。
实现效果如下:
环境遮挡
首先请观察下面的图片
可以看出右侧图片视觉效果更为真实立体,原因是小球之间互相遮挡的部位阴影更明显,也就是深度越深距离越近遮挡越多,越难以被光线照亮,这样也更符合现实世界的实际光影表现。
因此有了环境光遮挡的出现,通过模型的面之间的遮挡关系,计算出一张单色贴图,代表模型之间的遮挡关系,黑色的部分遮挡更多,更难以被光照亮,这就是环境光遮挡贴图(Ambient Occution),也称为AO贴图。
在前文光照模型基础之环境光照一文中有介绍过多色环境光的制作方法,如果要考虑到环境光遮挡,则完整的节点如下:
将环境光颜色对AO贴图进行采样即可,而镜面反射同理。
这样一来,AO贴图黑色的部分就是对环境光的遮挡,也就是环境阴影。
有了上面的投影和环境光遮挡,再结合前面几篇文章,参考下图就可以实现一个比较完整的基础光照模型了,篇幅问题这里就不放整合版了。
光源投影的UE4自阴影算法参考自九猫的知乎,其他参考自B站庄懂的技术美术入门课,感谢。
不存在对所有人都有用的人
评论
还没有任何评论,你来说两句吧!