mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-12-03 01:12:33 +00:00
210 lines
6.5 KiB
C++
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);
|
|
}
|