cnq3/code/renderer/crp_gbuffer_viz.cpp

203 lines
6.2 KiB
C++
Raw Normal View History

/*
===========================================================================
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 - G-Buffer texture visualization
#include "crp_local.h"
#include "../client/cl_imgui.h"
#include "compshaders/crp/fullscreen.h"
#include "compshaders/crp/gbufferviz_depth.h"
#include "compshaders/crp/gbufferviz_normal.h"
#include "compshaders/crp/gbufferviz_position.h"
#pragma pack(push, 4)
struct LinearizeDepthRC
{
uint32_t depthTextureIndex;
float linearDepthA;
float linearDepthB;
float zFarInv;
};
struct DecodeNormalsRC
{
uint32_t normalTextureIndex;
};
struct DecodePositionRC
{
uint32_t textureIndex;
uint32_t coloredDelta;
};
#pragma pack(pop)
void GBufferViz::Init()
{
{
GraphicsPipelineDesc desc("G-Buffer Depth");
desc.shortLifeTime = true;
desc.vertexShader = ShaderByteCode(g_fullscreen_vs);
desc.pixelShader = ShaderByteCode(g_gbufferviz_depth_ps);
desc.depthStencil.DisableDepth();
desc.rasterizer.cullMode = CT_TWO_SIDED;
desc.AddRenderTarget(0, crp.renderTargetFormat);
linearizeDepthPipeline = CreateGraphicsPipeline(desc);
}
{
GraphicsPipelineDesc desc("G-Buffer Normal");
desc.shortLifeTime = true;
desc.vertexShader = ShaderByteCode(g_fullscreen_vs);
desc.pixelShader = ShaderByteCode(g_gbufferviz_normal_ps);
desc.depthStencil.DisableDepth();
desc.rasterizer.cullMode = CT_TWO_SIDED;
desc.AddRenderTarget(0, crp.renderTargetFormat);
decodeNormalsPipeline = CreateGraphicsPipeline(desc);
}
{
GraphicsPipelineDesc desc("G-Buffer Position");
desc.shortLifeTime = true;
desc.vertexShader = ShaderByteCode(g_fullscreen_vs);
desc.pixelShader = ShaderByteCode(g_gbufferviz_position_ps);
desc.depthStencil.DisableDepth();
desc.rasterizer.cullMode = CT_TWO_SIDED;
desc.AddRenderTarget(0, crp.renderTargetFormat);
decodeShadingPositionPipeline = CreateGraphicsPipeline(desc);
}
}
void GBufferViz::DrawGUI()
{
GUI_AddMainMenuItem(GUI_MainMenu::Tools, "Show G-Buffer", "", &windowActive);
if(!windowActive)
{
return;
}
const HTexture renderTarget = crp.GetReadRenderTarget();
if(textureIndex == GBufferTexture::Depth)
{
srp.renderMode = RenderMode::None;
SCOPED_RENDER_PASS("Debug Depth", 1.0f, 1.0f, 1.0f);
CmdSetViewportAndScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);
CmdBeginBarrier();
CmdTextureBarrier(crp.depthTexture, ResourceStates::PixelShaderAccessBit);
CmdTextureBarrier(renderTarget, ResourceStates::RenderTargetBit);
CmdEndBarrier();
LinearizeDepthRC rc = {};
rc.depthTextureIndex = GetTextureIndexSRV(crp.depthTexture);
RB_LinearDepthConstants(&rc.linearDepthA, &rc.linearDepthB);
rc.zFarInv = 1.0f / backEnd.viewParms.zFar;
CmdBindRenderTargets(1, &renderTarget, NULL);
CmdBindPipeline(linearizeDepthPipeline);
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
CmdDraw(3, 0);
}
else if(textureIndex == GBufferTexture::Normal)
{
srp.renderMode = RenderMode::None;
SCOPED_RENDER_PASS("Debug Normal", 1.0f, 1.0f, 1.0f);
CmdSetViewportAndScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);
CmdBeginBarrier();
CmdTextureBarrier(crp.normalTexture, ResourceStates::PixelShaderAccessBit);
CmdTextureBarrier(renderTarget, ResourceStates::RenderTargetBit);
CmdEndBarrier();
DecodeNormalsRC rc = {};
rc.normalTextureIndex = GetTextureIndexSRV(crp.normalTexture);
CmdBindRenderTargets(1, &renderTarget, NULL);
CmdBindPipeline(decodeNormalsPipeline);
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
CmdDraw(3, 0);
}
else if(textureIndex == GBufferTexture::ShadingPositionDelta)
{
srp.renderMode = RenderMode::None;
SCOPED_RENDER_PASS("Debug Position", 1.0f, 1.0f, 1.0f);
CmdSetViewportAndScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);
CmdBeginBarrier();
CmdTextureBarrier(crp.shadingPositionTexture, ResourceStates::PixelShaderAccessBit);
CmdTextureBarrier(renderTarget, ResourceStates::RenderTargetBit);
CmdEndBarrier();
DecodePositionRC rc = {};
rc.textureIndex = GetTextureIndexSRV(crp.shadingPositionTexture);
rc.coloredDelta = coloredPositionDelta ? 1 : 0;
CmdBindRenderTargets(1, &renderTarget, NULL);
CmdBindPipeline(decodeShadingPositionPipeline);
CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
CmdDraw(3, 0);
}
if(ImGui::Begin("G-Buffer", &windowActive, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::RadioButton("Depth", &textureIndex, GBufferTexture::Depth);
ImGui::SameLine();
ImGui::RadioButton("Normal", &textureIndex, GBufferTexture::Normal);
ImGui::SameLine();
ImGui::RadioButton("Light", &textureIndex, GBufferTexture::Light);
ImGui::SameLine();
ImGui::RadioButton("Shading Position Delta", &textureIndex, GBufferTexture::ShadingPositionDelta);
if(textureIndex == GBufferTexture::ShadingPositionDelta)
{
ImGui::SameLine();
ImGui::Checkbox("Per-axis delta", &coloredPositionDelta);
}
const ImVec2 resolution = ImVec2(glConfig.vidWidth / 2, glConfig.vidHeight / 2);
HTexture texture;
switch(textureIndex)
{
case GBufferTexture::Depth: texture = renderTarget; break;
case GBufferTexture::Normal: texture = renderTarget; break;
case GBufferTexture::Light: texture = crp.lightTexture; break;
case GBufferTexture::ShadingPositionDelta: texture = renderTarget; break;
default: Q_assert(!"Invalid G-Buffer texture index"); texture = crp.lightTexture; break;
}
ImGui::Image((ImTextureID)GetTextureIndexSRV(texture), resolution);
CmdBeginBarrier();
CmdTextureBarrier(texture, ResourceStates::PixelShaderAccessBit);
CmdEndBarrier();
}
ImGui::End();
}