TA-Shader-文件 Unity Shader | 遮挡透视显示解决方案
发布于
2022-4-11
1813
1
TA资源类型
TA资源类型: 算法思路 
shader资源类型: shader代码 
适用引擎: unity 
资源介绍: 转自 又不是非我不可 https://zhuanlan.zhihu.com/p/495772145

您需要 登录 才可以下载或查看,没有账号?注册

x
效果图
v2-5b31bc25df852ba1acab76c2987d766d_720w.jpg
x - ray 透视效果

原理
  • 物体被遮挡 --> 深度测试不通过
  • 深度测试通过的部分用普通光照pass
  • 深度测试不通过的部分用透视着色pass

伪代码
  1. Pass
  2. {
  3.     //深度测试通过的pass
  4.     //普通光照着色
  5.     //...
  6. }
  7. Pass
  8. {
  9.     //深度测试不通过的pass
  10.     //为了使被遮挡的部分被绘制, 则修改深度测试规则
  11.     ZTest Greater
  12.     //...
  13. }
点击此处复制文本



代码
  1. Shader "ZLearn/SimpleAlpha_XRay"
  2. {
  3.     Properties
  4.     {
  5.         [HDR]_XRayCol ("XRay Color", Color) = (1, 1, 1, 1)
  6.         _XRayFresPow ("XRay Fresnel Pow", Float) = 5
  7.     }
  8.     SubShader
  9.     {        
  10.         //lighting pass
  11.         Pass
  12.         {
  13.             Tags {"LightMode" = "ForwardBase"}

  14.             CGPROGRAM
  15.             #pragma vertex vert
  16.             #pragma fragment frag
  17.             #pragma multi_compile_fwdbase
  18.             #include "UnityCG.cginc"
  19.             #include "Lighting.cginc"

  20.             struct appdata
  21.             {
  22.                 float4 vertex : POSITION;
  23.                 float2 texcoord : TEXCOORD0;
  24.                 float3 normal : NORMAL;
  25.             };
  26.         
  27.             struct v2f
  28.             {
  29.                 float4 pos : SV_POSITION;
  30.                 float2 uv : TEXCOORD0;
  31.                 float3 wNor : TEXCOORD1;
  32.             };
  33.         
  34.             float _Alpha;
  35.         
  36.             v2f vert (appdata v)
  37.             {
  38.                 v2f o;
  39.                 o.pos = UnityObjectToClipPos(v.vertex);
  40.                 o.uv = v.texcoord;
  41.                 o.wNor = UnityObjectToWorldNormal(v.normal);
  42.                 return o;
  43.             }
  44.         
  45.             fixed4 frag (v2f i) : SV_Target
  46.             {
  47.                 float3 lDir = normalize(_WorldSpaceLightPos0.xyz);
  48.                 float LdN = dot(lDir, i.wNor);
  49.                 fixed4 col = 1;
  50.                 col.xyz = LdN * 0.5 + 0.5;//用简单的半兰伯特光照模型
  51.                 return col;
  52.             }
  53.             ENDCG
  54.         }

  55.         //x ray pass
  56.         Pass
  57.         {
  58.             Tags { "RenderType" = "Transparent" "Queue" = "Transparent" "IgnoreProjector" = "True"}
  59.             Blend SrcAlpha OneMinusSrcAlpha
  60.             ZWrite Off
  61.             Cull Back
  62.             ZTest Greater

  63.             CGPROGRAM
  64.             #pragma vertex vert
  65.             #pragma fragment frag
  66.             #include "UnityCG.cginc"

  67.             struct appdata
  68.             {
  69.                 float4 vertex : POSITION;
  70.                 float2 texcoord : TEXCOORD0;
  71.                 float3 normal : NORMAL;
  72.             };

  73.             struct v2f
  74.             {
  75.                 float4 pos : SV_POSITION;
  76.                 float2 uv : TEXCOORD0;
  77.                 float3 wNor : TEXCOORD1;
  78.                 float3 wPos : TEXCOORD2;
  79.             };

  80.             float4 _XRayCol;
  81.             float _XRayFresPow;

  82.             v2f vert (appdata v)
  83.             {
  84.                 v2f o;
  85.                 o.pos = UnityObjectToClipPos(v.vertex);
  86.                 o.uv = v.texcoord;
  87.                 o.wNor = UnityObjectToWorldNormal(v.normal);
  88.                 o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  89.                 return o;
  90.             }

  91.             fixed4 frag (v2f i) : SV_Target
  92.             {
  93.                 float3 vDir = normalize(_WorldSpaceCameraPos.xyz - i.wPos);
  94.                 float fres = dot(vDir, i.wNor);
  95.                 fres = pow(1 - fres, _XRayFresPow);
  96.                 fixed4 col = fres * _XRayCol;
  97.                 col.a = saturate(col.a);
  98.                 return col;
  99.             }
  100.             ENDCG
  101.         }
  102.     }
  103. }
