"#include \"AtmosphereShadersCommon.fxh\"\n" "\n" "#ifndef THREAD_GROUP_SIZE\n" "# define THREAD_GROUP_SIZE 16\n" "#endif\n" "\n" "cbuffer cbParticipatingMediaScatteringParams\n" "{\n" " AirScatteringAttribs g_MediaParams;\n" "}\n" "\n" "Texture3D g_tex3DPointwiseSctrRadiance;\n" "SamplerState g_tex3DPointwiseSctrRadiance_sampler;\n" "\n" "#include \"LookUpTables.fxh\"\n" "#include \"PrecomputeCommon.fxh\"\n" "\n" "RWTexture3D g_rwtex3DInsctrOrder;\n" "\n" "// This shader computes in-scattering order for a given point and direction. It performs integration of the \n" "// light scattered at particular point along the ray, see eq. (11) in [Bruneton and Neyret 08].\n" "[numthreads(THREAD_GROUP_SIZE, THREAD_GROUP_SIZE, 1)]\n" "void ComputeScatteringOrderCS(uint3 ThreadId : SV_DispatchThreadID)\n" "{\n" " // Get attributes for the current point\n" " float4 f4LUTCoords = LUTCoordsFromThreadID(ThreadId);\n" " float fAltitude, fCosViewZenithAngle, fCosSunZenithAngle, fCosSunViewAngle;\n" " InsctrLUTCoords2WorldParams(f4LUTCoords,\n" " g_MediaParams.fEarthRadius,\n" " g_MediaParams.fAtmBottomAltitude,\n" " g_MediaParams.fAtmTopAltitude,\n" " fAltitude,\n" " fCosViewZenithAngle,\n" " fCosSunZenithAngle,\n" " fCosSunViewAngle);\n" " float3 f3EarthCentre = float3(0.0, -g_MediaParams.fEarthRadius, 0.0);\n" " float3 f3RayStart = float3(0.0, fAltitude, 0.0);\n" " float3 f3ViewDir = ComputeViewDir(fCosViewZenithAngle);\n" " float3 f3DirOnLight = ComputeLightDir(f3ViewDir, fCosSunZenithAngle, fCosSunViewAngle);\n" " \n" " // Intersect the ray with the atmosphere boundaries\n" " float4 f4Isecs;\n" " GetRaySphereIntersection2( f3RayStart, f3ViewDir, f3EarthCentre, \n" " float2(g_MediaParams.fAtmBottomRadius, g_MediaParams.fAtmTopRadius), \n" " f4Isecs);\n" " float2 f2RayEarthIsecs = f4Isecs.xy;\n" " float2 f2RayAtmTopIsecs = f4Isecs.zw;\n" "\n" " if(f2RayAtmTopIsecs.y <= 0.0)\n" " {\n" " // This is just a sanity check and should never happen\n" " // as the start point is always under the top of the \n" " // atmosphere (look at InsctrLUTCoords2WorldParams())\n" " g_rwtex3DInsctrOrder[ThreadId] = float3(0.0, 0.0, 0.0); \n" " return;\n" " }\n" "\n" " float fRayLength = f2RayAtmTopIsecs.y;\n" " if(f2RayEarthIsecs.x > 0.0)\n" " fRayLength = min(fRayLength, f2RayEarthIsecs.x);\n" " \n" " float3 f3RayEnd = f3RayStart + f3ViewDir * fRayLength;\n" "\n" " const int iNumSamples = 64;\n" "\n" " float4 f4UVWQ = float4(-1.0, -1.0, -1.0, -1.0);\n" " float3 f3PrevSctrRadiance = LookUpPrecomputedScattering(\n" " f3RayStart,\n" " f3ViewDir,\n" " f3EarthCentre,\n" " g_MediaParams.fEarthRadius,\n" " f3DirOnLight.xyz,\n" " g_MediaParams.fAtmBottomAltitude,\n" " g_MediaParams.fAtmTopAltitude,\n" " g_tex3DPointwiseSctrRadiance,\n" " g_tex3DPointwiseSctrRadiance_sampler,\n" " f4UVWQ); \n" " float2 f2PrevParticleDensity = exp( -float2(fAltitude, fAltitude) * g_MediaParams.f4ParticleScaleHeight.zw );\n" "\n" " float2 f2NetParticleDensityFromCam = float2(0.0, 0.0);\n" " float3 f3Inscattering = float3(0.0, 0.0, 0.0);\n" "\n" " // We want to place more samples when the starting point is close to the surface,\n" " // but for high altitudes linear distribution works better.\n" " float fStartAltitude = length(f3RayStart - f3EarthCentre) - g_MediaParams.fEarthRadius;\n" " float pwr = lerp(2.0, 1.0, saturate((fStartAltitude - g_MediaParams.fAtmBottomAltitude) * g_MediaParams.fAtmAltitudeRangeInv));\n" "\n" " float fPrevSampleDist = 0.0;\n" " for (int iSample = 1; iSample <= iNumSamples; ++iSample)\n" " {\n" " // We need to place more samples closer to the start point and fewer samples farther away.\n" " // The ad-hoc power function does the job well.\n" " float r = pow(float(iSample) / float(iNumSamples), pwr);\n" " float3 f3Pos = lerp(f3RayStart, f3RayEnd, r);\n" " float fCurrSampleDist = fRayLength * r;\n" " float fStepLen = fCurrSampleDist - fPrevSampleDist;\n" " fPrevSampleDist = fCurrSampleDist;\n" " \n" " float fCurrHeight = length(f3Pos - f3EarthCentre) - g_MediaParams.fEarthRadius;\n" " float2 f2ParticleDensity = exp( -float2(fCurrHeight, fCurrHeight) * g_MediaParams.f4ParticleScaleHeight.zw );\n" "\n" " f2NetParticleDensityFromCam += (f2PrevParticleDensity + f2ParticleDensity) * (fStepLen / 2.0);\n" " f2PrevParticleDensity = f2ParticleDensity;\n" " \n" " // Get optical depth\n" " float3 f3RlghOpticalDepth = g_MediaParams.f4RayleighExtinctionCoeff.rgb * f2NetParticleDensityFromCam.x;\n" " float3 f3MieOpticalDepth = g_MediaParams.f4MieExtinctionCoeff.rgb * f2NetParticleDensityFromCam.y;\n" " \n" " // Compute extinction from the camera for the current integration point:\n" " float3 f3ExtinctionFromCam = exp( -(f3RlghOpticalDepth + f3MieOpticalDepth) );\n" "\n" " // Get attenuated scattered light radiance in the current point\n" " float4 f4UVWQ = float4(-1.0, -1.0, -1.0, -1.0);\n" " float3 f3SctrRadiance = f3ExtinctionFromCam *\n" " LookUpPrecomputedScattering(\n" " f3Pos,\n" " f3ViewDir,\n" " f3EarthCentre,\n" " g_MediaParams.fEarthRadius,\n" " f3DirOnLight.xyz,\n" " g_MediaParams.fAtmBottomAltitude,\n" " g_MediaParams.fAtmTopAltitude,\n" " g_tex3DPointwiseSctrRadiance,\n" " g_tex3DPointwiseSctrRadiance_sampler,\n" " f4UVWQ); \n" " // Update in-scattering integral\n" " f3Inscattering += (f3SctrRadiance + f3PrevSctrRadiance) * (fStepLen/2.0);\n" " f3PrevSctrRadiance = f3SctrRadiance;\n" " }\n" "\n" " g_rwtex3DInsctrOrder[ThreadId] = f3Inscattering;\n" "}\n"