cnq3/code/renderer/crp_motion_blur.cpp

210 lines
6.5 KiB
C++

/*
===========================================================================
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 <https://www.gnu.org/licenses/>.
===========================================================================
*/
// Cinematic Rendering Pipeline - scatter-as-gather motion blur
#include "crp_local.h"
#include "compshaders/crp/fullscreen.h"
#include "compshaders/crp/mblur_pack.h"
#include "compshaders/crp/mblur_tile_gen.h"
#include "compshaders/crp/mblur_tile_max.h"
#include "compshaders/crp/mblur_blur.h"
#pragma pack(push, 4)
struct MBPackRC
{
float motionScale;
float maxRadiusPx;
};
struct MBTileGenRC
{
uint32_t inputTextureIndex;
uint32_t outputTextureIndex;
};
struct MBTileMaxRC
{
uint32_t inputTextureIndex;
uint32_t outputTextureIndex;
uint32_t samplerIndex; // point/clamp
};
struct MBBlurRC
{
uint32_t colorTextureIndex;
uint32_t tileTextureIndex;
uint32_t packedTextureIndex;
uint32_t blueNoiseTextureIndex;
uint32_t pointSamplerIndex; // clamp
uint32_t linearSamplerIndex; // clamp
};
#pragma pack(pop)
void MotionBlur::Init()
{
tileTextureWidth = (uint32_t)(glConfig.vidWidth + 15) / 16;
tileTextureHeight = (uint32_t)(glConfig.vidHeight + 15) / 16;
{
GraphicsPipelineDesc desc("MBlur velocity/depth packing");
MakeFullScreenPipeline(desc, ShaderByteCode(g_pack_ps));
desc.AddRenderTarget(0, TextureFormat::R32G32_UInt);
packPipeline = CreateGraphicsPipeline(desc);
}
tileGenPipeline = CreateComputePipeline("MBlur tile generation", ShaderByteCode(g_tile_gen_cs));
tileMaxPipeline = CreateComputePipeline("MBlur tile dilation", ShaderByteCode(g_tile_max_cs));
{
GraphicsPipelineDesc desc("MBlur reconstruction filter");
MakeFullScreenPipeline(desc, ShaderByteCode(g_blur_ps));
desc.AddRenderTarget(0, crp.renderTargetFormat);
blurPipeline = CreateGraphicsPipeline(desc);
}
{
TextureDesc desc("MBlur velocity tile #1", tileTextureWidth, tileTextureHeight);
desc.shortLifeTime = true;
desc.committedResource = true;
desc.initialState = ResourceStates::UnorderedAccessBit;
desc.allowedState = ResourceStates::UnorderedAccessBit | ResourceStates::ComputeShaderAccessBit | ResourceStates::PixelShaderAccessBit;
desc.format = TextureFormat::R16G16_Float;
tileTexture = CreateTexture(desc);
desc.name = "MBlur velocity tile #2";
tileTexture2 = CreateTexture(desc);
}
{
TextureDesc desc("MBlur packed velocity/depth", glConfig.vidWidth, glConfig.vidHeight);
desc.shortLifeTime = true;
desc.committedResource = true;
desc.initialState = ResourceStates::RenderTargetBit;
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::ComputeShaderAccessBit | ResourceStates::PixelShaderAccessBit;
desc.format = TextureFormat::R32G32_UInt;
packedTexture = CreateTexture(desc);
}
}
void MotionBlur::Draw()
{
if(crp_mblur->integer == 0 ||
(backEnd.refdef.rdflags & RDF_CNQ3_TELEPORTED) != 0 ||
!IsViewportFullscreen(backEnd.viewParms))
{
return;
}
SCOPED_RENDER_PASS("Motion Blur", 0.125f, 0.125f, 0.25f);
DrawPack();
DrawTileGen();
DrawTileMax();
DrawBlur();
}
void MotionBlur::DrawPack()
{
SCOPED_DEBUG_LABEL("MBlur Pack", 0.125f, 0.125f, 0.25f);
CmdBeginBarrier();
CmdTextureBarrier(crp.motionVectorMBTexture, ResourceStates::PixelShaderAccessBit);
CmdTextureBarrier(crp.depthTexture, ResourceStates::PixelShaderAccessBit);
CmdTextureBarrier(packedTexture, ResourceStates::RenderTargetBit);
CmdEndBarrier();
MBPackRC rc = {};
rc.motionScale = crp_mblur_exposure->value;
rc.maxRadiusPx = min(glConfig.vidHeight / 25.0f, 30.0f);
CmdBindRenderTargets(1, &packedTexture, NULL);
CmdBindPipeline(packPipeline);
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
CmdDraw(3, 0);
}
void MotionBlur::DrawTileGen()
{
SCOPED_DEBUG_LABEL("MBlur Tile Gen", 0.125f, 0.125f, 0.25f);
CmdBeginBarrier();
CmdTextureBarrier(packedTexture, ResourceStates::ComputeShaderAccessBit);
CmdTextureBarrier(tileTexture, ResourceStates::UnorderedAccessBit);
CmdEndBarrier();
MBTileGenRC rc = {};
rc.inputTextureIndex = GetTextureIndexSRV(packedTexture);
rc.outputTextureIndex = GetTextureIndexUAV(tileTexture, 0);
CmdBindPipeline(tileGenPipeline);
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
CmdDispatch((tileTextureWidth + 7) / 8, (tileTextureHeight + 7) / 8, 1);
}
void MotionBlur::DrawTileMax()
{
SCOPED_DEBUG_LABEL("MBlur Tile Max", 0.125f, 0.125f, 0.25f);
CmdBeginBarrier();
CmdTextureBarrier(tileTexture, ResourceStates::ComputeShaderAccessBit);
CmdTextureBarrier(tileTexture2, ResourceStates::UnorderedAccessBit);
CmdEndBarrier();
MBTileMaxRC rc = {};
rc.inputTextureIndex = GetTextureIndexSRV(tileTexture);
rc.outputTextureIndex = GetTextureIndexUAV(tileTexture2, 0);
rc.samplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Point);
CmdBindPipeline(tileMaxPipeline);
CmdSetComputeRootConstants(0, sizeof(rc), &rc);
CmdDispatch((tileTextureWidth + 7) / 8, (tileTextureHeight + 7) / 8, 1);
}
void MotionBlur::DrawBlur()
{
SCOPED_DEBUG_LABEL("MBlur Blur", 0.125f, 0.125f, 0.25f);
crp.SwapRenderTargets();
CmdBeginBarrier();
CmdTextureBarrier(crp.GetReadRenderTarget(), ResourceStates::PixelShaderAccessBit);
CmdTextureBarrier(tileTexture2, ResourceStates::PixelShaderAccessBit);
CmdTextureBarrier(packedTexture, ResourceStates::PixelShaderAccessBit);
CmdTextureBarrier(crp.renderTarget, ResourceStates::RenderTargetBit);
CmdEndBarrier();
MBBlurRC rc = {};
rc.colorTextureIndex = GetTextureIndexSRV(crp.GetReadRenderTarget());
rc.tileTextureIndex = GetTextureIndexSRV(tileTexture2);
rc.packedTextureIndex = GetTextureIndexSRV(packedTexture);
rc.blueNoiseTextureIndex = GetTextureIndexSRV(crp.blueNoise2D);
rc.pointSamplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Point);
rc.linearSamplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Linear);
CmdBindRenderTargets(1, &crp.renderTarget, NULL);
CmdBindPipeline(blurPipeline);
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
CmdDraw(3, 0);
}