-
Notifications
You must be signed in to change notification settings - Fork 28
/
Distance Fade Cube Volume.shader
128 lines (109 loc) · 3.34 KB
/
Distance Fade Cube Volume.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// by Neitri, free of charge, free to redistribute
// downloaded from https://github.com/netri/Neitri-Unity-Shaders
Shader "Neitri/Distance Fade Cube Volume"
{
Properties
{
[HDR] _Color("Color", Color) = (0,0,0,1)
[Enum(Alpha Blended,0,Dithered,1)] _FadeType("Fade type", Range(0, 1)) = 0
}
SubShader
{
Tags
{
"Queue" = "Transparent+1000"
"RenderType" = "Transparent"
}
Blend SrcAlpha OneMinusSrcAlpha
Cull Back
ZWrite Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float4 _Color;
int _FadeType;
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
float4 depthTextureUv : TEXCOORD1;
float4 rayFromCamera : TEXCOORD2;
};
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
// Dj Lukis.LT's oblique view frustum correction (VRChat mirrors use such view frustum)
// https://github.com/lukis101/VRCUnityStuffs/blob/master/Shaders/DJL/Overlays/WorldPosOblique.shader
inline float4 CalculateObliqueFrustumCorrection()
{
float x1 = -UNITY_MATRIX_P._31 / (UNITY_MATRIX_P._11 * UNITY_MATRIX_P._34);
float x2 = -UNITY_MATRIX_P._32 / (UNITY_MATRIX_P._22 * UNITY_MATRIX_P._34);
return float4(x1, x2, 0, UNITY_MATRIX_P._33 / UNITY_MATRIX_P._34 + x1 * UNITY_MATRIX_P._13 + x2 * UNITY_MATRIX_P._23);
}
inline float CorrectedLinearEyeDepth(float z, float correctionFactor)
{
return 1.f / (z / UNITY_MATRIX_P._34 + correctionFactor);
}
bool SceneZDefaultValue()
{
#if UNITY_REVERSED_Z
return 0.f;
#else
return 1.f;
#endif
}
// from https://www.shadertoy.com/view/Mllczf
float GetTriangularPDFNoiseDithering(float3 pos)
{
float3 p3 = frac(pos * float3(.1031, .1030, .0973));
p3 += dot(p3, p3.yzx + 19.19);
float2 rand = frac((p3.xx + p3.yz) * p3.zy);
return (rand.x + rand.y) * 0.5;
}
v2f vert(appdata v)
{
float4 worldPosition = mul(unity_ObjectToWorld, v.vertex);
v2f o;
o.vertex = mul(UNITY_MATRIX_VP, worldPosition);
o.depthTextureUv = ComputeGrabScreenPos(o.vertex);
o.rayFromCamera.xyz = worldPosition.xyz - _WorldSpaceCameraPos.xyz;
o.rayFromCamera.w = dot(o.vertex, CalculateObliqueFrustumCorrection()); // oblique frustrum correction factor
return o;
}
float4 frag(v2f i) : SV_Target
{
float perspectiveDivide = 1.f / i.vertex.w;
float4 rayFromCamera = i.rayFromCamera * perspectiveDivide;
float2 depthTextureUv = i.depthTextureUv.xy * perspectiveDivide;
float sceneZ = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, depthTextureUv);
if (sceneZ == SceneZDefaultValue())
{
// this is skybox, depth texture has default value
clip(-1);
}
// linearize depth and use it to calculate background world position
float sceneDepth = CorrectedLinearEyeDepth(sceneZ, rayFromCamera.w);
float3 worldPosition = rayFromCamera.xyz * sceneDepth + _WorldSpaceCameraPos.xyz;
float4 localPosition = mul(unity_WorldToObject, float4(worldPosition, 1));
localPosition.xyz /= localPosition.w;
float fade = max(0, 0.5 - localPosition.z);
float4 color = _Color;
UNITY_BRANCH
if (_FadeType == 0)
{
color *= fade;
}
else
{
clip(fade - GetTriangularPDFNoiseDithering(worldPosition * 100));
}
return color;
}
ENDCG
}
}
}