cnq3/code/renderer/crp_local.h

897 lines
22 KiB
C++

/*
===========================================================================
Copyright (C) 2023-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 <https://www.gnu.org/licenses/>.
===========================================================================
*/
// Cinematic Rendering Pipeline - private declarations
#pragma once
#include "srp_local.h"
extern cvar_t* crp_dof;
extern cvar_t* crp_dof_overlay;
extern cvar_t* crp_dof_blades;
extern cvar_t* crp_dof_angle;
extern cvar_t* crp_gatherDof_focusNearDist;
extern cvar_t* crp_gatherDof_focusNearRange;
extern cvar_t* crp_gatherDof_focusFarDist;
extern cvar_t* crp_gatherDof_focusFarRange;
extern cvar_t* crp_gatherDof_brightness;
extern cvar_t* crp_accumDof_focusDist;
extern cvar_t* crp_accumDof_radius;
extern cvar_t* crp_accumDof_samples;
extern cvar_t* crp_accumDof_preview;
extern cvar_t* crp_mblur;
extern cvar_t* crp_mblur_exposure;
extern cvar_t* crp_sunlight;
extern cvar_t* crp_volLight;
extern cvar_t* crp_drawNormals;
extern cvar_t* crp_updateRTAS;
extern cvar_t* crp_debug0;
extern cvar_t* crp_debug1;
extern cvar_t* crp_debug2;
extern cvar_t* crp_debug3;
struct DOFMethod
{
enum Id
{
None,
Gather,
Accumulation,
Count
};
};
struct MotionBlurModes
{
enum Flags
{
CameraBit = 1 << 0,
ObjectBit = 1 << 1
};
enum Id
{
None,
CameraOnly = CameraBit,
ObjectOnly = ObjectBit,
Full = CameraOnly + ObjectOnly
};
};
struct Tessellator
{
enum Id
{
None,
Prepass,
Opaque,
Transp,
Count
};
};
using namespace RHI;
struct WorldVertexRC
{
float modelViewMatrix[16];
};
struct PSOCache
{
struct Entry
{
GraphicsPipelineDesc desc;
HPipeline handle;
};
void Init(Entry* entries, uint32_t maxEntryCount);
int AddPipeline(const GraphicsPipelineDesc& desc, const char* name);
Entry* entries = NULL;
uint32_t maxEntryCount = 0;
uint32_t entryCount = 1; // we treat index 0 as invalid
};
struct Prepass
{
void Init();
void Draw(const drawSceneViewCommand_t& cmd);
void ProcessShader(shader_t& shader);
void TessellationOverflow();
private:
void BeginBatch(const shader_t* shader);
void EndBatch();
PSOCache::Entry psoCacheEntries[128];
PSOCache psoCache;
bool batchOldDepthHack;
bool batchDepthHack;
int batchEntityId;
float batchMotionScale;
HPipeline skyboxMotionPipeline;
};
struct WorldOpaque
{
void Init();
void Draw(const drawSceneViewCommand_t& cmd);
void ProcessShader(shader_t& shader);
void TessellationOverflow();
void DrawSkyBox();
void DrawClouds();
private:
void BeginBatch(const shader_t* shader);
void EndBatch();
void EndSkyBatch();
PSOCache::Entry psoCacheEntries[128];
PSOCache psoCache;
bool batchOldDepthHack;
bool batchDepthHack;
HPipeline wireframeNormalsPipeline;
};
struct WorldTransp
{
void Init();
void Draw(const drawSceneViewCommand_t& cmd);
void ProcessShader(shader_t& shader);
void TessellationOverflow();
private:
void BeginBatch(const shader_t* shader);
void EndBatch();
PSOCache::Entry psoCacheEntries[32];
PSOCache psoCache;
bool batchOldDepthHack;
bool batchDepthHack;
};
struct TranspResolve
{
void Init();
void Draw(const drawSceneViewCommand_t& cmd);
private:
HPipeline noVolPipeline;
HPipeline volPipeline;
};
struct ToneMap
{
void Init();
void DrawToneMap();
void DrawInverseToneMap();
private:
HPipeline pipeline;
HPipeline inversePipeline;
};
struct AccumDepthOfField
{
void Init();
void Begin(const drawSceneViewCommand_t& cmd);
uint32_t GetSampleCount();
void FixCommand(drawSceneViewCommand_t& newCmd, const drawSceneViewCommand_t& cmd, uint32_t x, uint32_t y);
void Accumulate();
void Normalize();
void DrawDebug();
private:
HPipeline accumPipeline;
HPipeline normPipeline;
HPipeline debugPipeline;
HTexture accumTexture;
float maxNearCocCS;
float maxFarCocCS;
float modelViewMatrix[16];
float projMatrix[16];
};
struct GatherDepthOfField
{
void Init();
void Draw();
private:
void DrawDebug();
void DrawSplit();
void DrawNearCocTileGen();
void DrawNearCocTileMax();
void DrawBlur();
void DrawFill();
void DrawCombine();
HPipeline debugPipeline;
HPipeline splitPipeline;
HPipeline nearCocTileGenPipeline;
HPipeline nearCocTileMaxPipeline;
HPipeline blurPipeline;
HPipeline fillPipeline;
HPipeline combinePipeline;
HTexture nearColorTexture;
HTexture farColorTexture;
HTexture nearBlurTexture;
HTexture farBlurTexture;
HTexture nearCocTexture;
HTexture nearCocTexture2;
HTexture nearCocTileTexture;
HTexture nearCocTileTexture2;
HTexture farCocTexture;
uint32_t tileTextureWidth;
uint32_t tileTextureHeight;
};
struct MotionBlur
{
void Init();
void Draw();
private:
void DrawPack();
void DrawTileGen();
void DrawTileMax();
void DrawBlur();
HPipeline packPipeline;
HPipeline tileGenPipeline;
HPipeline tileMaxPipeline;
HPipeline blurPipeline;
HTexture tileTexture;
HTexture tileTexture2;
HTexture packedTexture;
uint32_t tileTextureWidth;
uint32_t tileTextureHeight;
};
struct Magnifier
{
void Init();
void Draw();
void DrawGUI();
private:
HPipeline pipeline;
bool magnifierActive = false;
};
struct GBufferViz
{
void Init();
void DrawGUI();
private:
struct GBufferTexture
{
enum Id
{
Depth,
Normal,
Light,
ShadingPositionDelta,
MotionVectorRaw,
MotionVectorMB,
SunlightVisibility,
SunlightPenumbra,
Sunlight,
Count
};
};
HPipeline linearizeDepthPipeline;
HPipeline decodeNormalsPipeline;
HPipeline decodeShadingPositionPipeline;
HPipeline motionVectorPipeline;
bool windowActive = false;
int textureIndex = 0;
bool coloredPositionDelta = false;
bool fullResolution = false;
};
struct DynamicLights
{
void Init();
void DrawBegin();
void DrawPointLight(const dlight_t& light);
bool WantRTASUpdate(const trRefdef_t& scene);
private:
HPipeline pipeline;
HPipeline denoisingPipeline;
};
struct Raytracing
{
void Init();
void ProcessWorld(world_t& world);
void BeforeFrame(bool wantUpdate);
void BeginFrame(bool wantUpdate);
uint32_t GetTLASBufferIndex();
uint32_t GetInstanceBufferIndex();
bool CanRaytrace();
private:
struct BLASBuildBuffers;
struct BLASBuffers;
struct ISurfaceList;
void TagMapSurfacesRecursively(mnode_t* node);
void ProcessStaticSurfaces();
void EnsureBuffersAreLargeEnough(BLASBuildBuffers& buffers, uint32_t maxVertexCount, uint32_t maxIndexCount);
void EnsureBuffersAreLargeEnough(BLASBuffers& buffers, uint32_t maxVertexCount, uint32_t maxIndexCount, uint32_t maxMeshCount);
void BuildBLASes(BLASBuffers* blasBuffers, struct BLASBuilder* blasBuilders, ISurfaceList* surfaceList);
uint32_t GetRTFrameIndex() { return frameCount % RTFrameCount; }
enum Constants
{
RTFrameCount = RHI::FrameCount
};
struct BLASBucket
{
enum Constants
{
Count = CT_COUNT
};
};
struct BLASBuildBuffers
{
HBuffer vertexBuffer;
HBuffer indexBuffer;
uint32_t vertexBufferByteCount;
uint32_t indexBufferByteCount;
};
struct BLASBuffers
{
HBuffer blasBuffer;
HBuffer vertexBuffer;
HBuffer indexBuffer;
HBuffer meshBuffer;
uint32_t vertexBufferByteCount;
uint32_t indexBufferByteCount;
uint32_t meshBufferByteCount;
};
struct Surface
{
const surfaceType_t* surface;
const shader_t* shader;
int entityNum;
};
struct ISurfaceList
{
virtual uint32_t GetSurfaceCount() = 0;
virtual bool GetSurface(Surface& surface, uint32_t index) = 0; // true when skipped
};
struct WorldSurfaceList : ISurfaceList
{
uint32_t GetSurfaceCount() override;
bool GetSurface(Surface& surface, uint32_t index) override;
};
struct DynamicSurfaceList : ISurfaceList
{
uint32_t GetSurfaceCount() override;
bool GetSurface(Surface& surface, uint32_t index) override;
};
struct FrameData
{
BLASBuildBuffers blasBuildBuffers[BLASBucket::Count] = {};
BLASBuffers dynamicBLASBuffers[BLASBucket::Count] = {};
HBuffer tlasBuffer = RHI_MAKE_NULL_HANDLE();
HBuffer tlasInstanceBuffer = RHI_MAKE_NULL_HANDLE();
};
FrameData frameData[RTFrameCount];
BLASBuffers staticBLASBuffers[BLASBucket::Count] = {};
StaticArray<TLASInstanceDesc, 2 * BLASBucket::Count> tlasInstanceDescs;
uint32_t staticTLASInstanceCount = 0;
bool pendingWorldProcess = false;
uint32_t frameCount = 0;
// we have a local frame counter because (for now)
// RHI::GetFrameIndex() increments during RHI::BeginFrame()
// in a given frame, we need BeforeFrame and BeginFrame to use the same buffer index
};
struct SunlightEditor
{
void Init();
void ProcessWorld(world_t& world);
void DrawOverlay();
void DrawGUI();
private:
HPipeline pipeline;
bool windowActive = false;
bool drawOverlay = false;
const shader_t* skyShader = NULL;
};
struct Sunlight
{
void Init();
void Draw();
bool WantRTASUpdate(const trRefdef_t& scene);
//private:
HPipeline visibilityPipeline;
HPipeline blurPipeline;
HTexture visibilityTexture;
HTexture penumbraTexture;
};
struct VDBSequenceDesc
{
const char* folderPath = NULL;
const char* smokeGridName = "density";
const char* fireGridName = "flames";
vec3_t originOffset = {}; // index space
vec3_t position = { 700 }; // world space
vec3_t anglesRad = {}; // in radians
vec3_t scale = { 1.0f, 1.0f, 1.0f };
float smokeExtinctionScale = 1.0f;
float smokeAlbedo = 0.9f; // real smoke: 0.9 to 0.97
float fireEmissionScale = 0.1f;
float fireTemperatureScale = 1000.0f;
float frameRate = 60.0f;
int startTimeMS = 0;
int startTimeUS = 0;
bool loop = false;
bool useSequenceOffset = true;
bool gpuResident = false;
};
struct NanoVDBManager
{
struct Instance;
struct DrawInstance;
struct CPUFrame;
void Init();
void DrawGUI();
void DrawIm3d();
void BeforeFrame();
bool AddSequence(const VDBSequenceDesc& desc);
void MakeWorldToIndexMatrix(matrix3x3_t matrix, const Instance& instance);
void Purge();
int FindStreamedFrameIndex(uint32_t sequenceIndex, uint32_t frameIndex);
struct Sequence
{
char folderPath[64];
vec3_t originOffset;
vec3_t scale;
HBuffer buffer;
uint32_t bufferByteCount;
uint32_t frameCount;
uint32_t firstFrameIndex;
};
struct Instance
{
char smokeGridName[64];
char fireGridName[64];
vec3_t originOffset; // index space
vec3_t position; // world space
vec3_t anglesRad; // in radians
vec3_t scale;
float smokeExtinctionScale;
float smokeAlbedo;
float fireEmissionScale;
float fireTemperatureScale;
float frameRate;
int startTimeMS;
int startTimeUS;
uint32_t sequenceIndex;
bool loop;
};
struct DrawInstance
{
HBuffer buffer;
uint32_t smokeByteOffset;
uint32_t fireByteOffset;
uint32_t smokeByteOffset2;
uint32_t fireByteOffset2;
float t;
};
struct GPUFrame
{
uint32_t smokeByteOffset;
uint32_t fireByteOffset;
};
struct CPUFrame
{
char filePath[64];
uint32_t smokeByteOffset;
uint32_t smokeByteCount;
uint32_t fireByteOffset;
uint32_t fireByteCount;
};
struct StreamedFrame
{
uint32_t sequenceIndex;
uint32_t frameIndex;
uint32_t smokeByteOffset;
uint32_t flamesByteOffset;
};
StaticArray<Sequence, 16> sequences;
StaticArray<Instance, 64> instances;
StaticArray<DrawInstance, 64> drawInstances; // for the current frame
StaticArray<StreamedFrame, 128> streamedFrames; // for the current frame
StaticArray<GPUFrame, 4096> gpuFrames;
StaticArray<CPUFrame, 4096> cpuFrames;
HBuffer streamBuffers[FrameCount + 1];
uint32_t streamBufferByteCount;
uint32_t streamBufferIndex;
bool windowActive = false;
bool linearInterpolation = false;
bool accurateOverlapTest = false;
bool supersampling = false;
int ambientRaymarchLOD = 8;
bool ambientIncreasedCoverage = true;
bool previewMode = false;
float emissiveScatterScale = 0.5f;
int activeInstanceIndex = -1;
};
struct ParticleSystem
{
void Init();
void Draw();
//private:
HPipeline clearPipeline;
HPipeline setupPipeline;
HPipeline emitPipeline;
HPipeline simulatePipeline;
HBuffer particleBuffer;
HBuffer liveBuffers[2]; // indices before and after simulation
HBuffer deadBuffer; // indices
HBuffer emitterBuffer;
HBuffer indirectBuffer; // 0: emit dispatch, 1: simulate dispatch
uint32_t liveBufferReadIndex;
bool needsClearing;
};
struct VolumetricLight
{
void Init();
void ProcessWorld(world_t& world);
void DrawBegin();
void DrawPointLight(const dlight_t& light);
void DrawSunlight();
void DrawEnd();
void DrawDebug();
void DrawGUI();
void DrawIm3d();
bool WantRTASUpdate(const trRefdef_t& scene);
bool ShouldDraw();
bool ShouldDrawDebug();
bool LoadFogFile(const char* filePath);
void SaveFogFile(const char* filePath);
void SetLightGridRootConstants(struct LightGridRC& rc);
// GUI/user-friendly data layout
struct Fog
{
vec3_t scatterColor;
vec3_t emissiveColor;
vec3_t boxCenter;
vec3_t boxSize;
float extinction;
float albedo; // thin fog: 0.3 to 0.5, thick fog: 0.6 to 0.9
float emissive;
float anisotropy; // thin fog: 0.9, thick fog: 0.9 with strong backscatter
float noiseStrength;
float noiseSpatialPeriod;
float noiseTimePeriod;
bool isGlobalFog;
bool isHeightFog;
};
Fog fogs[64];
uint32_t fogCount = 0;
HPipeline extinctionFogPipeline;
HPipeline extinctionVDBPipeline;
HPipeline frustumAmbientPipeline;
HPipeline frustumAnisotropyPipeline;
HPipeline frustumFogPipeline;
HPipeline frustumLightPropNXPipeline;
HPipeline frustumLightPropNYPipeline;
HPipeline frustumLightPropPXPipeline;
HPipeline frustumLightPropPYPipeline;
HPipeline frustumParticlePipeline;
HPipeline frustumPointLightScatterPipeline;
HPipeline frustumRaymarchPipeline;
HPipeline frustumSunlightVisPipeline;
HPipeline frustumTemporalFloatPipeline;
HPipeline frustumTemporalFloat4Pipeline;
HPipeline frustumVDBPipeline;
HPipeline frustumVDBLQPipeline;
HPipeline frustumDepthTestPipeline;
HPipeline particleClearPipeline;
HPipeline particleHitPipeline;
HPipeline particleListPipeline;
HPipeline particleTilesPipeline;
HPipeline pointLightShadowPipeline;
HPipeline sunlightScatterPipeline;
HPipeline sunlightShadowPipeline;
HPipeline ambientVizPipeline;
HPipeline extinctionVizPipeline;
HPipeline sunShadowVizPipeline;
HTexture materialTextureA; // frustum, RGB = scatter, A = absorption
HTexture materialTextureB; // frustum, RGB = emissive, A = anisotropy (g)
HTexture materialTextureC; // frustum, R = anisotropy (g) weight sum
HTexture sunlightVisTexture; // frustum, R = sunlight visibility
HTexture prevSunlightVisTexture; // frustum, R = sunlight visibility
HTexture scatterExtTexture; // frustum, RGB = in-scattering, A = extinction
HTexture scatterTransTexture; // frustum, RGB = in-scattering, A = transmittance
HTexture extinctionTextures[4]; // cube, R = extinction
HTexture pointShadowTexture; // cube, R = transmittance
HTexture sunShadowTextures[4]; // cube, R = transmittance
HTexture ambientLightTextureA; // box, can be NULL, RGB = ambient.rgb, A = directional.r
HTexture ambientLightTextureB; // box, can be NULL, RG = directional.gb, B = longitude, A = latitude
HTexture frustumVisTexture; // screen tiles, R = Z index of furthest visible froxel tile
HBuffer particleTileBuffer; // voxel tiles: StructuredBuffer<Tile>
HBuffer particleCounterBuffer; // global counters: StructuredBuffer<Counters>
HBuffer particleTileIndexBuffer; // flattened voxel tile indices: StructuredBuffer<uint>
HBuffer particleIndexBuffer; // particle indices: StructuredBuffer<uint>
HBuffer particleDispatchBuffer; // indirect dispatch buffer
uvec3_t frustumSize; // frustum volume pixel counts
uvec3_t frustumTileScale; // by how much do we divide
uvec3_t frustumTileSize; // frustum volume tile pixel counts
uvec3_t extinctionSize; // extinction volume pixel counts
uvec3_t extinctionTileScale; // by how much do we divide
uvec3_t extinctionTileSize; // extinction volume tile pixel counts
uint32_t maxParticleIndexCount; // uint count in particleIndexBuffer
uint32_t shadowPixelCount; // @TODO: transform into uvec3_t as well
uint32_t jitterCounter;
uint32_t depthMip; // has to match the X/Y scale of frustumSize
vec4_t extinctionVolumeScale; // how many world units per pixel
float pointShadowVolumeScale; // how many world units per pixel
vec4_t sunShadowVolumeScale; // how many world units per pixel
uvec3_t sunShadowSize; // sunlight shadow volume pixel counts
vec3_t ambientColorGUI;
vec3_t ambientColor; // normalized to 0.5 brightness
float ambientIntensity;
float pointLightIntensity = 20.0f;
vec3_t debugCameraPosition;
float debugBoxScale = 1.0f;
float debugExtinctionScale = 50.0f;
int debugExtinctionCascadeIndex = 0;
int debugSunShadowCascadeIndex = 0;
bool drawExtinctionDebug = false;
bool drawSunShadowDebug = false;
bool drawAmbientDebug = false;
bool lockCameraPosition = false;
bool firstFrame = true;
bool windowActive = false;
bool drawSunlight = true;
bool enableLightGrid = true;
vec3_t mapBoxMin;
vec3_t mapBoxMax;
vec3_t lightGridCenter;
float debugSphereScale = 0.5f;
int xySubsampling = 2;
int zResolution = 256;
int extinctionResolution = 128;
int sunShadowResolution = 128;
int pointShadowResolution = 64;
int activeFogIndex = -1; // tab GUI index
};
#pragma pack(push, 1)
struct SunlightData
{
vec3_t direction;
vec3_t color;
float intensityVL = 40.0f;
float intensityDL = 2.0f;
};
#pragma pack(pop)
struct BaseBufferId
{
enum Id
{
Position,
Normal,
Count
};
};
struct StageBufferId
{
enum Id
{
TexCoords,
Color,
Count
};
};
struct GeoBuffers
{
void Create(const char* name, uint32_t vertexCount, uint32_t indexCount);
void Rewind();
void BeginUpload();
void EndUpload();
void UploadBase();
void UploadStage(uint32_t svarsIndex);
void EndBaseBatch(uint32_t vertexCount);
bool CanAdd(uint32_t vertexCount, uint32_t indexCount, uint32_t stageCount);
void DrawStage(uint32_t vertexCount, uint32_t indexCount);
void DrawPositionOnly(uint32_t vertexCount, uint32_t indexCount);
void UploadAndDrawDebugNormals();
GeometryBuffer baseVertexBuffers[BaseBufferId::Count];
GeometryBuffer stageVertexBuffers[StageBufferId::Count];
IndexBuffer indexBuffer;
HBuffer vertexBuffers[BaseBufferId::Count + StageBufferId::Count];
uint32_t vertexBufferStrides[BaseBufferId::Count + StageBufferId::Count];
};
struct FreezeFrame
{
enum Id
{
Inactive,
Pending,
Active,
PendingBeforeMB,
ActiveBeforeMB
};
};
struct CRP : IRenderPipeline
{
void Init() override;
void LoadResources() override;
void ShutDown(bool fullShutDown) override;
void ProcessWorld(world_t& world) override;
void ProcessModel(model_t& model) override;
void ProcessShader(shader_t& shader) override;
void CreateTexture(image_t* image, int mipCount, int width, int height) override;
void UpoadTextureAndGenerateMipMaps(image_t* image, const byte* data) override;
void BeginTextureUpload(MappedTexture& mappedTexture, image_t* image) override;
void EndTextureUpload() override;
void ExecuteRenderCommands(const byte* data, bool readbackRequested) override;
void TessellationOverflow() override;
void DrawSkyBox() override { opaque.DrawSkyBox(); }
void DrawClouds() override { opaque.DrawClouds(); }
void ReadPixels(int w, int h, int alignment, colorSpace_t colorSpace, void* out) override;
uint32_t GetSamplerDescriptorIndexFromBaseIndex(uint32_t baseIndex) override;
void BeginFrame();
void EndFrame();
void Blit(HTexture destination, HTexture source, const char* passName, bool hdr, const vec2_t tcScale, const vec2_t tcBias);
void BlitRenderTarget(HTexture destination, const char* passName);
void DrawSceneView(const drawSceneViewCommand_t& cmd);
void DrawSceneView3D(const drawSceneViewCommand_t& cmd);
void UploadSceneViewData();
void BuildDepthPyramid();
HTexture GetReadRenderTarget();
HTexture GetWriteRenderTarget();
void SwapRenderTargets();
// general
float frameSeed;
HTexture readbackRenderTarget;
HTexture depthTexture;
HTexture depthMinMaxTexture;
HTexture normalTexture;
HTexture motionVectorTexture; // raw, for TAA/denoisers/etc
HTexture motionVectorMBTexture; // mangled, for motion blur only
HTexture sunlightTexture;
HTexture lightTexture;
HTexture shadingPositionTexture;
HTexture renderTarget;
HTexture blackbodyTexture;
TextureFormat::Id renderTargetFormat;
HTexture renderTargets[2];
uint32_t renderTargetIndex; // the one to write to
HSampler samplers[BASE_SAMPLER_COUNT]; // all base samplers
uint32_t samplerIndices[BASE_SAMPLER_COUNT]; // descriptor heap indices
HTexture blueNoise2D;
FreezeFrame::Id freezeFrame;
HTexture frozenTexture;
HPipeline depthPyramidPipeline;
// blit
HPipeline blitPipelineLDR;
HPipeline blitPipelineHDR;
// world geometry
GeoBuffers dynBuffers[FrameCount]; // for rendering world surfaces
// scene view data
HBuffer sceneViewUploadBuffers[FrameCount];
HBuffer sceneViewBuffer; // this is the buffer that lives at ResourceDescriptorHeap[0]
uint32_t sceneViewIndex;
// for rendering transparent world surfaces
HTexture oitIndexTexture;
HBuffer oitFragmentBuffer;
HBuffer oitCounterBuffer;
HBuffer oitCounterStagingBuffer;
UI ui;
MipMapGenerator mipMapGen;
ImGUI imgui;
Im3D im3d;
Nuklear nuklear;
Prepass prepass;
WorldOpaque opaque;
WorldTransp transp;
TranspResolve transpResolve;
ToneMap toneMap;
GatherDepthOfField gatherDof;
AccumDepthOfField accumDof;
MotionBlur motionBlur;
Magnifier magnifier;
DynamicLights dynamicLights;
Sunlight sunlight;
VolumetricLight volumetricLight;
Raytracing raytracing;
GBufferViz gbufferViz;
SunlightEditor sunlightEditor;
SunlightData sunlightData;
ParticleSystem particleSystem;
NanoVDBManager vdbManager;
};
HPipeline CreateComputePipeline(const char* name, const ShaderByteCode& shader);
void MakeFullScreenPipeline(GraphicsPipelineDesc& desc, const ShaderByteCode& pixelShader);
void DirectionToAzimuthInclination(float* sc, const float* dir);
void AzimuthInclinationToDirection(float* dir, const float* sc);
extern CRP crp;