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
|
#ifndef _ATMOSPHERE_SHADERS_COMMON_FXH_
#define _ATMOSPHERE_SHADERS_COMMON_FXH_
#include "FullScreenTriangleVSOutput.fxh"
#include "ToneMappingStructures.fxh"
#include "EpipolarLightScatteringStructures.fxh"
#include "ShaderUtilities.fxh"
#define PI 3.1415928
#define FLT_MAX 3.402823466e+38
#ifndef OPTIMIZE_SAMPLE_LOCATIONS
# define OPTIMIZE_SAMPLE_LOCATIONS 1
#endif
#ifndef CORRECT_INSCATTERING_AT_DEPTH_BREAKS
# define CORRECT_INSCATTERING_AT_DEPTH_BREAKS 0
#endif
//#define SHADOW_MAP_DEPTH_BIAS 1e-4
#ifndef ENABLE_LIGHT_SHAFTS
# define ENABLE_LIGHT_SHAFTS 1
#endif
#ifndef USE_1D_MIN_MAX_TREE
# define USE_1D_MIN_MAX_TREE 1
#endif
#ifndef IS_32BIT_MIN_MAX_MAP
# define IS_32BIT_MIN_MAX_MAP 0
#endif
#ifndef SINGLE_SCATTERING_MODE
# define SINGLE_SCATTERING_MODE SINGLE_SCTR_MODE_INTEGRATION
#endif
#ifndef MULTIPLE_SCATTERING_MODE
# define MULTIPLE_SCATTERING_MODE MULTIPLE_SCTR_MODE_NONE
#endif
#ifndef PRECOMPUTED_SCTR_LUT_DIM
# define PRECOMPUTED_SCTR_LUT_DIM float4(32.0, 128.0, 32.0, 16.0)
#endif
#ifndef NUM_RANDOM_SPHERE_SAMPLES
# define NUM_RANDOM_SPHERE_SAMPLES 128
#endif
#ifndef PERFORM_TONE_MAPPING
# define PERFORM_TONE_MAPPING 1
#endif
#ifndef LOW_RES_LUMINANCE_MIPS
# define LOW_RES_LUMINANCE_MIPS 7
#endif
#ifndef TONE_MAPPING_MODE
# define TONE_MAPPING_MODE TONE_MAPPING_MODE_REINHARD_MOD
#endif
#ifndef LIGHT_ADAPTATION
# define LIGHT_ADAPTATION 1
#endif
#ifndef CASCADE_PROCESSING_MODE
# define CASCADE_PROCESSING_MODE CASCADE_PROCESSING_MODE_SINGLE_PASS
#endif
#ifndef USE_COMBINED_MIN_MAX_TEXTURE
# define USE_COMBINED_MIN_MAX_TEXTURE 1
#endif
#ifndef EXTINCTION_EVAL_MODE
# define EXTINCTION_EVAL_MODE EXTINCTION_EVAL_MODE_EPIPOLAR
#endif
#ifndef AUTO_EXPOSURE
# define AUTO_EXPOSURE 1
#endif
#define INVALID_EPIPOLAR_LINE float4(-1000.0, -1000.0, -100.0, -100.0)
#define RGB_TO_LUMINANCE float3(0.212671, 0.715160, 0.072169)
// GLSL compiler is so bad that it cannot properly handle matrices passed as structure members!
float3 ProjSpaceXYZToWorldSpace(in float3 f3PosPS, in float4x4 mProj, in float4x4 mViewProjInv /*CameraAttribs CamAttribs <- DO NOT DO THIS*/)
{
// We need to compute normalized device z before applying view-proj inverse matrix
// It does not matter if we are in HLSL or GLSL. The way normalized device
// coordinates are computed is the same in both APIs - simply transform by
// matrix and then divide by w. Consequently, the inverse transform is also
// the same.
// What differs is that in GL, NDC z is transformed from [-1,+1] to [0,1]
// before storing in the depth buffer, which we will have to inverse.
float fNDC_Z = CameraZToNormalizedDeviceZ(f3PosPS.z, mProj);
float4 ReconstructedPosWS = mul( float4(f3PosPS.xy, fNDC_Z, 1.0), mViewProjInv );
ReconstructedPosWS /= ReconstructedPosWS.w;
return ReconstructedPosWS.xyz;
}
float3 WorldSpaceToShadowMapUV(in float3 f3PosWS, in matrix mWorldToShadowMapUVDepth)
{
float4 f4ShadowMapUVDepth = mul( float4(f3PosWS, 1), mWorldToShadowMapUVDepth );
// Shadow map projection matrix is orthographic, so we do not need to divide by w
//f4ShadowMapUVDepth.xyz /= f4ShadowMapUVDepth.w;
// Applying depth bias results in light leaking through the opaque objects when looking directly
// at the light source
return f4ShadowMapUVDepth.xyz;
}
void GetRaySphereIntersection(in float3 f3RayOrigin,
in float3 f3RayDirection,
in float3 f3SphereCenter,
in float fSphereRadius,
out float2 f2Intersections)
{
// http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
f3RayOrigin -= f3SphereCenter;
float A = dot(f3RayDirection, f3RayDirection);
float B = 2.0 * dot(f3RayOrigin, f3RayDirection);
float C = dot(f3RayOrigin,f3RayOrigin) - fSphereRadius*fSphereRadius;
float D = B*B - 4.0*A*C;
// If discriminant is negative, there are no real roots hence the ray misses the
// sphere
if (D < 0.0)
{
f2Intersections = float2(-1.0, -1.0);
}
else
{
D = sqrt(D);
f2Intersections = float2(-B - D, -B + D) / (2.0*A); // A must be positive here!!
}
}
void GetRaySphereIntersection2(in float3 f3RayOrigin,
in float3 f3RayDirection,
in float3 f3SphereCenter,
in float2 f2SphereRadius,
out float4 f4Intersections)
{
// http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
f3RayOrigin -= f3SphereCenter;
float A = dot(f3RayDirection, f3RayDirection);
float B = 2.0 * dot(f3RayOrigin, f3RayDirection);
float2 C = dot(f3RayOrigin,f3RayOrigin) - f2SphereRadius*f2SphereRadius;
float2 D = B*B - 4.0*A*C;
// If discriminant is negative, there are no real roots hence the ray misses the
// sphere
float2 f2RealRootMask = float2(D.x >= 0.0 ? 1.0 : 0.0, D.y >= 0.0 ? 1.0 : 0.0);
D = sqrt( max(D,0.0) );
f4Intersections = f2RealRootMask.xxyy * float4(-B - D.x, -B + D.x, -B - D.y, -B + D.y) / (2.0*A) +
(float4(1.0, 1.0, 1.0, 1.0) - f2RealRootMask.xxyy) * float4(-1.0, -1.0, -1.0, -1.0);
}
float4 GetOutermostScreenPixelCoords(float4 ScreenResolution)
{
// The outermost visible screen pixels centers do not lie exactly on the boundary (+1 or -1), but are biased by
// 0.5 screen pixel size inwards
//
// 2.0
// |<---------------------------------------------------------------------->|
//
// 2.0/Res
// |<--------->|
// | X | X | X | ... | X | X |
// -1 | | +1
// | |
// | |
// -1 + 1.0/Res +1 - 1.0/Res
return float4(-1.0, -1.0, 1.0, 1.0) + float4(1.0, 1.0, -1.0, -1.0) * ScreenResolution.zwzw;
}
// When checking if a point is inside the screen, we must test against
// the biased screen boundaries
bool IsValidScreenLocation(in float2 f2XY, float4 ScreenResolution)
{
const float2 SAFETY_EPSILON = float2(0.2, 0.2);
return all( LessEqual( abs(f2XY), float2(1.0, 1.0) - (float2(1.0, 1.0) - SAFETY_EPSILON) * ScreenResolution.zw ) );
}
float GetAverageSceneLuminance(in Texture2D<float> tex2DAverageLuminance)
{
#if AUTO_EXPOSURE
float fAveLogLum = tex2DAverageLuminance.Load( int3(0,0,0) );
#else
float fAveLogLum = 0.1;
#endif
fAveLogLum = max(0.05, fAveLogLum); // Average luminance is an approximation to the key of the scene
return fAveLogLum;
}
float2 GetWeightedLogLum(float3 Color, float MinLuminance)
{
float Luminance = dot(Color, RGB_TO_LUMINANCE);
float LumWeight = saturate((Luminance - MinLuminance) / MinLuminance);
float LogLum = log(max(Luminance, 1e-5));
return float2(LogLum * LumWeight, LumWeight);
}
#endif //_ATMOSPHERE_SHADERS_COMMON_FXH_
|