点击此处复制文本



虽然被其他物体遮挡的部分有了透视效果, 但自身遮挡自身的部分, 也出现了不希望的透视效果
v2-dcd919164ed9a59c0f9f5fca726d7fe8_720w.jpg

自遮挡解决方案
伪代码
  1. Pass
  2. {
  3.     //深度测试通过的pass
  4.     //普通光照着色
  5.     Stencil
  6.     {
  7.         Ref 1 //设定值为1
  8.         Comp GEqual //该ref值(1)比缓冲中的值大于等于时通过
  9.         Pass Replace //通过后写入值
  10.     }
  11.     //...
  12. }
  13. Pass
  14. {
  15.     //深度测试不通过的pass
  16.     //为了使被遮挡的部分被绘制, 则修改深度测试规则
  17.     ZTest Greater
  18.     Stencil
  19.     {
  20.         Ref 0 //设定值为0
  21.         Comp Equal //缓冲的值为0才能通过, pass1中自身覆盖像素模板缓冲为1, 则pass2不会通过
  22.         Pass Keep //通过后缓冲值不变
  23.     }
  24.     //...
  25. }
点击此处复制文本



代码
  1. Shader "ZLearn/SimpleAlpha_XRay"
  2. {
  3.     Properties
  4.     {
  5.         [HDR]_XRayCol ("XRay Color", Color) = (1, 1, 1, 1)
  6.         _XRayFresPow ("XRay Fresnel Pow", Float) = 5
  7.     }
  8.     SubShader
  9.     {        
  10.         //lighting pass
  11.         Pass
  12.         {
  13.             Tags {"LightMode" = "ForwardBase"}
  14.             Stencil
  15.             {
  16.                 Ref 1
  17.                 Comp GEqual //该ref值(1)比缓冲中的值大于等于时通过
  18.                 Pass Replace
  19.             }

  20.             CGPROGRAM
  21.             #pragma vertex vert
  22.             #pragma fragment frag
  23.             #pragma multi_compile_fwdbase
  24.             #include "UnityCG.cginc"
  25.             #include "Lighting.cginc"

  26.             struct appdata
  27.             {
  28.                 float4 vertex : POSITION;
  29.                 float2 texcoord : TEXCOORD0;
  30.                 float3 normal : NORMAL;
  31.             };
  32.         
  33.             struct v2f
  34.             {
  35.                 float4 pos : SV_POSITION;
  36.                 float2 uv : TEXCOORD0;
  37.                 float3 wNor : TEXCOORD1;
  38.             };
  39.         
  40.             float _Alpha;
  41.         
  42.             v2f vert (appdata v)
  43.             {
  44.                 v2f o;
  45.                 o.pos = UnityObjectToClipPos(v.vertex);
  46.                 o.uv = v.texcoord;
  47.                 o.wNor = UnityObjectToWorldNormal(v.normal);
  48.                 return o;
  49.             }
  50.         
  51.             fixed4 frag (v2f i) : SV_Target
  52.             {
  53.                 float3 lDir = normalize(_WorldSpaceLightPos0.xyz);
  54.                 float LdN = dot(lDir, i.wNor);
  55.                 fixed4 col = 1;
  56.                 col.xyz = LdN * 0.5 + 0.5;//用简单的半兰伯特光照模型
  57.                 return col;
  58.             }
  59.             ENDCG
  60.         }

  61.         //x ray pass
  62.         Pass
  63.         {
  64.             Tags { "RenderType" = "Transparent" "Queue" = "Transparent" "IgnoreProjector" = "True"}
  65.             Blend SrcAlpha OneMinusSrcAlpha
  66.             ZWrite Off
  67.             Cull Back
  68.             ZTest Greater

  69.             Stencil
  70.             {
  71.                 Ref 0
  72.                 Comp Equal
  73.                 Pass Keep
  74.             }

  75.             CGPROGRAM
  76.             #pragma vertex vert
  77.             #pragma fragment frag
  78.             #include "UnityCG.cginc"

  79.             struct appdata
  80.             {
  81.                 float4 vertex : POSITION;
  82.                 float2 texcoord : TEXCOORD0;
  83.                 float3 normal : NORMAL;
  84.             };

  85.             struct v2f
  86.             {
  87.                 float4 pos : SV_POSITION;
  88.                 float2 uv : TEXCOORD0;
  89.                 float3 wNor : TEXCOORD1;
  90.                 float3 wPos : TEXCOORD2;
  91.             };

  92.             float4 _XRayCol;
  93.             float _XRayFresPow;

  94.             v2f vert (appdata v)
  95.             {
  96.                 v2f o;
  97.                 o.pos = UnityObjectToClipPos(v.vertex);
  98.                 o.uv = v.texcoord;
  99.                 o.wNor = UnityObjectToWorldNormal(v.normal);
  100.                 o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  101.                 return o;
  102.             }

  103.             fixed4 frag (v2f i) : SV_Target
  104.             {
  105.                 float3 vDir = normalize(_WorldSpaceCameraPos.xyz - i.wPos);
  106.                 float fres = dot(vDir, i.wNor);
  107.                 fres = pow(1 - fres, _XRayFresPow);
  108.                 fixed4 col = fres * _XRayCol;
  109.                 col.a = saturate(col.a);
  110.                 return col;
  111.             }
  112.             ENDCG
  113.         }
  114.     }
  115. }
