unity-shader-深度测试-透视xray

unity-shader深度测试-透视xray


效果

这里写图片描述


思路

实现这个效果需要两个pass

  1. 绘制被遮挡部分,即 深度测试 Greater ,且不写入 深度缓冲区(防止印象其他物体的深度对比),剩下的 xray效果就比较容易,同一 空间 下通过 点积 处理
  2. 正常绘制,即 深度测试 LEqual ,且写入 深度缓冲区(正常与其他物体遮挡)

shader代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
Shader "ITS/test/aaaa_XRay"
{
Properties
{
_MainTex("Base 2D", 2D) = "white" {}
_XRayColor("XRay Color", Color) = (1,1,1,1)
}

SubShader
{
CGINCLUDE // 写法二,使用 CGINCLUDE 写好 顶点、片段 着色器,然后各个 Pass 中 使用 CGPROGRAM 指定需要用到的 顶点、片段 着色器
#include "UnityCG.cginc"

fixed4 _XRayColor;

struct v2f
{
float4 pos : SV_POSITION;
float3 normal : NORMAL;
float3 viewDir : TEXCOORD0;
fixed4 clr : COLOR;
};

v2f vertXray(appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.viewDir = ObjSpaceViewDir(v.vertex); // 在 模型空间 上计算夹角
o.normal = v.normal;

float3 normal = normalize(v.normal);
float3 viewDir = normalize(o.viewDir);
float rim = 1 - dot(normal, viewDir);

o.clr = _XRayColor * rim;
return o;
}

fixed4 fragXray(v2f i) : SV_TARGET
{
return i.clr;
}

sampler2D _MainTex;
float4 _MainTex_ST;

struct v2f2
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};

v2f2 vertNormal(appdata_base v)
{
v2f2 o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}

fixed4 fragNormal(v2f2 i) : SV_TARGET
{
return tex2D(_MainTex, i.uv);
}
ENDCG

Pass // xRay 绘制
{
Tags{ "RenderType"="Transparent" "Queue"="Transparent"}
Blend SrcAlpha One
ZTest Greater
ZWrite Off
Cull Back

CGPROGRAM
#pragma vertex vertXray
#pragma fragment fragXray
ENDCG
}

Pass // 正常绘制
{
Tags{ "RenderType"="Opaque" }
ZTest LEqual
ZWrite On

CGPROGRAM
#pragma vertex vertNormal
#pragma fragment fragNormal
ENDCG
}
}
}