/* =========================================================================== Copyright (C) 2024 Gian 'myT' Schellenbaum This file is part of Challenge Quake 3 (CNQ3). Challenge Quake 3 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Challenge Quake 3 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Challenge Quake 3. If not, see . =========================================================================== */ // volumetric lighting: accumulates in-scattered sunlight #include "common.hlsli" #include "scene_view.h.hlsli" #include "raytracing.h.hlsli" cbuffer RootConstants { uint materialTextureAIndex; uint materialTextureBIndex; uint scatterExtTextureIndex; uint sunlightVisTextureIndex; } [numthreads(4, 4, 4)] void cs(uint3 id : SV_DispatchThreadID) { RWTexture3D scatterExtTexture = ResourceDescriptorHeap[scatterExtTextureIndex]; uint3 textureSize = GetTextureSize(scatterExtTexture); if(any(id >= textureSize)) { return; } RWTexture3D materialTextureA = ResourceDescriptorHeap[materialTextureAIndex]; RWTexture3D materialTextureB = ResourceDescriptorHeap[materialTextureBIndex]; RWTexture3D sunlightVisTexture = ResourceDescriptorHeap[sunlightVisTextureIndex]; SceneView scene = GetSceneView(); float3 froxelSize3 = scene.FroxelAverageDimensions(id, float3(textureSize)); float froxelSize = max3(froxelSize3.x, froxelSize3.y, froxelSize3.z); SunVShadowCascade cascade = scene.GetSunVShadowCascade(froxelSize); float3 positionWS = scene.FroxelIndexToWorldSpace(id, textureSize); float visOpaque = sunlightVisTexture[id]; float visVolume = cascade.TransmittanceAt(positionWS); float vis = visOpaque * visVolume; float2 tc = (float2(id.xy) + float2(0.5, 0.5)) / float2(textureSize.xy); float2 ndc = TCToNDC(tc); float3 cameraRay = scene.CamerayRay(ndc); float cosTheta = dot(-scene.sunDirection, -cameraRay); float3 scattering = materialTextureA[id].rgb; float anisotropy = materialTextureB[id].a; float phase = HenyeyGreenstein(cosTheta, anisotropy); float3 inScattering = vis * scene.sunColor * scene.sunIntensityVL * scattering * phase; scatterExtTexture[id].rgb += inScattering; }