网站结构是体现的工程分包信息平台
news/
2025/10/6 2:00:06/
文章来源:
网站结构是体现的,工程分包信息平台,大连网络产业大厦,wordpress 添加ico1. 透明度测试物体的阴影
对于物体有片元丢弃的情况#xff0c;比如透明度测试或者后边会讲到的消融效果#xff0c;使用默认的 ShadowCaster Pass 会产生问题#xff0c;这是因为该Pass在生成阴影映射纹理时#xff0c;没有考虑被丢弃的片元#xff0c;而是使用完整的模…1. 透明度测试物体的阴影
对于物体有片元丢弃的情况比如透明度测试或者后边会讲到的消融效果使用默认的 ShadowCaster Pass 会产生问题这是因为该Pass在生成阴影映射纹理时没有考虑被丢弃的片元而是使用完整的模型计算深度因此镂空的部分也会向外投射阴影。
要解决这个问题可以使用Unity内置的Pass:
UsePass Legacy Shaders/Transparent/Cutout/VertexLit/CASTER由于该Pass内部在计算阴影时需要用到特定名称的变量因此在使用时必须声明如下属性
Properties
{_MainTex(MainTex, 2D) white{}_Color(Color, Color) (1, 1, 1, 1)_Cutoff(Cutoff, range(0, 1)) 0}除此以外我们也可以自己实现一个 ShadowCaster 的 Pass代码与上一篇【Unity Shader入门精要 第9章】更复杂的光照三中手动实现的 ShadowCaster 基本一样只是在片元着色器中加入和正常渲染 Pass 中一样的剔除代码即可。
另外由于镂空物体的内部也可能产生阴影因此根据需要可以将物体的Cast Shadows选项选为Two Sided
测试Shader如下
Shader MyShader/Chapter_9/Chapter_9_Shadow_AlphaTest_Shader
{Properties{_MainTex(MainTex, 2D) white{}_Color(Color, Color) (1, 1, 1, 1)_Cutoff(Cutoff, range(0, 1)) 0}SubShader{Tags {Queue AlphaTest IgnoreProjector True RenderType TransparentCutout}Pass{Tags {LightMode ForwardBase}Cull FrontCGPROGRAM#pragma vertex vert#pragma fragment frag#include UnityCG.cginc#include Lighting.cginc#include AutoLight.cginc#pragma multi_compile_fwdbasestruct a2v{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;float2 uv : TEXCOORD0;float3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;SHADOW_COORDS(3)};sampler2D _MainTex;float4 _MainTex_ST;fixed _Cutoff;v2f vert(a2v i){v2f o;o.pos UnityObjectToClipPos(i.vertex);o.worldNormal mul(i.normal, (float3x3)unity_WorldToObject);o.uv TRANSFORM_TEX(i.uv, _MainTex);o.worldPos mul(unity_ObjectToWorld, i.vertex).xyz;TRANSFER_SHADOW(o);return o;}fixed4 frag(v2f i) : SV_Target{float3 _worldNormal normalize(i.worldNormal);float3 _worldLight normalize(_WorldSpaceLightPos0.xyz);fixed4 _sampledColor tex2D(_MainTex, i.uv);clip(_sampledColor.w - _Cutoff);fixed3 _ambient UNITY_LIGHTMODEL_AMBIENT.rgb;fixed3 _diffuse _LightColor0.rgb * _sampledColor.xyz * (0.5 * dot(_worldLight, _worldNormal) 0.5);UNITY_LIGHT_ATTENUATION(_atten, i, i.worldPos);return fixed4(_ambient _diffuse * _atten, 1);}ENDCG}Pass{Tags {LightMode ForwardBase}Cull BackCGPROGRAM#pragma vertex vert#pragma fragment frag#include UnityCG.cginc#include Lighting.cginc#include AutoLight.cginc#pragma multi_compile_fwdbasestruct a2v{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;float2 uv : TEXCOORD0;float3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;SHADOW_COORDS(3)};sampler2D _MainTex;float4 _MainTex_ST;fixed _Cutoff;v2f vert(a2v i){v2f o;o.pos UnityObjectToClipPos(i.vertex);o.worldNormal mul(i.normal, (float3x3)unity_WorldToObject);o.uv TRANSFORM_TEX(i.uv, _MainTex);o.worldPos mul(unity_ObjectToWorld, i.vertex).xyz;TRANSFER_SHADOW(o);return o;}fixed4 frag(v2f i) : SV_Target{fixed3 _ambient UNITY_LIGHTMODEL_AMBIENT.rgb;float3 _worldNormal normalize(i.worldNormal);float3 _worldLight normalize(_WorldSpaceLightPos0.xyz);fixed4 _sampledColor tex2D(_MainTex, i.uv);clip(_sampledColor.w - _Cutoff);fixed3 _diffuse _LightColor0.rgb * _sampledColor.xyz * (0.5 * dot(_worldLight, _worldNormal) 0.5);UNITY_LIGHT_ATTENUATION(_atten, i, i.worldPos);return fixed4(_ambient _diffuse * _atten, 1);}ENDCG}//使用内置的Pass处理透明度测试的物体向外投射阴影//UsePass Legacy Shaders/Transparent/Cutout/VertexLit/CASTER//或者根据渲染逻辑手动实现符合当前效果的ShadowCaster的PassPass{Tags { LightMode ShadowCaster }CGPROGRAM#pragma vertex vert#pragma fragment frag#include UnityCG.cginc#pragma multi_compile_shadowcasterstruct a2v{float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 normal : NORMAL;};struct v2f{V2F_SHADOW_CASTER;float2 uv : TEXCOORD0;};sampler2D _MainTex;float4 _MainTex_ST;fixed _Cutoff;v2f vert(a2v v){v2f o;o.uv TRANSFORM_TEX(v.uv, _MainTex);TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);return o;}fixed4 frag(v2f i) : SV_Target{fixed4 _sampledColor tex2D(_MainTex, i.uv);clip(_sampledColor.w - _Cutoff);SHADOW_CASTER_FRAGMENT(i);}ENDCG }}}
效果如下
2. 透明度混合物体的阴影
2.1 投射阴影
透明度混合的Shader中关闭了深度写入不会参与深度纹理的计算因此不会向其他物体投射阴影。要使透明度测试的物体能够向外投射阴影方法有很多比如放一个直接算阴影但不渲染自身的代替物体或者像书中说的添加一个非Transparent的FallBack的Shader再或者自己手写一个都可以实现。
下面的例子就是将之前的阴影投射的Pass复制过来也可以正常产生阴影。
Shader MyShader/Chapter_9/Chapter_9_Shadow_AlphaBlend_Shader
{Properties{_MainTex(MainTex, 2D) white{}}SubShader{Tags { Queue Transparent RenderType Transparent IgnoreProjector True}Pass{Tags {LightMode ForwardBase}Cull FrontZWrite OffBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fwdbase#include UnityCG.cginc#include Lighting.cginc#include AutoLight.cgincstruct a2v{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;float2 uv : TEXCOORD0;float3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;SHADOW_COORDS(3)};sampler2D _MainTex;float4 _MainTex_ST;v2f vert(a2v i){v2f o;o.pos UnityObjectToClipPos(i.vertex);o.worldNormal UnityObjectToWorldNormal(i.normal);o.worldPos mul(unity_ObjectToWorld, i.vertex).xyz;o.uv TRANSFORM_TEX(i.uv, _MainTex);TRANSFER_SHADOW(o);return o;}fixed4 frag(v2f i) : SV_Target{fixed3 _ambient UNITY_LIGHTMODEL_AMBIENT.rgb;float3 _worldNormal normalize(i.worldNormal);float3 _worldLight normalize(_WorldSpaceLightPos0.xyz);float4 _mainColor tex2D(_MainTex, i.uv);fixed3 _diffuse _LightColor0.rgb * _mainColor.xyz * (0.5 * dot(_worldLight, _worldNormal) 0.5);UNITY_LIGHT_ATTENUATION(_atten, i, i.worldPos);return fixed4(_ambient _diffuse * _atten, _mainColor.w);}ENDCG}Pass{Tags {LightMode ForwardBase}Cull BackZWrite OffBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fwdbase#include UnityCG.cginc#include Lighting.cginc#include AutoLight.cgincstruct a2v{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;float2 uv : TEXCOORD0;float3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;SHADOW_COORDS(3)};sampler2D _MainTex;float4 _MainTex_ST;v2f vert(a2v i){v2f o;o.pos UnityObjectToClipPos(i.vertex);o.worldNormal UnityObjectToWorldNormal(i.normal);o.worldPos mul(unity_ObjectToWorld, i.vertex).xyz;o.uv TRANSFORM_TEX(i.uv, _MainTex);TRANSFER_SHADOW(o);return o;}fixed4 frag(v2f i) : SV_Target{fixed3 _ambient UNITY_LIGHTMODEL_AMBIENT.rgb;float3 _worldNormal normalize(i.worldNormal);float3 _worldLight normalize(_WorldSpaceLightPos0.xyz);float4 _mainColor tex2D(_MainTex, i.uv);fixed3 _diffuse _LightColor0.rgb * _mainColor.xyz * (0.5 * dot(_worldLight, _worldNormal) 0.5);UNITY_LIGHT_ATTENUATION(_atten, i, i.worldPos);return fixed4(_ambient _diffuse * _atten, _mainColor.w);}ENDCG}Pass{Tags { LightMode ShadowCaster }CGPROGRAM#pragma vertex vert#pragma fragment frag#include UnityCG.cginc#pragma multi_compile_shadowcasterstruct v2f{V2F_SHADOW_CASTER;};v2f vert(appdata_base v){v2f o;TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);return o;}fixed4 frag(v2f i) : SV_Target{SHADOW_CASTER_FRAGMENT(i);}ENDCG}}// FallBack VertexLit
// FallBack Diffuse
}
效果
2.2 接收阴影
半透物体接收阴影就比较麻烦了即使像书中说的将FallBack设置为 VertexLit实际也是无法接收到阴影的可以将上面测试shader中的注释放开试一下。
这是因为正常半透物体的渲染队列为3000Transparent而在2500以后就没有阴影映射纹理的信息了因此即使shader里有相应代码也无法正常接收到阴影。
从下面 FrameDebug 的截图中也可以看出来 网上最多的说法是将渲染队列强制调到2500以下比如像这样 这样虽然能接收到阴影但显然不是正经做法因为这样会造成半透物体的渲染顺序错乱比如这样 要真正解决这个问题内容就超出《入门精要》的范围了也超出我的范围了。 这里先存本书《实时阴影技术》有时间开坑研究一下应该是不会有时间了。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/928915.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!