/* =========================================================================== 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: shared data structures and functions #pragma once #include "typedefs.h.hlsli" #if !defined(__cplusplus) #include "common.hlsli" #include "simplex_noise.hlsli" #endif #if defined(__cplusplus) #pragma pack(push, 1) #endif struct FogVolume { float3 scatter; float absorption; float3 emissive; float anisotropy; float3 boxMin; float noiseMin; float3 boxMax; float noiseMax; float noiseScale; float noiseTimeScale; uint isHeightFog; #if !defined(__cplusplus) bool IsPointInside(float3 position) { return IsInRange(position, boxMin, boxMax); } float DensityAt(float3 position, float time) { float4 positionTime = float4(position * noiseScale, time * noiseTimeScale); float density = noiseMin + (noiseMax - noiseMin) * SimplexNoise4D(positionTime); if(isHeightFog) { float maxHeight = boxMax.z - boxMin.z; float height = position.z - boxMin.z; density *= 1.0 - EaseOutCubic(height / maxHeight); } return density; } #endif }; struct Tile { uint firstParticle; uint particleCount; uint particleIndex; uint pad0; }; struct Counters { uint particleCount; uint tileCount; }; #if defined(__cplusplus) #pragma pack(pop) #endif #if !defined(__cplusplus) // defines voxel sampling offsets for super-sampled fog/particle injection #if defined(VOXEL_SUPERSAMPLING_1X) static const int VoxelSampleCount = 1; static const float3 VoxelSamples[1] = { float3(0, 0, 0) }; #elif defined(VOXEL_SUPERSAMPLING_2X) static const float Offset = 0.1666666666666666666666666666666; static const int VoxelSampleCount = 9; static const float3 VoxelSamples[9] = { float3(0, 0, 0), float3(-Offset, -Offset, -Offset), float3(-Offset, -Offset, +Offset), float3(-Offset, +Offset, -Offset), float3(-Offset, +Offset, +Offset), float3(+Offset, -Offset, -Offset), float3(+Offset, -Offset, +Offset), float3(+Offset, +Offset, -Offset), float3(+Offset, +Offset, +Offset) }; #elif defined(VOXEL_SUPERSAMPLING_3X) static const int VoxelSampleCount = 27; static const float3 VoxelSamples[27] = { float3(-0.25, -0.25, -0.25), float3(-0.25, -0.25, 0), float3(-0.25, -0.25, 0.25), float3(-0.25, 0, -0.25), float3(-0.25, 0, 0), float3(-0.25, 0, 0.25), float3(-0.25, 0.25, -0.25), float3(-0.25, 0.25, 0), float3(-0.25, 0.25, 0.25), float3(0, -0.25, -0.25), float3(0, -0.25, 0), float3(0, -0.25, 0.25), float3(0, 0, -0.25), float3(0, 0, 0), float3(0, 0, 0.25), float3(0, 0.25, -0.25), float3(0, 0.25, 0), float3(0, 0.25, 0.25), float3(0.25, -0.25, -0.25), float3(0.25, -0.25, 0), float3(0.25, -0.25, 0.25), float3(0.25, 0, -0.25), float3(0.25, 0, 0), float3(0.25, 0, 0.25), float3(0.25, 0.25, -0.25), float3(0.25, 0.25, 0), float3(0.25, 0.25, 0.25) }; #elif defined(VOXEL_SUPERSAMPLING_4X) static const int VoxelSampleCount = 65; static const float3 VoxelSamples[65] = { float3(0, 0, 0), float3(-0.3, -0.3, -0.3), float3(-0.3, -0.3, -0.1), float3(-0.3, -0.3, 0.1), float3(-0.3, -0.3, 0.3), float3(-0.3, -0.1, -0.3), float3(-0.3, -0.1, -0.1), float3(-0.3, -0.1, 0.1), float3(-0.3, -0.1, 0.3), float3(-0.3, 0.1, -0.3), float3(-0.3, 0.1, -0.1), float3(-0.3, 0.1, 0.1), float3(-0.3, 0.1, 0.3), float3(-0.3, 0.3, -0.3), float3(-0.3, 0.3, -0.1), float3(-0.3, 0.3, 0.1), float3(-0.3, 0.3, 0.3), float3(-0.1, -0.3, -0.3), float3(-0.1, -0.3, -0.1), float3(-0.1, -0.3, 0.1), float3(-0.1, -0.3, 0.3), float3(-0.1, -0.1, -0.3), float3(-0.1, -0.1, -0.1), float3(-0.1, -0.1, 0.1), float3(-0.1, -0.1, 0.3), float3(-0.1, 0.1, -0.3), float3(-0.1, 0.1, -0.1), float3(-0.1, 0.1, 0.1), float3(-0.1, 0.1, 0.3), float3(-0.1, 0.3, -0.3), float3(-0.1, 0.3, -0.1), float3(-0.1, 0.3, 0.1), float3(-0.1, 0.3, 0.3), float3(0.1, -0.3, -0.3), float3(0.1, -0.3, -0.1), float3(0.1, -0.3, 0.1), float3(0.1, -0.3, 0.3), float3(0.1, -0.1, -0.3), float3(0.1, -0.1, -0.1), float3(0.1, -0.1, 0.1), float3(0.1, -0.1, 0.3), float3(0.1, 0.1, -0.3), float3(0.1, 0.1, -0.1), float3(0.1, 0.1, 0.1), float3(0.1, 0.1, 0.3), float3(0.1, 0.3, -0.3), float3(0.1, 0.3, -0.1), float3(0.1, 0.3, 0.1), float3(0.1, 0.3, 0.3), float3(0.3, -0.3, -0.3), float3(0.3, -0.3, -0.1), float3(0.3, -0.3, 0.1), float3(0.3, -0.3, 0.3), float3(0.3, -0.1, -0.3), float3(0.3, -0.1, -0.1), float3(0.3, -0.1, 0.1), float3(0.3, -0.1, 0.3), float3(0.3, 0.1, -0.3), float3(0.3, 0.1, -0.1), float3(0.3, 0.1, 0.1), float3(0.3, 0.1, 0.3), float3(0.3, 0.3, -0.3), float3(0.3, 0.3, -0.1), float3(0.3, 0.3, 0.1), float3(0.3, 0.3, 0.3), }; #endif // defines sphere sampling offsets for super-sampled particle injection #if defined(SPHERE_SUPERSAMPLING_1X) static const int SphereSampleCount = 1; static const float3 SphereSamples[1] = { float3(0, 0, 0) }; #elif defined(SPHERE_SUPERSAMPLING_2X) static const int SphereSampleCount = 13; static const float3 SphereSamples[13] = { float3(-0.000070998815798, -0.000005560663499, -0.666666662862852), float3(-0.184273763669020, -0.567104158597683, -0.298128324331843), float3(0.482401099870031, -0.350493177757963, -0.298141167291191), float3(-0.596343845795264, -0.000022877791848, -0.298024263279293), float3(0.482326151451980, 0.350363917328204, -0.298414231403936), float3(-0.184272548445118, 0.567103656272574, -0.298130030986924), float3(0.000000000000000, 0.000000000000000, 0.000000000000000), float3(0.184241177452589, -0.567097520996929, 0.298161088431179), float3(-0.482404802195943, -0.350487719732367, 0.298141593172679), float3(0.596236953290593, -0.000018337625111, 0.298238058669458), float3(-0.482641375963473, 0.350268310738867, 0.298016538374417), float3(0.184262272798761, 0.567101475888716, 0.298140529469443), float3(-0.000135987657896, -0.000010037080285, 0.666666652721627) }; #elif defined(SPHERE_SUPERSAMPLING_2X_OLD) // 8x with 0,0,0 added static const int SphereSampleCount = 9; static const float3 SphereSamples[9] = { float3(0, 0, 0), float3(-0.378024926878978, -0.378024806866870, -0.317879684372474), float3(0.378024762722181, -0.378024944670528, -0.317879715711806), float3(-0.378024789075323, 0.378024882734286, -0.317879758027500), float3(0.378024900525835, 0.378024744930628, -0.317879789366832), float3(-0.000000084265328, -0.534607831462839, 0.317879788951622), float3(-0.534607849254392, 0.000000128410024, 0.317879759029907), float3(0.534607875607536, -0.000000066473779, 0.317879714709398), float3(0.000000110618471, 0.534607893399083, 0.317879684787684) }; #endif #endif