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
|
#ifndef _EPIPOLAR_LIGHT_SCATTERING_STRCUTURES_FXH_
#define _EPIPOLAR_LIGHT_SCATTERING_STRCUTURES_FXH_
#ifdef __cplusplus
# ifndef BOOL
# define BOOL int32_t // Do not use bool, because sizeof(bool)==1 !
# endif
# ifndef TRUE
# define TRUE 1
# endif
# ifndef FALSE
# define FALSE 0
# endif
# ifndef CHECK_STRUCT_ALIGNMENT
// Note that defining empty macros causes GL shader compilation error on Mac, because
// it does not allow standalone semicolons outside of main.
// On the other hand, adding semicolon at the end of the macro definition causes gcc error.
# define CHECK_STRUCT_ALIGNMENT(s) static_assert( sizeof(s) % 16 == 0, "sizeof(" #s ") is not multiple of 16" )
# endif
# ifndef DEFAULT_VALUE
# define DEFAULT_VALUE(x) =x
# endif
#else
# ifndef BOOL
# define BOOL bool
# endif
# ifndef DEFAULT_VALUE
# define DEFAULT_VALUE(x)
# endif
#endif
// Epipolar light scattering
#define LIGHT_SCTR_TECHNIQUE_EPIPOLAR_SAMPLING 0
// High-quality brute-force ray marching for every pixel without any optimizations
#define LIGHT_SCTR_TECHNIQUE_BRUTE_FORCE 1
// Shadow map cascade processing mode
// Process all shadow map cascades in a single pass
#define CASCADE_PROCESSING_MODE_SINGLE_PASS 0
// Process every shadow map cascade in a separate pass
#define CASCADE_PROCESSING_MODE_MULTI_PASS 1
// Process every shadow map cascade in a separate pass, but use single instanced draw command
#define CASCADE_PROCESSING_MODE_MULTI_PASS_INST 2
// Epipolar sampling refinement criterion
// Use depth difference to refine epipolar sampling
#define REFINEMENT_CRITERION_DEPTH_DIFF 0
// Use inscattering difference to refine epipolar sampling
#define REFINEMENT_CRITERION_INSCTR_DIFF 1
// Extinction evaluation mode used when attenuating background
// Evaluate extinction for each pixel using analytic formula by Eric Bruneton
#define EXTINCTION_EVAL_MODE_PER_PIXEL 0
// Render extinction in epipolar space and perform bilateral filtering
// in the same manner as for inscattering
#define EXTINCTION_EVAL_MODE_EPIPOLAR 1
// Single scattering evaluation mode
// No single scattering
#define SINGLE_SCTR_MODE_NONE 0
// Use numerical intergarion
#define SINGLE_SCTR_MODE_INTEGRATION 1
// Use single scattering look-up-table
#define SINGLE_SCTR_MODE_LUT 2
// No higher-order scattering
#define MULTIPLE_SCTR_MODE_NONE 0
// Use unoccluded (unshadowed) scattering
#define MULTIPLE_SCTR_MODE_UNOCCLUDED 1
// Use occluded (shadowed) scattering
#define MULTIPLE_SCTR_MODE_OCCLUDED 2
#ifndef EARTH_RADIUS
// Average Earth radius at sea level
# define EARTH_RADIUS 6371000.0
#endif
struct EpipolarLightScatteringAttribs
{
// Total number of epipolar slices (or lines). For high quality effect,
// set this value to (Screen Width + Screen Height)/2
uint uiNumEpipolarSlices DEFAULT_VALUE(512);
// Maximum number of samples on a single epipolar line.
// For high quality effect, set this value to max(Screen Width, Screen Height)/2.
uint uiMaxSamplesInSlice DEFAULT_VALUE(256);
// Initial ray marching sample spacing on an epipolar line.
// Additional samples are added at discontinuities.
uint uiInitialSampleStepInSlice DEFAULT_VALUE(16);
// Sample density scale near the epipole where inscattering changes rapidly.
// Note that sampling near the epipole is very cheap since only a few steps
// are required to perform ray marching.
uint uiEpipoleSamplingDensityFactor DEFAULT_VALUE(2);
// Refinement threshold controls detection of discontinuities. Smaller values
// produce more samples and higher quality, but at a higher performance cost.
float fRefinementThreshold DEFAULT_VALUE(0.03f);
// Whether to show epipolar sampling.
// Do not use bool, because sizeof(bool)==1 and as a result bool variables
// will be incorrectly mapped on GPU constant buffer.
BOOL bShowSampling DEFAULT_VALUE(FALSE);
// Whether to correct inscattering at depth discontinuities. Improves quality
// for additional cost.
BOOL bCorrectScatteringAtDepthBreaks DEFAULT_VALUE(FALSE);
// Whether to display pixels which are classified as depth discontinuities and which
// will be corrected. Only has effect when bCorrectScatteringAtDepthBreaks is TRUE.
BOOL bShowDepthBreaks DEFAULT_VALUE(FALSE);
// Whether to show lighting only
BOOL bShowLightingOnly DEFAULT_VALUE(FALSE);
// Optimize sample locations to avoid oversampling. This should generally be TRUE.
BOOL bOptimizeSampleLocations DEFAULT_VALUE(TRUE);
// Whether to enable light shafts or render unshadowed inscattering.
// Setting this to FALSE increases performance, but reduces visual quality.
BOOL bEnableLightShafts DEFAULT_VALUE(TRUE);
// Number of inscattering integral steps taken when computing unshadowed inscattering (default is OK).
uint uiInstrIntegralSteps DEFAULT_VALUE(30);
// Size of the shadowmap texel (1/width, 1/height)
float2 f2ShadowMapTexelSize DEFAULT_VALUE(float2(0,0));
// Maximum number of ray marching samples on a single ray. Typically this value should match the maximum
// shadow map cascade resolution. Using lower value will improve performance but may result
// in moire patterns. Note that in most cases singificantly less samples are actually taken.
uint uiMaxSamplesOnTheRay DEFAULT_VALUE(512);
// The number of ray marching samples on a ray when running scattering correction pass.
// This value should typically be much lower than the maximum number of samples on a single ray
// because 1D min-max optimization is not available during the correction pass.
uint uiNumSamplesOnTheRayAtDepthBreak DEFAULT_VALUE(32);
// This defines the number of samples at the lowest level of min-max binary tree
// and should match the maximum cascade shadow map resolution
uint uiMinMaxShadowMapResolution DEFAULT_VALUE(0);
// Number of shadow map cascades
int iNumCascades DEFAULT_VALUE(0);
// First cascade to use for ray marching. Usually first few cascades are small, and ray
// marching them is inefficient.
int iFirstCascadeToRayMarch DEFAULT_VALUE(2);
// Cap on the maximum shadow map step in texels. Can be increased for higher shadow map
// resolutions.
float fMaxShadowMapStep DEFAULT_VALUE(16.f);
// Whether to use 1D min/max binary tree optimization. This improves
// performance for higher shadow map resolution. Test it.
BOOL bUse1DMinMaxTree DEFAULT_VALUE(TRUE);
// Whether to use 32-bit float or 16-bit UNORM min-max binary tree.
BOOL bIs32BitMinMaxMipMap DEFAULT_VALUE(FALSE);
// Technique used to evaluate light scattering.
int iLightSctrTechnique DEFAULT_VALUE(LIGHT_SCTR_TECHNIQUE_EPIPOLAR_SAMPLING);
// Shadow map cascades processing mode.
int iCascadeProcessingMode DEFAULT_VALUE(CASCADE_PROCESSING_MODE_SINGLE_PASS);
// Epipolar sampling refinement criterion.
int iRefinementCriterion DEFAULT_VALUE(REFINEMENT_CRITERION_INSCTR_DIFF);
// Single scattering evaluation mode.
int iSingleScatteringMode DEFAULT_VALUE(SINGLE_SCTR_MODE_INTEGRATION);
// Higher-order scattering evaluation mode.
int iMultipleScatteringMode DEFAULT_VALUE(MULTIPLE_SCTR_MODE_UNOCCLUDED);
// Atmospheric extinction evaluation mode.
int iExtinctionEvalMode DEFAULT_VALUE(EXTINCTION_EVAL_MODE_EPIPOLAR);
// Whether to use Ozone approximation (ignored when custom scattering coefficients are used).
BOOL bUseOzoneApproximation DEFAULT_VALUE(TRUE);
// Whether to use custom scattering coefficients.
BOOL bUseCustomSctrCoeffs DEFAULT_VALUE(FALSE);
// Aerosol density scale to use for scattering coefficient computation.
float fAerosolDensityScale DEFAULT_VALUE(1.f);
// Aerosol absorption scale to use for scattering coefficient computation.
float fAerosolAbsorbtionScale DEFAULT_VALUE(0.1f);
// Custom Rayleigh coefficients.
float4 f4CustomRlghBeta DEFAULT_VALUE(float4(5.8e-6f, 13.5e-6f, 33.1e-6f, 0.f));
// Custom Mie coefficients.
float4 f4CustomMieBeta DEFAULT_VALUE(float4(2.e-5f, 2.e-5f, 2.e-5f, 0.f));
// Custom Ozone absorption coefficient.
float4 f4CustomOzoneAbsorption DEFAULT_VALUE(float4(0.650f, 1.881f, 0.085f, 0.f) * 1e-6f);
float4 f4EarthCenter DEFAULT_VALUE(float4(0.f, -static_cast<float>(EARTH_RADIUS), 0.f, 0.f));
// ToneMappingStructures.fxh must be included before EpipolarLightScatteringStructures.fxh
ToneMappingAttribs ToneMapping;
// Members below are automatically set by the effect. User-provided values are ignored.
float4 f4ScreenResolution DEFAULT_VALUE(float4(0,0,0,0));
float4 f4LightScreenPos DEFAULT_VALUE(float4(0,0,0,0));
BOOL bIsLightOnScreen DEFAULT_VALUE(FALSE);
float fNumCascades DEFAULT_VALUE(0);
float fFirstCascadeToRayMarch DEFAULT_VALUE(0);
int Padding0;
};
#ifdef CHECK_STRUCT_ALIGNMENT
CHECK_STRUCT_ALIGNMENT(EpipolarLightScatteringAttribs);
#endif
struct AirScatteringAttribs
{
// Angular Rayleigh scattering coefficient contains all the terms exepting 1 + cos^2(Theta):
// Pi^2 * (n^2-1)^2 / (2*N) * (6+3*Pn)/(6-7*Pn)
float4 f4AngularRayleighSctrCoeff;
// Total Rayleigh scattering coefficient is the integral of angular scattering coefficient in all directions
// and is the following:
// 8 * Pi^3 * (n^2-1)^2 / (3*N) * (6+3*Pn)/(6-7*Pn)
float4 f4TotalRayleighSctrCoeff;
float4 f4RayleighExtinctionCoeff;
// Note that angular scattering coefficient is essentially a phase function multiplied by the
// total scattering coefficient
float4 f4AngularMieSctrCoeff;
float4 f4TotalMieSctrCoeff;
float4 f4MieExtinctionCoeff;
float4 f4TotalExtinctionCoeff;
// Cornette-Shanks phase function (see Nishita et al. 93) normalized to unity has the following form:
// F(theta) = 1/(4*PI) * 3*(1-g^2) / (2*(2+g^2)) * (1+cos^2(theta)) / (1 + g^2 - 2g*cos(theta))^(3/2)
float4 f4CS_g; // x == 3*(1-g^2) / (2*(2+g^2))
// y == 1 + g^2
// z == -2*g
// Earth parameters can't be chnaged at run time
float fEarthRadius DEFAULT_VALUE(static_cast<float>(EARTH_RADIUS));
float fAtmBottomAltitude DEFAULT_VALUE(0.f); // Altitude of the bottom atmosphere boundary (sea level by default)
float fAtmTopAltitude DEFAULT_VALUE(80000.f); // Altitude of the top atmosphere boundary, 80 km by default
float fTurbidity DEFAULT_VALUE(1.02f);
float fAtmBottomRadius DEFAULT_VALUE(fEarthRadius + fAtmBottomAltitude);
float fAtmTopRadius DEFAULT_VALUE(fEarthRadius + fAtmTopAltitude);
float fAtmAltitudeRangeInv DEFAULT_VALUE(1.f / (fAtmTopAltitude - fAtmBottomAltitude));
float fAerosolPhaseFuncG DEFAULT_VALUE(0.76f);
float4 f4ParticleScaleHeight DEFAULT_VALUE(float4(7994.f, 1200.f, 1.f/7994.f, 1.f/1200.f));
};
#ifdef CHECK_STRUCT_ALIGNMENT
CHECK_STRUCT_ALIGNMENT(AirScatteringAttribs);
#endif
// Internal structure used by the effect
struct MiscDynamicParams
{
float fMaxStepsAlongRay; // Maximum number of steps during ray tracing
float fCascadeInd;
float fElapsedTime;
float fDummy;
#ifdef __cplusplus
uint ui4SrcMinMaxLevelXOffset;
uint ui4SrcMinMaxLevelYOffset;
uint ui4DstMinMaxLevelXOffset;
uint ui4DstMinMaxLevelYOffset;
#else
uint4 ui4SrcDstMinMaxLevelOffset;
#endif
};
#ifdef CHECK_STRUCT_ALIGNMENT
CHECK_STRUCT_ALIGNMENT(MiscDynamicParams);
#endif
#endif //_EPIPOLAR_LIGHT_SCATTERING_STRCUTURES_FXH_
|