/* =========================================================================== 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 . =========================================================================== */ // Cinematic Rendering Pipeline - sunlight on opaque surfaces #include "crp_local.h" #include "compshaders/crp/fullscreen.h" #include "compshaders/crp/sun_visibility.h" #include "compshaders/crp/sun_blur.h" #pragma pack(push, 4) struct SunBlurRC { uint32_t visibilityTextureIndex; uint32_t penumbraTextureIndex; }; #pragma pack(pop) void Sunlight::Init() { if(!rhiInfo.hasInlineRaytracing) { return; } { GraphicsPipelineDesc desc("Sunlight Visibility"); MakeFullScreenPipeline(desc, ShaderByteCode(g_sun_visibility_ps)); desc.AddRenderTarget(0, TextureFormat::R8_UNorm); desc.AddRenderTarget(0, TextureFormat::R8_UNorm); visibilityPipeline = CreateGraphicsPipeline(desc); } { GraphicsPipelineDesc desc("Sunlight Blur"); MakeFullScreenPipeline(desc, ShaderByteCode(g_sun_blur_ps)); desc.AddRenderTarget(0, crp.renderTargetFormat); blurPipeline = CreateGraphicsPipeline(desc); } { TextureDesc desc("sunlight visibility", glConfig.vidWidth, glConfig.vidHeight); desc.shortLifeTime = true; desc.format = TextureFormat::R8_UNorm; desc.initialState = ResourceStates::RenderTargetBit; desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit; visibilityTexture = CreateTexture(desc); desc.name = "sunlight penumbra"; penumbraTexture = CreateTexture(desc); } } void Sunlight::Draw() { if(crp_sunlight->integer == 0 || (backEnd.refdef.rdflags & RDF_NOWORLDMODEL) != 0 || !crp.raytracing.CanRaytrace() || !IsViewportFullscreen(backEnd.viewParms)) { CmdBeginBarrier(); CmdTextureBarrier(crp.sunlightTexture, ResourceStates::RenderTargetBit); CmdEndBarrier(); CmdClearColorTarget(crp.sunlightTexture, colorBlack); return; } srp.renderMode = RenderMode::None; { SCOPED_RENDER_PASS("Sunlight Visibility", 1.0f, 1.0f, 1.0f); CmdSetViewportAndScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight); CmdBeginBarrier(); CmdTextureBarrier(crp.shadingPositionTexture, ResourceStates::PixelShaderAccessBit); CmdTextureBarrier(visibilityTexture, ResourceStates::RenderTargetBit); CmdTextureBarrier(penumbraTexture, ResourceStates::RenderTargetBit); CmdEndBarrier(); const HTexture renderTargets[] = { visibilityTexture, penumbraTexture }; CmdBindRenderTargets(ARRAY_LEN(renderTargets), renderTargets, NULL); CmdBindPipeline(visibilityPipeline); CmdDraw(3, 0); } { SCOPED_RENDER_PASS("Sunlight Blur", 1.0f, 1.0f, 1.0f); CmdSetViewportAndScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight); CmdBeginBarrier(); for(int c = 0; c < 4; c++) { CmdTextureBarrier(crp.volumetricLight.sunShadowTextures[c], ResourceStates::PixelShaderAccessBit); } CmdTextureBarrier(visibilityTexture, ResourceStates::PixelShaderAccessBit); CmdTextureBarrier(penumbraTexture, ResourceStates::PixelShaderAccessBit); CmdTextureBarrier(crp.shadingPositionTexture, ResourceStates::PixelShaderAccessBit); CmdTextureBarrier(crp.normalTexture, ResourceStates::PixelShaderAccessBit); CmdTextureBarrier(crp.sunlightTexture, ResourceStates::RenderTargetBit); CmdEndBarrier(); SunBlurRC rc = {}; rc.penumbraTextureIndex = GetTextureIndexSRV(penumbraTexture); rc.visibilityTextureIndex = GetTextureIndexSRV(visibilityTexture); CmdBindRenderTargets(1, &crp.sunlightTexture, NULL); CmdBindPipeline(blurPipeline); CmdSetGraphicsRootConstants(0, sizeof(rc), &rc); CmdDraw(3, 0); } } bool Sunlight::WantRTASUpdate(const trRefdef_t& scene) { return crp_sunlight->integer != 0; }