summaryrefslogtreecommitdiffstats
path: root/Shaders/PostProcess/EpipolarLightScattering/public/EpipolarLightScatteringStructures.fxh
blob: dcebf45263a87422ed3a7ea321a2169500063d5f (plain)
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_