点击此处复制文本



效果


Surface Shader
  • 若不想从unlit shader入手, 直接使用pbr shader, 可使用surface shader
  1. Shader "ZLearn/Surf_XRay"
  2. {
  3.     Properties
  4.     {
  5.         _Color ("Color", Color) = (1,1,1,1)
  6.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
  7.         _Metallic ("Metallic", Range(0,1)) = 0.0

  8.         [Space(20)]
  9.         [HDR]_XRayCol ("XRay Color", Color) = (1, 1, 1, 1)
  10.         _XRayFresPow ("XRay Fresnel Pow", Float) = 5
  11.     }
  12.     SubShader
  13.     {
  14.         //lighting pass
  15.         Tags { "RenderType" = "Opaque" }
  16.         Stencil
  17.         {
  18.             Ref 1
  19.             Comp GEqual
  20.             Pass Replace
  21.         }
  22.         CGPROGRAM
  23.         #pragma surface surf Standard fullforwardshadows addshadow
  24.         struct Input
  25.         {
  26.             float2 uv_texcoord;
  27.         };
  28.         half _Glossiness;
  29.         half _Metallic;
  30.         fixed4 _Color;
  31.         UNITY_INSTANCING_BUFFER_START(Props)
  32.         UNITY_INSTANCING_BUFFER_END(Props)
  33.         void surf (Input IN, inout SurfaceOutputStandard o)
  34.         {
  35.             fixed4 c = _Color;
  36.             o.Albedo = c.rgb;
  37.             o.Metallic = _Metallic;
  38.             o.Smoothness = _Glossiness;
  39.             o.Alpha = c.a;
  40.         }
  41.         ENDCG

  42.         //x ray pass
  43.         Tags { "RenderType" = "Transparent" "Queue" = "Transparent" "IgnoreProjector" = "True"}
  44.         Stencil
  45.         {
  46.             Ref 0
  47.             Comp Equal
  48.             Pass Keep
  49.         }
  50.         ZWrite Off
  51.         ZTest Greater
  52.         CGPROGRAM
  53.         #pragma surface surf Standard addshadow fullforwardshadows alpha:fade
  54.         struct Input
  55.         {
  56.             float2 uv_texcoord;
  57.             float3 worldPos;
  58.             float3 worldNormal;
  59.         };

  60.         float4 _XRayCol;
  61.         float _XRayFresPow;        

  62.         UNITY_INSTANCING_BUFFER_START(Props)
  63.         UNITY_INSTANCING_BUFFER_END(Props)
  64.         void surf (Input IN, inout SurfaceOutputStandard o)
  65.         {
  66.             float3 vDir = normalize(_WorldSpaceCameraPos.xyz - IN.worldPos);
  67.             float fres = dot(vDir, IN.worldNormal);
  68.             fres = pow(1 - fres, _XRayFresPow);
  69.             fixed4 col = fres * _XRayCol;
  70.             o.Emission = col.xyz;
  71.             o.Alpha = col.a;
  72.         }
  73.         ENDCG
  74.     }
  75.     FallBack "Diffuse"
  76. }
