forked from QianMo/X-PostProcessing-Library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStdLib.hlsl
322 lines (267 loc) · 8.72 KB
/
StdLib.hlsl
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
// Because this framework is supposed to work with the legacy render pipelines AND scriptable render
// pipelines we can't use Unity's shader libraries (some scriptable pipelines come with their own
// shader lib). So here goes a minimal shader lib only used for post-processing to ensure good
// compatibility with all pipelines.
#ifndef UNITY_POSTFX_STDLIB
#define UNITY_POSTFX_STDLIB
// -----------------------------------------------------------------------------
// API macros
#if defined(SHADER_API_PSSL)
#include "API/PSSL.hlsl"
#elif defined(SHADER_API_XBOXONE)
#include "API/XboxOne.hlsl"
#elif defined(SHADER_API_D3D11)
#include "API/D3D11.hlsl"
#elif defined(SHADER_API_D3D12)
#include "API/D3D12.hlsl"
#elif defined(SHADER_API_D3D9) || defined(SHADER_API_D3D11_9X)
#include "API/D3D9.hlsl"
#elif defined(SHADER_API_VULKAN)
#include "API/Vulkan.hlsl"
#elif defined(SHADER_API_SWITCH)
#include "API/Switch.hlsl"
#elif defined(SHADER_API_METAL)
#include "API/Metal.hlsl"
#elif defined(SHADER_API_PSP2)
#include "API/PSP2.hlsl"
#else
#include "API/OpenGL.hlsl"
#endif
#if defined(SHADER_API_PSSL) || defined(SHADER_API_XBOXONE) || defined(SHADER_API_SWITCH) || defined(SHADER_API_PSP2)
#define SHADER_API_CONSOLE
#endif
// -----------------------------------------------------------------------------
// Constants
#define HALF_MAX 65504.0 // (2 - 2^-10) * 2^15
#define HALF_MAX_MINUS1 65472.0 // (2 - 2^-9) * 2^15
#define EPSILON 1.0e-4
#define PI 3.14159265359
#define TWO_PI 6.28318530718
#define FOUR_PI 12.56637061436
#define INV_PI 0.31830988618
#define INV_TWO_PI 0.15915494309
#define INV_FOUR_PI 0.07957747155
#define HALF_PI 1.57079632679
#define INV_HALF_PI 0.636619772367
#define FLT_EPSILON 1.192092896e-07 // Smallest positive number, such that 1.0 + FLT_EPSILON != 1.0
#define FLT_MIN 1.175494351e-38 // Minimum representable positive floating-point number
#define FLT_MAX 3.402823466e+38 // Maximum representable floating-point number
// -----------------------------------------------------------------------------
// Compatibility functions
#if (SHADER_TARGET < 50 && !defined(SHADER_API_PSSL))
float rcp(float value)
{
return 1.0 / value;
}
#endif
#if defined(SHADER_API_GLES)
#define mad(a, b, c) (a * b + c)
#endif
#ifndef INTRINSIC_MINMAX3
float Min3(float a, float b, float c)
{
return min(min(a, b), c);
}
float2 Min3(float2 a, float2 b, float2 c)
{
return min(min(a, b), c);
}
float3 Min3(float3 a, float3 b, float3 c)
{
return min(min(a, b), c);
}
float4 Min3(float4 a, float4 b, float4 c)
{
return min(min(a, b), c);
}
float Max3(float a, float b, float c)
{
return max(max(a, b), c);
}
float2 Max3(float2 a, float2 b, float2 c)
{
return max(max(a, b), c);
}
float3 Max3(float3 a, float3 b, float3 c)
{
return max(max(a, b), c);
}
float4 Max3(float4 a, float4 b, float4 c)
{
return max(max(a, b), c);
}
#endif // INTRINSIC_MINMAX3
// https://twitter.com/SebAaltonen/status/878250919879639040
// madd_sat + madd
float FastSign(float x)
{
return saturate(x * FLT_MAX + 0.5) * 2.0 - 1.0;
}
float2 FastSign(float2 x)
{
return saturate(x * FLT_MAX + 0.5) * 2.0 - 1.0;
}
float3 FastSign(float3 x)
{
return saturate(x * FLT_MAX + 0.5) * 2.0 - 1.0;
}
float4 FastSign(float4 x)
{
return saturate(x * FLT_MAX + 0.5) * 2.0 - 1.0;
}
// Using pow often result to a warning like this
// "pow(f, e) will not work for negative f, use abs(f) or conditionally handle negative values if you expect them"
// PositivePow remove this warning when you know the value is positive and avoid inf/NAN.
float PositivePow(float base, float power)
{
return pow(max(abs(base), float(FLT_EPSILON)), power);
}
float2 PositivePow(float2 base, float2 power)
{
return pow(max(abs(base), float2(FLT_EPSILON, FLT_EPSILON)), power);
}
float3 PositivePow(float3 base, float3 power)
{
return pow(max(abs(base), float3(FLT_EPSILON, FLT_EPSILON, FLT_EPSILON)), power);
}
float4 PositivePow(float4 base, float4 power)
{
return pow(max(abs(base), float4(FLT_EPSILON, FLT_EPSILON, FLT_EPSILON, FLT_EPSILON)), power);
}
// NaN checker
// /Gic isn't enabled on fxc so we can't rely on isnan() anymore
bool IsNan(float x)
{
// For some reason the following tests outputs "internal compiler error" randomly on desktop
// so we'll use a safer but slightly slower version instead :/
//return (x <= 0.0 || 0.0 <= x) ? false : true;
return (x < 0.0 || x > 0.0 || x == 0.0) ? false : true;
}
bool AnyIsNan(float2 x)
{
return IsNan(x.x) || IsNan(x.y);
}
bool AnyIsNan(float3 x)
{
return IsNan(x.x) || IsNan(x.y) || IsNan(x.z);
}
bool AnyIsNan(float4 x)
{
return IsNan(x.x) || IsNan(x.y) || IsNan(x.z) || IsNan(x.w);
}
// -----------------------------------------------------------------------------
// Std unity data
float4x4 unity_CameraProjection;
float4x4 unity_MatrixVP;
float4x4 unity_ObjectToWorld;
float4x4 unity_WorldToCamera;
float3 _WorldSpaceCameraPos;
float4 _ProjectionParams; // x: 1 (-1 flipped), y: near, z: far, w: 1/far
float4 unity_ColorSpaceLuminance;
float4 unity_DeltaTime; // x: dt, y: 1/dt, z: smoothDt, w: 1/smoothDt
float4 unity_OrthoParams; // x: width, y: height, z: unused, w: ortho ? 1 : 0
float4 _ZBufferParams; // x: 1-far/near, y: far/near, z: x/far, w: y/far
float4 _ScreenParams; // x: width, y: height, z: 1+1/width, w: 1+1/height
float4 _Time; // x: t/20, y: t, z: t*2, w: t*3
float4 _SinTime; // x: sin(t/20), y: sin(t), z: sin(t*2), w: sin(t*3)
float4 _CosTime; // x: cos(t/20), y: cos(t), z: cos(t*2), w: cos(t*3)
// -----------------------------------------------------------------------------
// Std functions
// Z buffer depth to linear 0-1 depth
// Handles orthographic projection correctly
float Linear01Depth(float z)
{
float isOrtho = unity_OrthoParams.w;
float isPers = 1.0 - unity_OrthoParams.w;
z *= _ZBufferParams.x;
return (1.0 - isOrtho * z) / (isPers * z + _ZBufferParams.y);
}
float LinearEyeDepth(float z)
{
return rcp(_ZBufferParams.z * z + _ZBufferParams.w);
}
// Clamp HDR value within a safe range
half3 SafeHDR(half3 c)
{
return min(c, HALF_MAX);
}
half4 SafeHDR(half4 c)
{
return min(c, HALF_MAX);
}
// Decode normals stored in _CameraDepthNormalsTexture
float3 DecodeViewNormalStereo(float4 enc4)
{
float kScale = 1.7777;
float3 nn = enc4.xyz * float3(2.0 * kScale, 2.0 * kScale, 0) + float3(-kScale, -kScale, 1);
float g = 2.0 / dot(nn.xyz, nn.xyz);
float3 n;
n.xy = g * nn.xy;
n.z = g - 1.0;
return n;
}
// Interleaved gradient function from Jimenez 2014
// http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
float GradientNoise(float2 uv)
{
uv = floor(uv * _ScreenParams.xy);
float f = dot(float2(0.06711056, 0.00583715), uv);
return frac(52.9829189 * frac(f));
}
// Vertex manipulation
float2 TransformTriangleVertexToUV(float2 vertex)
{
float2 uv = (vertex + 1.0) * 0.5;
return uv;
}
#include "xRLib.hlsl"
// -----------------------------------------------------------------------------
// Default vertex shaders
struct AttributesDefault
{
float3 vertex : POSITION;
};
struct VaryingsDefault
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
float2 texcoordStereo : TEXCOORD1;
#if STEREO_INSTANCING_ENABLED
uint stereoTargetEyeIndex : SV_RenderTargetArrayIndex;
#endif
};
#if STEREO_INSTANCING_ENABLED
float _DepthSlice;
#endif
VaryingsDefault VertDefault(AttributesDefault v)
{
VaryingsDefault o;
o.vertex = float4(v.vertex.xy, 0.0, 1.0);
o.texcoord = TransformTriangleVertexToUV(v.vertex.xy);
#if UNITY_UV_STARTS_AT_TOP
o.texcoord = o.texcoord * float2(1.0, -1.0) + float2(0.0, 1.0);
#endif
o.texcoordStereo = TransformStereoScreenSpaceTex(o.texcoord, 1.0);
return o;
}
float4 _UVTransform; // xy: scale, wz: translate
#if STEREO_DOUBLEWIDE_TARGET
float4 _PosScaleOffset; // xy: scale, wz: offset
#endif
VaryingsDefault VertUVTransform(AttributesDefault v)
{
VaryingsDefault o;
#if STEREO_DOUBLEWIDE_TARGET
o.vertex = float4(v.vertex.xy * _PosScaleOffset.xy + _PosScaleOffset.zw, 0.0, 1.0);
#else
o.vertex = float4(v.vertex.xy, 0.0, 1.0);
#endif
o.texcoord = TransformTriangleVertexToUV(v.vertex.xy) * _UVTransform.xy + _UVTransform.zw;
o.texcoordStereo = TransformStereoScreenSpaceTex(o.texcoord, 1.0);
#if STEREO_INSTANCING_ENABLED
o.stereoTargetEyeIndex = (uint)_DepthSlice;
#endif
return o;
}
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
#endif // UNITY_POSTFX_STDLIB