mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-12-02 08:52:28 +00:00
444 lines
15 KiB
C++
444 lines
15 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 - scatter-as-gather depth of field
|
|
|
|
|
|
#include "crp_local.h"
|
|
#include "compshaders/crp/fullscreen.h"
|
|
#include "compshaders/crp/gatherdof_debug.h"
|
|
#include "compshaders/crp/gatherdof_split.h"
|
|
#include "compshaders/crp/gatherdof_coc_tile_gen.h"
|
|
#include "compshaders/crp/gatherdof_coc_tile_max.h"
|
|
#include "compshaders/crp/gatherdof_blur.h"
|
|
#include "compshaders/crp/gatherdof_fill.h"
|
|
#include "compshaders/crp/gatherdof_combine.h"
|
|
|
|
|
|
#pragma pack(push, 4)
|
|
|
|
struct DOFDebugRC
|
|
{
|
|
uint32_t colorTextureIndex;
|
|
uint32_t depthTextureIndex;
|
|
uint32_t debugMode;
|
|
float linearDepthA;
|
|
float linearDepthB;
|
|
float focusNearMin;
|
|
float focusNearMax;
|
|
float focusFarMin;
|
|
float focusFarMax;
|
|
float focusDist;
|
|
};
|
|
|
|
struct DOFSplitRC
|
|
{
|
|
uint32_t depthTextureIndex;
|
|
uint32_t colorTextureIndex;
|
|
uint32_t nearColorTextureIndex;
|
|
uint32_t farColorTextureIndex;
|
|
uint32_t nearCocTextureIndex;
|
|
uint32_t farCocTextureIndex;
|
|
float linearDepthA;
|
|
float linearDepthB;
|
|
float focusNearMin;
|
|
float focusNearMax;
|
|
float focusFarMin;
|
|
float focusFarMax;
|
|
float brightnessScale;
|
|
};
|
|
|
|
struct DOFNearCocMaxRC
|
|
{
|
|
uint32_t inputTextureIndex;
|
|
uint32_t outputTextureIndex;
|
|
uint32_t samplerIndex;
|
|
int32_t kernelRadius;
|
|
float kernelDirectionX;
|
|
float kernelDirectionY;
|
|
};
|
|
|
|
struct DOFNearCocBlurRC
|
|
{
|
|
uint32_t inputTextureIndex;
|
|
uint32_t outputTextureIndex;
|
|
uint32_t samplerIndex;
|
|
int32_t kernelRadius;
|
|
float kernelDirectionX;
|
|
float kernelDirectionY;
|
|
};
|
|
|
|
struct DOFNearCocTileGenRC
|
|
{
|
|
uint32_t inputTextureIndex;
|
|
uint32_t outputTextureIndex;
|
|
};
|
|
|
|
struct DOFNearCocTileMaxRC
|
|
{
|
|
uint32_t inputTextureIndex;
|
|
uint32_t outputTextureIndex;
|
|
uint32_t samplerIndex; // point/clamp
|
|
};
|
|
|
|
struct DOFBlurRC
|
|
{
|
|
uint32_t colorTextureIndex;
|
|
uint32_t nearColorTextureIndex;
|
|
uint32_t nearMaxCocTextureIndex;
|
|
uint32_t nearCocTextureIndex; // blurry
|
|
uint32_t nearOutputTextureIndex;
|
|
uint32_t farColorTextureIndex;
|
|
uint32_t farCocTextureIndex; // sharp
|
|
uint32_t farOutputTextureIndex;
|
|
uint32_t samplerIndex; // linear/clamp
|
|
float brightnessScale;
|
|
float bladeCount;
|
|
float bokehAngleRad;
|
|
};
|
|
|
|
struct DOFFillRC
|
|
{
|
|
uint32_t nearInputTextureIndex;
|
|
uint32_t nearOutputTextureIndex;
|
|
uint32_t farInputTextureIndex;
|
|
uint32_t farOutputTextureIndex;
|
|
uint32_t samplerIndex; // point/clamp
|
|
};
|
|
|
|
struct DOFCombineRC
|
|
{
|
|
uint32_t nearTextureIndex;
|
|
uint32_t farTextureIndex;
|
|
uint32_t nearCocTextureIndex;
|
|
uint32_t farCocTextureIndex;
|
|
uint32_t sharpTextureIndex;
|
|
uint32_t samplerIndex; // point/clamp
|
|
};
|
|
|
|
#pragma pack(pop)
|
|
|
|
|
|
void GatherDepthOfField::Init()
|
|
{
|
|
const TextureFormat::Id renderTargetFormat = TextureFormat::RGBA64_Float;
|
|
|
|
tileWidth = (uint32_t)(glConfig.vidWidth + 15) / 16;
|
|
tileHeight = (uint32_t)(glConfig.vidHeight + 15) / 16;
|
|
|
|
{
|
|
ComputePipelineDesc desc("DOF split");
|
|
desc.shortLifeTime = true;
|
|
desc.shader = ShaderByteCode(g_split_cs);
|
|
splitPipeline = CreateComputePipeline(desc);
|
|
}
|
|
|
|
{
|
|
ComputePipelineDesc desc("DOF near CoC tile generation");
|
|
desc.shortLifeTime = true;
|
|
desc.shader = ShaderByteCode(g_coc_tile_gen_cs);
|
|
nearCocTileGenPipeline = CreateComputePipeline(desc);
|
|
}
|
|
|
|
{
|
|
ComputePipelineDesc desc("DOF near CoC tile dilation");
|
|
desc.shortLifeTime = true;
|
|
desc.shader = ShaderByteCode(g_coc_tile_max_cs);
|
|
nearCocTileMaxPipeline = CreateComputePipeline(desc);
|
|
}
|
|
|
|
{
|
|
ComputePipelineDesc desc("DOF blur");
|
|
desc.shortLifeTime = true;
|
|
desc.shader = ShaderByteCode(g_blur_cs);
|
|
blurPipeline = CreateComputePipeline(desc);
|
|
}
|
|
|
|
{
|
|
ComputePipelineDesc desc("DOF fill");
|
|
desc.shortLifeTime = true;
|
|
desc.shader = ShaderByteCode(g_fill_cs);
|
|
fillPipeline = CreateComputePipeline(desc);
|
|
}
|
|
|
|
{
|
|
GraphicsPipelineDesc desc("DOF combine");
|
|
desc.shortLifeTime = true;
|
|
desc.vertexShader = ShaderByteCode(g_fullscreen_vs);
|
|
desc.pixelShader = ShaderByteCode(g_combine_ps);
|
|
desc.depthStencil.DisableDepth();
|
|
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
|
desc.AddRenderTarget(0, renderTargetFormat);
|
|
combinePipeline = CreateGraphicsPipeline(desc);
|
|
}
|
|
|
|
{
|
|
GraphicsPipelineDesc desc("DOF viz");
|
|
desc.shortLifeTime = true;
|
|
desc.vertexShader = ShaderByteCode(g_fullscreen_vs);
|
|
desc.pixelShader = ShaderByteCode(g_debug_ps);
|
|
desc.depthStencil.DisableDepth();
|
|
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
|
desc.AddRenderTarget(0, renderTargetFormat);
|
|
debugPipeline = CreateGraphicsPipeline(desc);
|
|
}
|
|
|
|
{
|
|
TextureDesc desc("DOF far field color", glConfig.vidWidth, glConfig.vidHeight);
|
|
desc.shortLifeTime = true;
|
|
desc.committedResource = true;
|
|
desc.initialState = ResourceStates::UnorderedAccessBit;
|
|
desc.allowedState = ResourceStates::UnorderedAccessBit | ResourceStates::ComputeShaderAccessBit | ResourceStates::PixelShaderAccessBit;
|
|
desc.format = renderTargetFormat;
|
|
farColorTexture = CreateTexture(desc);
|
|
desc.name = "DOF near field color";
|
|
nearColorTexture = CreateTexture(desc);
|
|
desc.name = "DOF near field blurred color";
|
|
nearBlurTexture = CreateTexture(desc);
|
|
desc.name = "DOF far field blurred color";
|
|
farBlurTexture = CreateTexture(desc);
|
|
|
|
desc.format = TextureFormat::R8_UNorm;
|
|
desc.name = "DOF near field CoC #1";
|
|
nearCocTexture = CreateTexture(desc);
|
|
desc.name = "DOF near field CoC #2";
|
|
nearCocTexture2 = CreateTexture(desc);
|
|
desc.name = "DOF far field CoC";
|
|
farCocTexture = CreateTexture(desc);
|
|
|
|
desc.width = tileWidth;
|
|
desc.height = tileHeight;
|
|
desc.name = "DOF near field CoC tile #1";
|
|
nearCocTileTexture = CreateTexture(desc);
|
|
desc.name = "DOF near field CoC tile #2";
|
|
nearCocTileTexture2 = CreateTexture(desc);
|
|
}
|
|
}
|
|
|
|
void GatherDepthOfField::Draw()
|
|
{
|
|
if(crp_dof->integer != DOFMethod::Gather)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(backEnd.viewParms.viewportX != 0 ||
|
|
backEnd.viewParms.viewportY != 0 ||
|
|
backEnd.viewParms.viewportWidth != glConfig.vidWidth ||
|
|
backEnd.viewParms.viewportHeight != glConfig.vidHeight)
|
|
{
|
|
return;
|
|
}
|
|
|
|
DrawSplit();
|
|
DrawNearCocTileGen();
|
|
DrawNearCocTileMax();
|
|
DrawBlur();
|
|
DrawFill();
|
|
DrawCombine();
|
|
DrawDebug();
|
|
}
|
|
|
|
void GatherDepthOfField::DrawDebug()
|
|
{
|
|
if(crp_dof_overlay->integer == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SCOPED_RENDER_PASS("DOF Debug", 0.125f, 0.125f, 0.25f);
|
|
|
|
crp.SwapRenderTargets();
|
|
|
|
CmdBeginBarrier();
|
|
CmdTextureBarrier(crp.GetReadRenderTarget(), ResourceStates::PixelShaderAccessBit);
|
|
CmdTextureBarrier(crp.depthTexture, ResourceStates::PixelShaderAccessBit);
|
|
CmdTextureBarrier(crp.GetWriteRenderTarget(), ResourceStates::RenderTargetBit);
|
|
CmdEndBarrier();
|
|
|
|
DOFDebugRC rc = {};
|
|
rc.colorTextureIndex = GetTextureIndexSRV(crp.GetReadRenderTarget());
|
|
rc.depthTextureIndex = GetTextureIndexSRV(crp.depthTexture);
|
|
rc.debugMode = crp_dof_overlay->integer;
|
|
RB_LinearDepthConstants(&rc.linearDepthA, &rc.linearDepthB);
|
|
rc.focusNearMin = crp_gatherDof_focusNearDist->value - 0.5f * crp_gatherDof_focusNearRange->value;
|
|
rc.focusNearMax = crp_gatherDof_focusNearDist->value + 0.5f * crp_gatherDof_focusNearRange->value;
|
|
rc.focusFarMin = crp_gatherDof_focusFarDist->value - 0.5f * crp_gatherDof_focusFarRange->value;
|
|
rc.focusFarMax = crp_gatherDof_focusFarDist->value + 0.5f * crp_gatherDof_focusFarRange->value;
|
|
rc.focusDist = 0.5f * (rc.focusNearMax + rc.focusFarMin);
|
|
|
|
CmdBindRenderTargets(1, &crp.renderTarget, NULL);
|
|
CmdBindPipeline(debugPipeline);
|
|
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
|
|
CmdDraw(3, 0);
|
|
}
|
|
|
|
void GatherDepthOfField::DrawSplit()
|
|
{
|
|
SCOPED_RENDER_PASS("DOF Split", 0.125f, 0.125f, 0.25f);
|
|
|
|
CmdBeginBarrier();
|
|
CmdTextureBarrier(crp.depthTexture, ResourceStates::ComputeShaderAccessBit);
|
|
CmdTextureBarrier(crp.renderTarget, ResourceStates::ComputeShaderAccessBit);
|
|
CmdTextureBarrier(nearColorTexture, ResourceStates::UnorderedAccessBit);
|
|
CmdTextureBarrier(farColorTexture, ResourceStates::UnorderedAccessBit);
|
|
CmdTextureBarrier(nearCocTexture, ResourceStates::UnorderedAccessBit);
|
|
CmdTextureBarrier(farCocTexture, ResourceStates::UnorderedAccessBit);
|
|
CmdEndBarrier();
|
|
|
|
DOFSplitRC rc = {};
|
|
rc.depthTextureIndex = GetTextureIndexSRV(crp.depthTexture);
|
|
rc.colorTextureIndex = GetTextureIndexSRV(crp.renderTarget);
|
|
rc.nearColorTextureIndex = GetTextureIndexUAV(nearColorTexture, 0);
|
|
rc.farColorTextureIndex = GetTextureIndexUAV(farColorTexture, 0);
|
|
rc.nearCocTextureIndex = GetTextureIndexUAV(nearCocTexture, 0);
|
|
rc.farCocTextureIndex = GetTextureIndexUAV(farCocTexture, 0);
|
|
RB_LinearDepthConstants(&rc.linearDepthA, &rc.linearDepthB);
|
|
rc.focusNearMin = crp_gatherDof_focusNearDist->value - 0.5f * crp_gatherDof_focusNearRange->value;
|
|
rc.focusNearMax = crp_gatherDof_focusNearDist->value + 0.5f * crp_gatherDof_focusNearRange->value;
|
|
rc.focusFarMin = crp_gatherDof_focusFarDist->value - 0.5f * crp_gatherDof_focusFarRange->value;
|
|
rc.focusFarMax = crp_gatherDof_focusFarDist->value + 0.5f * crp_gatherDof_focusFarRange->value;
|
|
rc.brightnessScale = crp_gatherDof_brightness->value;
|
|
|
|
CmdBindPipeline(splitPipeline);
|
|
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
|
|
CmdDispatch((glConfig.vidWidth + 7) / 8, (glConfig.vidHeight + 7) / 8, 1);
|
|
}
|
|
|
|
void GatherDepthOfField::DrawNearCocTileGen()
|
|
{
|
|
SCOPED_RENDER_PASS("DOF Tile Gen", 0.125f, 0.125f, 0.25f);
|
|
|
|
CmdBeginBarrier();
|
|
CmdTextureBarrier(nearCocTexture, ResourceStates::ComputeShaderAccessBit);
|
|
CmdTextureBarrier(nearCocTileTexture, ResourceStates::UnorderedAccessBit);
|
|
CmdEndBarrier();
|
|
|
|
DOFNearCocTileGenRC rc = {};
|
|
rc.inputTextureIndex = GetTextureIndexSRV(nearCocTexture);
|
|
rc.outputTextureIndex = GetTextureIndexUAV(nearCocTileTexture, 0);
|
|
|
|
CmdBindPipeline(nearCocTileGenPipeline);
|
|
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
|
|
CmdDispatch((tileWidth + 7) / 8, (tileHeight + 7) / 8, 1);
|
|
}
|
|
|
|
void GatherDepthOfField::DrawNearCocTileMax()
|
|
{
|
|
SCOPED_RENDER_PASS("DOF Tile Max", 0.125f, 0.125f, 0.25f);
|
|
|
|
CmdBeginBarrier();
|
|
CmdTextureBarrier(nearCocTileTexture, ResourceStates::ComputeShaderAccessBit);
|
|
CmdTextureBarrier(nearCocTileTexture2, ResourceStates::UnorderedAccessBit);
|
|
CmdEndBarrier();
|
|
|
|
DOFNearCocTileMaxRC rc = {};
|
|
rc.inputTextureIndex = GetTextureIndexSRV(nearCocTileTexture);
|
|
rc.outputTextureIndex = GetTextureIndexUAV(nearCocTileTexture2, 0);
|
|
rc.samplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Point);
|
|
|
|
CmdBindPipeline(nearCocTileMaxPipeline);
|
|
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
|
|
CmdDispatch((tileWidth + 7) / 8, (tileHeight + 7) / 8, 1);
|
|
}
|
|
|
|
void GatherDepthOfField::DrawBlur()
|
|
{
|
|
SCOPED_RENDER_PASS("DOF Blur", 0.125f, 0.125f, 0.25f);
|
|
|
|
CmdBeginBarrier();
|
|
CmdTextureBarrier(crp.renderTarget, ResourceStates::ComputeShaderAccessBit);
|
|
CmdTextureBarrier(nearColorTexture, ResourceStates::ComputeShaderAccessBit);
|
|
CmdTextureBarrier(farColorTexture, ResourceStates::ComputeShaderAccessBit);
|
|
CmdTextureBarrier(nearCocTexture, ResourceStates::ComputeShaderAccessBit);
|
|
CmdTextureBarrier(nearCocTileTexture2, ResourceStates::ComputeShaderAccessBit);
|
|
CmdTextureBarrier(farCocTexture, ResourceStates::ComputeShaderAccessBit);
|
|
CmdTextureBarrier(nearBlurTexture, ResourceStates::UnorderedAccessBit);
|
|
CmdTextureBarrier(farBlurTexture, ResourceStates::UnorderedAccessBit);
|
|
CmdEndBarrier();
|
|
|
|
DOFBlurRC rc = {};
|
|
rc.colorTextureIndex = GetTextureIndexSRV(crp.renderTarget);
|
|
rc.nearColorTextureIndex = GetTextureIndexSRV(nearColorTexture);
|
|
rc.nearMaxCocTextureIndex = GetTextureIndexSRV(nearCocTileTexture2);
|
|
rc.nearCocTextureIndex = GetTextureIndexSRV(nearCocTexture);
|
|
rc.nearOutputTextureIndex = GetTextureIndexUAV(nearBlurTexture, 0);
|
|
rc.farColorTextureIndex = GetTextureIndexSRV(farColorTexture);
|
|
rc.farCocTextureIndex = GetTextureIndexSRV(farCocTexture);
|
|
rc.farOutputTextureIndex = GetTextureIndexUAV(farBlurTexture, 0);
|
|
rc.samplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Linear);
|
|
rc.brightnessScale = crp_gatherDof_brightness->value;
|
|
rc.bladeCount = crp_dof_blades->value;
|
|
rc.bokehAngleRad = DEG2RAD(crp_dof_angle->value);
|
|
|
|
CmdBindPipeline(blurPipeline);
|
|
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
|
|
CmdDispatch((glConfig.vidWidth + 7) / 8, (glConfig.vidHeight + 7) / 8, 1);
|
|
}
|
|
|
|
void GatherDepthOfField::DrawFill()
|
|
{
|
|
SCOPED_RENDER_PASS("DOF Fill", 0.125f, 0.125f, 0.25f);
|
|
|
|
CmdBeginBarrier();
|
|
CmdTextureBarrier(nearBlurTexture, ResourceStates::ComputeShaderAccessBit);
|
|
CmdTextureBarrier(farBlurTexture, ResourceStates::ComputeShaderAccessBit);
|
|
CmdTextureBarrier(nearColorTexture, ResourceStates::UnorderedAccessBit);
|
|
CmdTextureBarrier(farColorTexture, ResourceStates::UnorderedAccessBit);
|
|
CmdEndBarrier();
|
|
|
|
DOFFillRC rc = {};
|
|
rc.nearInputTextureIndex = GetTextureIndexSRV(nearBlurTexture);
|
|
rc.farInputTextureIndex = GetTextureIndexSRV(farBlurTexture);
|
|
rc.nearOutputTextureIndex = GetTextureIndexUAV(nearColorTexture, 0);
|
|
rc.farOutputTextureIndex = GetTextureIndexUAV(farColorTexture, 0);
|
|
rc.samplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Point);
|
|
|
|
CmdBindPipeline(fillPipeline);
|
|
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
|
|
CmdDispatch((glConfig.vidWidth + 7) / 8, (glConfig.vidHeight + 7) / 8, 1);
|
|
}
|
|
|
|
void GatherDepthOfField::DrawCombine()
|
|
{
|
|
SCOPED_RENDER_PASS("DOF Combine", 0.125f, 0.125f, 0.25f);
|
|
|
|
CmdBeginBarrier();
|
|
CmdTextureBarrier(nearColorTexture, ResourceStates::PixelShaderAccessBit);
|
|
CmdTextureBarrier(farColorTexture, ResourceStates::PixelShaderAccessBit);
|
|
CmdTextureBarrier(nearCocTexture, ResourceStates::PixelShaderAccessBit);
|
|
CmdTextureBarrier(farCocTexture, ResourceStates::PixelShaderAccessBit);
|
|
CmdTextureBarrier(crp.GetReadRenderTarget(), ResourceStates::PixelShaderAccessBit);
|
|
CmdTextureBarrier(crp.GetWriteRenderTarget(), ResourceStates::RenderTargetBit);
|
|
CmdEndBarrier();
|
|
|
|
DOFCombineRC rc = {};
|
|
rc.nearTextureIndex = GetTextureIndexSRV(nearColorTexture);
|
|
rc.farTextureIndex = GetTextureIndexSRV(farColorTexture);
|
|
rc.nearCocTextureIndex = GetTextureIndexSRV(nearCocTexture);
|
|
rc.farCocTextureIndex = GetTextureIndexSRV(farCocTexture);
|
|
rc.sharpTextureIndex = GetTextureIndexSRV(crp.renderTarget);
|
|
rc.samplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Point);
|
|
|
|
CmdBindRenderTargets(1, &crp.renderTarget, NULL);
|
|
CmdBindPipeline(combinePipeline);
|
|
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
|
|
CmdDraw(3, 0);
|
|
}
|