点击此处复制文本



本帖被以下画板推荐:

收模型,杂志,教程,插图,插件,软件,拿来卖。

使用道具 举报 登录

回复 <
Koiya  发表于 2023-10-24 10:18:59  
2#
很棒得思路
回复 收起回复
使用道具

快来发表你宝贵的意见吧!

DiGiToTo 实名

通过了实名认证的内容创造者

大自然的搬运工

主题
1347
精华
588
超神
7
扩散
0
微金
2090
智慧
166
余额
454
在线时间
7790 小时

翡翠剑 【绝】红龙战甲 学徒法袍 赤铁剑 英雄盾 铁剑 钢盾 元素之盾 钢剑 长剑 水晶剑 死亡刃 阿鼻剑 鬼道剑 修罗剑 天子剑 天道剑 元素铜币 元素银币 元素金币 元素秘币 元素圣币 短杖 圣杖-【安东尼达斯】 【绝】珍珠戒指 女皇之泪 长枪 双杀 巨浪 龙枪 深渊 战神 魔神战甲 元素之铠 黄金圣衣 相对时空 征战护手 【绝】结界玄晶 神界之石 六界传音 【绝】大天使权杖 微光灵石 圣盾-【瓦雷利亚】 【绝】盘古斧 魔镜 裁决 神速靴 火元素 暴风之眼 元素之钻 秘法之钻 血精之钻 波塞冬之叉 圣光之钻 小苹果 大菠萝 再造药水 黄色药水 蓝色药水 赤色药水 微库VIP 翠晶之钻 紫晶之钻 扩散者 钢铁矿镐 秘银矿镐 黄金矿镐 彗星钛晶矿 阿尔法晶矿 泰坦高能矿 守望者【EX】 守望者【赤炼】 守望者【天使】 【绝】守望者【死神】 希望人没事 吃鸡头盔 吉普车 吃鸡甲 守望者【猎空】 生命之缘 自然之怒 原初葫芦 冰晶剑 玫瑰金项链 烈-红龙战甲 【绝】真-红龙战甲 【绝】千人纪念徽章 橙色药水 青色药水 一星珠 二星珠 七星珠 赛博空间 天体物理 宏观物质 无色原始矿 绿母翠晶矿 超星赤辉矿 怀特紫星矿 飞雷靴 现实宝石 灵魂宝石 心灵宝石 时间宝石 力量宝石 粒粒皆辛苦 【绝】赤影战盔 【绝】赤影战斧 莆田鞋 魔法扫帚 朝阳之光 光明勋章 魔法帽 【绝】烈龙战甲 【绝】魔焰斧 【绝】碧焰指环 烈火长枪 烈火匕首 粉御之钻 青戒之钻 黄金沙鹰 金阳之水 紫雷之水 青息之水 粽子 天蓝靴 光虹靴 紫霞之秋 源力法杖 【魔剑】龙葵之魂 绿色药水 紫色药水 光之杖 水晶杖 血晶杖 守望者【D.Va兔子】

快速回复 返回顶部 返回列表