-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathDeferredReflections.shader
181 lines (143 loc) · 6.65 KB
/
DeferredReflections.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
Shader "Hidden/DeferredReflections" {
Properties {
_SrcBlend ("", Float) = 1
_DstBlend ("", Float) = 1
}
SubShader {
// Calculates reflection contribution from a single probe (rendered as cubes) or default reflection (rendered as full screen quad)
Pass {
ZWrite Off
ZTest LEqual
Blend [_SrcBlend] [_DstBlend]
CGPROGRAM
#pragma target 3.0
#pragma vertex vert_deferred
#pragma fragment frag
#include "UnityCG.cginc"
#include "UnityDeferredLibrary.cginc"
#include "UnityStandardUtils.cginc"
#include "UnityGBuffer.cginc"
#include "UnityStandardBRDF.cginc"
#include "UnityPBSLighting.cginc"
sampler2D _CameraGBufferTexture0;
sampler2D _CameraGBufferTexture1;
sampler2D _CameraGBufferTexture2;
float3 distanceFromAABB(float3 p, float3 aabbMin, float3 aabbMax)
{
return max(max(p - aabbMax, aabbMin - p), float3(0.0, 0.0, 0.0));
}
float4 BRDF (float3 specColor, float oneMinusReflectivity, float smoothness,
float3 normal, float3 viewDir, UnityIndirect gi)
{
float perceptualRoughness = SmoothnessToPerceptualRoughness (smoothness);
// NdotV should not be negative for visible pixels, but it can happen due to perspective projection and normal mapping
// In this case normal should be modified to become valid (i.e facing camera) and not cause weird artifacts.
// but this operation adds few ALU and users may not want it. Alternative is to simply take the abs of NdotV (less correct but works too).
// Following define allow to control this. Set it to 0 if ALU is critical on your platform.
// This correction is interesting for GGX with SmithJoint visibility function because artifacts are more visible in this case due to highlight edge of rough surface
// Edit: Disable this code by default for now as it is not compatible with two sided lighting used in SpeedTree.
float nv = (dot(normal, viewDir)); // This abs allow to limit artifact
//Diffuse = DisneyDiffuse(NoV, NoL, LoH, SmoothnessToPerceptualRoughness (smoothness)) * NoL;
// Specular term
// HACK: theoretically we should divide diffuseTerm by Pi and not multiply specularTerm!
// BUT 1) that will make shader look significantly darker than Legacy ones
// and 2) on engine side "Non-important" lights have to be divided by Pi too in cases when they are injected into ambient SH
float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
#if UNITY_BRDF_GGX
// GGX with roughtness to 0 would mean no specular at all, using max(roughness, 0.002) here to match HDrenderloop roughtness remapping.
roughness = max(roughness, 0.002);
#endif
// surfaceReduction = Int D(NdotH) * NdotH * Id(NdotL>0) dH = 1/(roughness^2+1)
float surfaceReduction;
# ifdef UNITY_COLORSPACE_GAMMA
surfaceReduction = 1.0-0.28*roughness*perceptualRoughness; // 1-0.28*x^3 as approximation for (1/(x^4+1))^(1/2.2) on the domain [0;1]
# else
surfaceReduction = 1.0 / (roughness*roughness + 1.0); // fade \in [0.5;1]
# endif
float grazingTerm = saturate(smoothness + (1-oneMinusReflectivity));
float3 color = surfaceReduction * gi.specular * FresnelLerp (specColor, grazingTerm, nv);
return float4(color, 1);
}
half4 frag (unity_v2f_deferred i) : SV_Target
{
// Stripped from UnityDeferredCalculateLightParams, refactor into function ?
i.ray = i.ray * (_ProjectionParams.z / i.ray.z);
float2 uv = i.uv.xy / i.uv.w;
// read depth and reconstruct world position
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);
depth = Linear01Depth (depth);
float4 viewPos = float4(i.ray * depth,1);
float3 worldPos = mul (unity_CameraToWorld, viewPos).xyz;
float4 gbuffer0 = tex2D (_CameraGBufferTexture0, uv);
float4 gbuffer1 = tex2D (_CameraGBufferTexture1, uv);
float4 gbuffer2 = tex2D (_CameraGBufferTexture2, uv);
UnityStandardData data = UnityStandardDataFromGbuffer(gbuffer0, gbuffer1, gbuffer2);
float3 eyeVec = normalize(worldPos - _WorldSpaceCameraPos);
float oneMinusReflectivity = 1 - SpecularStrength(data.specularColor);
float3 worldNormalRefl = reflect(eyeVec, data.normalWorld);
// Unused member don't need to be initialized
UnityGIInput d;
d.worldPos = worldPos;
d.worldViewDir = -eyeVec;
d.probeHDR[0] = unity_SpecCube0_HDR;
d.boxMin[0].w = 1; // 1 in .w allow to disable blending in UnityGI_IndirectSpecular call since it doesn't work in Deferred
float blendDistance = unity_SpecCube1_ProbePosition.w; // will be set to blend distance for this probe
#ifdef UNITY_SPECCUBE_BOX_PROJECTION
d.probePosition[0] = unity_SpecCube0_ProbePosition;
d.boxMin[0].xyz = unity_SpecCube0_BoxMin - float4(blendDistance,blendDistance,blendDistance,0);
d.boxMax[0].xyz = unity_SpecCube0_BoxMax + float4(blendDistance,blendDistance,blendDistance,0);
#endif
Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup(data.smoothness, d.worldViewDir, data.normalWorld, data.specularColor);
float3 env0 = UnityGI_IndirectSpecular(d, data.occlusion, g);
UnityIndirect ind;
ind.diffuse = 0;
ind.specular = env0;
float3 rgb = BRDF (data.specularColor, oneMinusReflectivity, data.smoothness, data.normalWorld, -eyeVec, ind).rgb;
// Calculate falloff value, so reflections on the edges of the probe would gradually blend to previous reflection.
// Also this ensures that pixels not located in the reflection probe AABB won't
// accidentally pick up reflections from this probe.
float3 distance = distanceFromAABB(worldPos, unity_SpecCube0_BoxMin.xyz, unity_SpecCube0_BoxMax.xyz);
float falloff = saturate(1.0 - length(distance)/blendDistance);
return float4(rgb, falloff);
}
ENDCG
}
// Adds reflection buffer to the lighting buffer
Pass
{
ZWrite Off
ZTest Always
Blend [_SrcBlend] [_DstBlend]
CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile ___ UNITY_HDR_ON
#include "UnityCG.cginc"
sampler2D _CameraReflectionsTexture;
struct v2f {
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
v2f vert (float4 vertex : POSITION)
{
v2f o;
o.pos = UnityObjectToClipPos(vertex);
o.uv = ComputeScreenPos (o.pos).xy;
return o;
}
float4 frag (v2f i) : SV_Target
{
float4 c = tex2D (_CameraReflectionsTexture, i.uv);
#ifdef UNITY_HDR_ON
return float4(c.rgb, 0.0f);
#else
return float4(exp2(-c.rgb), 0.0f);
#endif
}
ENDCG
}
}
Fallback Off
}