-
Notifications
You must be signed in to change notification settings - Fork 867
Expand file tree
/
Copy pathLensFlareCommon.hlsl
More file actions
346 lines (276 loc) · 9.54 KB
/
LensFlareCommon.hlsl
File metadata and controls
346 lines (276 loc) · 9.54 KB
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Filtering.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Random.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/Sampling.hlsl"
struct AttributesLensFlare
{
uint vertexID : SV_VertexID;
#ifndef FLARE_PREVIEW
UNITY_VERTEX_INPUT_INSTANCE_ID
#endif
};
struct VaryingsLensFlare
{
float4 positionCS : SV_POSITION;
float2 texcoord : TEXCOORD0;
#if defined(FLARE_HAS_OCCLUSION) || defined(FLARE_COMPUTE_OCCLUSION)
float occlusion : TEXCOORD1;
#endif
#ifndef FLARE_PREVIEW
UNITY_VERTEX_OUTPUT_STEREO
#endif
};
TEXTURE2D(_FlareTex);
SAMPLER(sampler_FlareTex);
TEXTURE2D(_FlareOcclusionRemapTex);
SAMPLER(sampler_FlareOcclusionRemapTex);
#if defined(FLARE_HAS_OCCLUSION)
TEXTURE2D_ARRAY(_FlareOcclusionTex);
SAMPLER(sampler_FlareOcclusionTex);
#endif
#ifdef HDRP_FLARE
#if defined(FLARE_CLOUD_BACKGROUND_OCCLUSION)
TEXTURE2D_X(_FlareCloudOpacity);
SAMPLER(sampler_FlareCloudOpacity);
#endif
#if defined(FLARE_VOLUMETRIC_CLOUD_OCCLUSION)
TEXTURE2D_X(_FlareSunOcclusionTex);
SAMPLER(sampler_FlareSunOcclusionTex);
#endif
#endif
float4 _FlareColorValue;
float4 _FlareData0; // x: localCos0, y: localSin0, zw: PositionOffsetXY
float4 _FlareData1; // x: OcclusionRadius, y: OcclusionSampleCount, z: ScreenPosZ, w: ScreenRatio
float4 _FlareData2; // xy: ScreenPos, zw: FlareSize
float4 _FlareData3; // x: Allow Offscreen, y: Edge Offset, z: Falloff, w: invSideCount
float4 _FlareData4; // x: SDF Roundness, y: Poly Radius, z: PolyParam0, w: PolyParam1
#ifdef FLARE_PREVIEW
float4 _FlarePreviewData;
#define _ScreenSize _FlarePreviewData.xy;
#define _FlareScreenRatio _FlarePreviewData.z;
#endif
float4 _FlareOcclusionIndex;
#define _FlareColor _FlareColorValue
#define _LocalCos0 _FlareData0.x
#define _LocalSin0 _FlareData0.y
#define _PositionTranslate _FlareData0.zw
#define _OcclusionRadius _FlareData1.x
#define _OcclusionSampleCount _FlareData1.y
#define _ScreenPosZ _FlareData1.z
#ifndef _FlareScreenRatio
#define _FlareScreenRatio _FlareData1.w
#endif
#define _ScreenPos _FlareData2.xy
#define _FlareSize _FlareData2.zw
#define _OcclusionOffscreen _FlareData3.x
#define _FlareEdgeOffset _FlareData3.y
#define _FlareFalloff _FlareData3.z
#define _FlareShapeInvSide _FlareData3.z
#define _FlareSDFRoundness _FlareData4.x
#define _FlareSDFPolyRadius _FlareData4.y
#define _FlareSDFPolyParam0 _FlareData4.z
#define _FlareSDFPolyParam1 _FlareData4.w
float2 Rotate(float2 v, float cos0, float sin0)
{
return float2(v.x * cos0 - v.y * sin0,
v.x * sin0 + v.y * cos0);
}
#if defined(FLARE_COMPUTE_OCCLUSION) || defined(FLARE_OPENGL3_OR_OPENGLCORE)
float GetLinearDepthValue(float2 uv)
{
#if defined(HDRP_FLARE) || defined(FLARE_PREVIEW)
float depth = LOAD_TEXTURE2D_X_LOD(_CameraDepthTexture, uint2(uv * _ScreenSize.xy), 0).x;
#else
float depth = LOAD_TEXTURE2D_X_LOD(_CameraDepthTexture, uint2(uv * GetScaledScreenParams().xy), 0).x;
#endif
return LinearEyeDepth(depth, _ZBufferParams);
}
float GetOcclusion(float ratio)
{
if (_OcclusionSampleCount == 0.0f)
return 1.0f;
float contrib = 0.0f;
float sample_Contrib = 1.0f / _OcclusionSampleCount;
float2 ratioScale = float2(1.0f / ratio, 1.0);
for (uint i = 0; i < (uint)_OcclusionSampleCount; i++)
{
float2 dir = _OcclusionRadius * SampleDiskUniform(Hash(2 * i + 0), Hash(2 * i + 1));
float2 pos0 = _ScreenPos.xy + dir;
float2 pos = pos0 * 0.5f + 0.5f;
#if UNITY_UV_STARTS_AT_TOP
pos.y = 1.0f - pos.y;
#endif
if (all(pos >= 0) && all(pos <= 1))
{
float depth0 = GetLinearDepthValue(pos);
if (depth0 > _ScreenPosZ || NearlyEqual_Float(depth0, _ScreenPosZ))
{
float occlusionValue = 1.0f;
#ifdef HDRP_FLARE
#if defined(FLARE_CLOUD_BACKGROUND_OCCLUSION)
float cloudOpacity = LOAD_TEXTURE2D_X_LOD(_FlareCloudOpacity, uint2(pos.xy * _ScreenSize.xy), 0).x;
occlusionValue *= LOAD_TEXTURE2D_X(_FlareCloudOpacity, uint2(pos * _ScreenParams.xy)).x;
#endif
#if defined(FLARE_VOLUMETRIC_CLOUD_OCCLUSION)
float volumetricCloudOcclusion = SAMPLE_TEXTURE2D_X_LOD(_FlareSunOcclusionTex, sampler_FlareSunOcclusionTex, pos, 0).w;
occlusionValue *= saturate(volumetricCloudOcclusion);
#endif
#endif
contrib += sample_Contrib * occlusionValue;
}
}
else if (_OcclusionOffscreen > 0.0f)
{
contrib += sample_Contrib;
}
}
contrib = SAMPLE_TEXTURE2D_LOD(_FlareOcclusionRemapTex, sampler_FlareOcclusionRemapTex, float2(saturate(contrib), 0.0f), 0).x;
contrib = saturate(contrib);
return contrib;
}
#endif
#if defined(FLARE_COMPUTE_OCCLUSION)
VaryingsLensFlare vertOcclusion(AttributesLensFlare input, uint instanceID : SV_InstanceID)
{
VaryingsLensFlare output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
#if defined(HDRP_FLARE) || defined(FLARE_PREVIEW)
float screenRatio = _FlareScreenRatio;
#else
float2 screenParam = GetScaledScreenParams().xy;
float screenRatio = screenParam.y / screenParam.x;
#endif
float2 quadPos = 2.0f * GetQuadVertexPosition(input.vertexID).xy - 1.0f;
float2 uv = GetQuadTexCoord(input.vertexID);
uv.x = 1.0f - uv.x;
output.positionCS.xy = quadPos;
output.texcoord.xy = uv;
output.positionCS.z = 1.0f;
output.positionCS.w = 1.0f;
float occlusion = GetOcclusion(screenRatio);
if (_OcclusionOffscreen < 0.0f && // No lens flare off screen
(any(_ScreenPos.xy < -1) || any(_ScreenPos.xy >= 1)))
occlusion = 0.0f;
output.occlusion = occlusion;
return output;
}
float4 fragOcclusion(VaryingsLensFlare input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
return float4(input.occlusion.xxx, 1.0f);
}
#else
VaryingsLensFlare vert(AttributesLensFlare input, uint instanceID : SV_InstanceID)
{
VaryingsLensFlare output;
#ifndef FLARE_PREVIEW
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
#endif
#if defined(HDRP_FLARE) || defined(FLARE_PREVIEW)
float screenRatio = _FlareScreenRatio;
#else
float2 screenParam = GetScaledScreenParams().xy;
float screenRatio = screenParam.y / screenParam.x;
#endif
float4 posPreScale = float4(2.0f, 2.0f, 1.0f, 1.0f) * GetQuadVertexPosition(input.vertexID) - float4(1.0f, 1.0f, 0.0f, 0.0);
float2 uv = GetQuadTexCoord(input.vertexID);
uv.x = 1.0f - uv.x;
output.texcoord.xy = uv;
posPreScale.xy *= _FlareSize;
float2 local = Rotate(posPreScale.xy, _LocalCos0, _LocalSin0);
local.x *= screenRatio;
output.positionCS.xy = local + _ScreenPos + _PositionTranslate;
output.positionCS.z = 1.0f;
output.positionCS.w = 1.0f;
#if defined(FLARE_HAS_OCCLUSION)
float occlusion;
if (_OcclusionOffscreen < 0.0f && // No lens flare off screen
(any(_ScreenPos.xy < -1) || any(_ScreenPos.xy > 1)))
{
occlusion = 0.0f;
}
else
{
#if defined(FLARE_OPENGL3_OR_OPENGLCORE)
#if defined(HDRP_FLARE) || defined(FLARE_PREVIEW)
float screenRatio = _FlareScreenRatio;
#else
float2 screenParam = GetScaledScreenParams().xy;
float screenRatio = screenParam.y / screenParam.x;
#endif
occlusion = GetOcclusion(screenRatio);
#else
occlusion = LOAD_TEXTURE2D_ARRAY_LOD(_FlareOcclusionTex, uint2(_FlareOcclusionIndex.x, 0), unity_StereoEyeIndex, 0).x;
#endif
}
output.occlusion = occlusion;
#endif
return output;
}
#endif
float InverseGradient(float x)
{
// Do *not* simplify as 1.0f - x
return x * (1.0f - x) / (x + 1e-6f);
}
float4 ComputeCircle(float2 uv)
{
float2 v = (uv - 0.5f) * 2.0f;
const float epsilon = 1e-3f;
const float epsCoef = pow(epsilon, 1.0f / _FlareFalloff);
float x = length(v);
float sdf = saturate((x - 1.0f) / ((_FlareEdgeOffset - 1.0f)));
#if defined(FLARE_INVERSE_SDF)
sdf = saturate(sdf);
sdf = InverseGradient(sdf);
#endif
return pow(sdf, _FlareFalloff);
}
// Modfied from ref: https://www.shadertoy.com/view/MtKcWW
// https://www.shadertoy.com/view/3tGBDt
float4 ComputePolygon(float2 uv_)
{
float2 p = uv_ * 2.0f - 1.0f;
float r = _FlareSDFPolyRadius;
float an = _FlareSDFPolyParam0;
float he = _FlareSDFPolyParam1;
float bn = an * floor((atan2(p.y, p.x) + 0.5f * an) / an);
float cos0 = cos(bn);
float sin0 = sin(bn);
p = float2( cos0 * p.x + sin0 * p.y,
-sin0 * p.x + cos0 * p.y);
// side of polygon
float sdf = length(p - float2(r, clamp(p.y, -he, he))) * sign(p.x - r) - _FlareSDFRoundness;
sdf *= _FlareEdgeOffset;
#if defined(FLARE_INVERSE_SDF)
sdf = saturate(-sdf);
sdf = InverseGradient(sdf);
#else
sdf = saturate(-sdf);
#endif
return saturate(pow(sdf, _FlareFalloff));
}
float4 GetFlareShape(float2 uv)
{
#ifdef FLARE_CIRCLE
return ComputeCircle(uv);
#elif defined(FLARE_POLYGON)
return ComputePolygon(uv);
#else
return SAMPLE_TEXTURE2D(_FlareTex, sampler_FlareTex, uv);
#endif
}
float4 frag(VaryingsLensFlare input) : SV_Target
{
#ifndef FLARE_PREVIEW
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
#endif
float4 col = GetFlareShape(input.texcoord);
#if defined(FLARE_HAS_OCCLUSION)
return col * _FlareColor * input.occlusion;
#else
return col * _FlareColor;
#endif
}