summaryrefslogtreecommitdiffstats
path: root/Shaders/PostProcess/EpipolarLightScattering/private/UnshadowedScattering.fxh
blob: b4612ed34562f4169e3be1969adc0345b9c5cf9b (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
void ComputeUnshadowedInscattering(float2     f2SampleLocation, 
                                   float      fCamSpaceZ,
                                   uint       uiNumSteps,
                                   float3     f3EarthCentre,
                                   out float3 f3Inscattering,
                                   out float3 f3Extinction)
{
    f3Inscattering = float3(0.0, 0.0, 0.0);
    f3Extinction = float3(1.0, 1.0, 1.0);
    float3 f3RayTermination = ProjSpaceXYZToWorldSpace( float3(f2SampleLocation, fCamSpaceZ), g_CameraAttribs.mProj, g_CameraAttribs.mViewProjInv );
    float3 f3CameraPos = g_CameraAttribs.f4Position.xyz;
    float3 f3ViewDir = f3RayTermination - f3CameraPos;
    float fRayLength = length(f3ViewDir);
    f3ViewDir /= fRayLength;

    float4 f4Isecs;
    GetRaySphereIntersection2(f3CameraPos, f3ViewDir, f3EarthCentre, 
                              float2(g_MediaParams.fAtmTopRadius, g_MediaParams.fAtmBottomRadius), f4Isecs);
    float2 f2RayAtmTopIsecs = f4Isecs.xy; 
    float2 f2RayEarthIsecs  = f4Isecs.zw;

    if( f2RayAtmTopIsecs.y <= 0.0 )
    {
        //                                                          view dir
        //                                                        /
        //             d<0                                       /
        //               *--------->                            *
        //            .      .                             .   /  . 
        //  .  '                    '  .         .  '         /\         '  .
        //                                                   /  f2rayatmtopisecs.y < 0
        //
        // the camera is outside the atmosphere and the ray either does not intersect the
        // top of it or the intersection point is behind the camera. In either
        // case there is no inscattering
        return;
    }

    float3 f3RayStart = f3CameraPos + f3ViewDir * max(0.0, f2RayAtmTopIsecs.x);
    if( fCamSpaceZ > g_CameraAttribs.fFarPlaneZ ) // fFarPlaneZ is pre-multiplied with 0.999999f
        fRayLength = +FLT_MAX;
    fRayLength = min(fRayLength, f2RayAtmTopIsecs.y);
    // If there is an intersection with the Earth surface, limit the tracing distance to the intersection
    if( f2RayEarthIsecs.x > 0.0 )
    {
        fRayLength = min(fRayLength, f2RayEarthIsecs.x);
    }    
    float3 f3RayEnd = f3CameraPos + f3ViewDir * fRayLength;

#if SINGLE_SCATTERING_MODE == SINGLE_SCTR_MODE_INTEGRATION
    IntegrateUnshadowedInscattering(f3RayStart, 
                                    f3RayEnd,
                                    f3ViewDir,
                                    f3EarthCentre,
                                    g_MediaParams.fEarthRadius,
                                    g_MediaParams.fAtmBottomAltitude,
                                    g_MediaParams.fAtmAltitudeRangeInv,
                                    g_MediaParams.f4ParticleScaleHeight,
                                    -g_LightAttribs.f4Direction.xyz,
                                    uiNumSteps,
                                    f3Inscattering,
                                    f3Extinction);
#endif

#if SINGLE_SCATTERING_MODE == SINGLE_SCTR_MODE_LUT || MULTIPLE_SCATTERING_MODE > MULTIPLE_SCTR_MODE_NONE

#if MULTIPLE_SCATTERING_MODE > MULTIPLE_SCTR_MODE_NONE
    #if SINGLE_SCATTERING_MODE == SINGLE_SCTR_MODE_LUT
        #define tex3DSctrLUT         g_tex3DMultipleSctrLUT
        #define tex3DSctrLUT_sampler g_tex3DMultipleSctrLUT_sampler
    #elif SINGLE_SCATTERING_MODE == SINGLE_SCTR_MODE_NONE || SINGLE_SCATTERING_MODE == SINGLE_SCTR_MODE_INTEGRATION
        #define tex3DSctrLUT         g_tex3DHighOrderSctrLUT
        #define tex3DSctrLUT_sampler g_tex3DHighOrderSctrLUT_sampler
    #endif
#else
    #define tex3DSctrLUT         g_tex3DSingleSctrLUT
    #define tex3DSctrLUT_sampler g_tex3DSingleSctrLUT_sampler
#endif

    f3Extinction = GetExtinctionUnverified(f3RayStart, f3RayEnd, f3ViewDir, f3EarthCentre, g_MediaParams.fEarthRadius, g_MediaParams.f4ParticleScaleHeight);

    // To avoid artifacts, we must be consistent when performing look-ups into the scattering texture, i.e.
    // we must assure that if the first look-up is above (below) horizon, then the second look-up
    // is also above (below) horizon. 
    float4 f4UVWQ = float4(-1.0, -1.0, -1.0, -1.0);
    f3Inscattering += 
        LookUpPrecomputedScattering(
            f3RayStart,
            f3ViewDir,
            f3EarthCentre,
            g_MediaParams.fEarthRadius,
            -g_LightAttribs.f4Direction.xyz,
            g_MediaParams.fAtmBottomAltitude,
            g_MediaParams.fAtmTopAltitude,
            tex3DSctrLUT,
            tex3DSctrLUT_sampler,
            f4UVWQ); 

    // Provide previous look-up coordinates to the function to assure that look-ups are consistent
    f3Inscattering -= f3Extinction *
        LookUpPrecomputedScattering(
            f3RayEnd,
            f3ViewDir,
            f3EarthCentre,
            g_MediaParams.fEarthRadius,
            -g_LightAttribs.f4Direction.xyz,
            g_MediaParams.fAtmBottomAltitude,
            g_MediaParams.fAtmTopAltitude,
            tex3DSctrLUT,
            tex3DSctrLUT_sampler,
            f4UVWQ);

    #undef tex3DSctrLUT
    #undef tex3DSctrLUT_sampler
#endif

}