/* =========================================================================== 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 . =========================================================================== */ // Cinematic Rendering Pipeline - tone mapping #include "crp_local.h" #include "compshaders/crp/fullscreen.h" #include "compshaders/crp/tone_map.h" #include "compshaders/crp/tone_map_inverse.h" #pragma pack(push, 4) struct ToneMapRC { uint32_t textureIndex; uint32_t samplerIndex; float invGamma; float brightness; float greyscale; }; struct InverseToneMapRC { uint32_t textureIndex; uint32_t samplerIndex; float gamma; float invBrightness; }; #pragma pack(pop) void ToneMap::Init() { { GraphicsPipelineDesc desc("Tone Map"); desc.shortLifeTime = true; desc.vertexShader = ShaderByteCode(g_fullscreen_vs); desc.pixelShader = ShaderByteCode(g_tone_map_ps); desc.depthStencil.DisableDepth(); desc.rasterizer.cullMode = CT_TWO_SIDED; desc.AddRenderTarget(0, crp.renderTargetFormat); pipeline = CreateGraphicsPipeline(desc); } { GraphicsPipelineDesc desc("Inverse Tone Map"); desc.shortLifeTime = true; desc.vertexShader = ShaderByteCode(g_fullscreen_vs); desc.pixelShader = ShaderByteCode(g_tone_map_inverse_ps); desc.depthStencil.DisableDepth(); desc.rasterizer.cullMode = CT_TWO_SIDED; desc.AddRenderTarget(0, crp.renderTargetFormat); pipeline = CreateGraphicsPipeline(desc); } } void ToneMap::DrawToneMap() { srp.renderMode = RenderMode::None; SCOPED_RENDER_PASS("Tone Map", 1.0f, 1.0f, 1.0f); CmdSetViewportAndScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight); crp.SwapRenderTargets(); CmdBeginBarrier(); CmdTextureBarrier(crp.GetReadRenderTarget(), ResourceStates::PixelShaderAccessBit); CmdTextureBarrier(crp.GetWriteRenderTarget(), ResourceStates::RenderTargetBit); CmdEndBarrier(); ToneMapRC rc = {}; rc.textureIndex = GetTextureIndexSRV(crp.GetReadRenderTarget()); rc.samplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Linear); rc.invGamma = 1.0f / r_gamma->value; rc.brightness = r_brightness->value; rc.greyscale = r_greyscale->value; CmdBindRenderTargets(1, &crp.renderTarget, NULL); CmdBindPipeline(pipeline); CmdSetGraphicsRootConstants(0, sizeof(rc), &rc); CmdDraw(3, 0); } void ToneMap::DrawInverseToneMap() { srp.renderMode = RenderMode::None; SCOPED_RENDER_PASS("Inverse Tone Map", 1.0f, 1.0f, 1.0f); CmdSetViewportAndScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight); crp.SwapRenderTargets(); CmdBeginBarrier(); CmdTextureBarrier(crp.GetReadRenderTarget(), ResourceStates::PixelShaderAccessBit); CmdTextureBarrier(crp.GetWriteRenderTarget(), ResourceStates::RenderTargetBit); CmdEndBarrier(); InverseToneMapRC rc = {}; rc.textureIndex = GetTextureIndexSRV(crp.GetReadRenderTarget()); rc.samplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Linear); rc.gamma = r_gamma->value; rc.invBrightness = 1.0f / r_brightness->value; CmdBindRenderTargets(1, &crp.renderTarget, NULL); CmdBindPipeline(inversePipeline); CmdSetGraphicsRootConstants(0, sizeof(rc), &rc); CmdDraw(3, 0); }