mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-11-26 05:50:57 +00:00
added pre-pass w/ normals, unified clip plane generation
motion vectors to be done later
This commit is contained in:
parent
7fab6ea376
commit
0cae0a9545
23 changed files with 563 additions and 115 deletions
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Copyright (C) 2023 Gian 'myT' Schellenbaum
|
Copyright (C) 2023-2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
This file is part of Challenge Quake 3 (CNQ3).
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@ struct Tessellator
|
||||||
enum Id
|
enum Id
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
|
Prepass,
|
||||||
Opaque,
|
Opaque,
|
||||||
Transp,
|
Transp,
|
||||||
Count
|
Count
|
||||||
|
@ -90,6 +91,25 @@ struct PSOCache
|
||||||
uint32_t entryCount = 1; // we treat index 0 as invalid
|
uint32_t entryCount = 1; // we treat index 0 as invalid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Prepass
|
||||||
|
{
|
||||||
|
void Init();
|
||||||
|
void Draw(const drawSceneViewCommand_t& cmd);
|
||||||
|
void ProcessShader(shader_t& shader);
|
||||||
|
void TessellationOverflow();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void BeginBatch(const shader_t* shader);
|
||||||
|
void EndBatch();
|
||||||
|
|
||||||
|
PSOCache::Entry psoCacheEntries[128];
|
||||||
|
PSOCache psoCache;
|
||||||
|
|
||||||
|
float clipPlane[4];
|
||||||
|
bool batchOldDepthHack;
|
||||||
|
bool batchDepthHack;
|
||||||
|
};
|
||||||
|
|
||||||
struct WorldOpaque
|
struct WorldOpaque
|
||||||
{
|
{
|
||||||
void Init();
|
void Init();
|
||||||
|
@ -304,6 +324,8 @@ struct CRP : IRenderPipeline
|
||||||
float frameSeed;
|
float frameSeed;
|
||||||
HTexture readbackRenderTarget;
|
HTexture readbackRenderTarget;
|
||||||
HTexture depthTexture;
|
HTexture depthTexture;
|
||||||
|
HTexture normalTexture;
|
||||||
|
HTexture motionVectorTexture;
|
||||||
HTexture renderTarget;
|
HTexture renderTarget;
|
||||||
TextureFormat::Id renderTargetFormat;
|
TextureFormat::Id renderTargetFormat;
|
||||||
HTexture renderTargets[2];
|
HTexture renderTargets[2];
|
||||||
|
@ -328,6 +350,7 @@ struct CRP : IRenderPipeline
|
||||||
MipMapGenerator mipMapGen;
|
MipMapGenerator mipMapGen;
|
||||||
ImGUI imgui;
|
ImGUI imgui;
|
||||||
Nuklear nuklear;
|
Nuklear nuklear;
|
||||||
|
Prepass prepass;
|
||||||
WorldOpaque opaque;
|
WorldOpaque opaque;
|
||||||
WorldTransp transp;
|
WorldTransp transp;
|
||||||
TranspResolve transpResolve;
|
TranspResolve transpResolve;
|
||||||
|
|
|
@ -305,6 +305,28 @@ void CRP::Init()
|
||||||
depthTexture = RHI::CreateTexture(desc);
|
depthTexture = RHI::CreateTexture(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TextureDesc desc("GBuffer normals", glConfig.vidWidth, glConfig.vidHeight);
|
||||||
|
desc.committedResource = true;
|
||||||
|
desc.shortLifeTime = true;
|
||||||
|
desc.initialState = ResourceStates::RenderTargetBit;
|
||||||
|
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
|
||||||
|
desc.format = TextureFormat::RG32_SNorm;
|
||||||
|
desc.SetClearColor(vec4_zero);
|
||||||
|
normalTexture = RHI::CreateTexture(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TextureDesc desc("GBuffer motion vectors", glConfig.vidWidth, glConfig.vidHeight);
|
||||||
|
desc.committedResource = true;
|
||||||
|
desc.shortLifeTime = true;
|
||||||
|
desc.initialState = ResourceStates::RenderTargetBit;
|
||||||
|
desc.allowedState = ResourceStates::RenderTargetBit | ResourceStates::PixelShaderAccessBit | ResourceStates::ComputeShaderAccessBit;
|
||||||
|
desc.format = TextureFormat::RG32_Float;
|
||||||
|
desc.SetClearColor(vec4_zero);
|
||||||
|
motionVectorTexture = RHI::CreateTexture(desc);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
GraphicsPipelineDesc desc("blit LDR");
|
GraphicsPipelineDesc desc("blit LDR");
|
||||||
desc.vertexShader = ShaderByteCode(g_fullscreen_vs);
|
desc.vertexShader = ShaderByteCode(g_fullscreen_vs);
|
||||||
|
@ -322,6 +344,7 @@ void CRP::Init()
|
||||||
imgui.Init(true, ShaderByteCode(g_imgui_vs), ShaderByteCode(g_imgui_ps), renderTargetFormat, RHI_MAKE_NULL_HANDLE(), NULL);
|
imgui.Init(true, ShaderByteCode(g_imgui_vs), ShaderByteCode(g_imgui_ps), renderTargetFormat, RHI_MAKE_NULL_HANDLE(), NULL);
|
||||||
nuklear.Init(true, ShaderByteCode(g_nuklear_vs), ShaderByteCode(g_nuklear_ps), renderTargetFormat, RHI_MAKE_NULL_HANDLE(), NULL);
|
nuklear.Init(true, ShaderByteCode(g_nuklear_vs), ShaderByteCode(g_nuklear_ps), renderTargetFormat, RHI_MAKE_NULL_HANDLE(), NULL);
|
||||||
mipMapGen.Init(true, ShaderByteCode(g_mip_1_cs), ShaderByteCode(g_mip_2_cs), ShaderByteCode(g_mip_3_cs));
|
mipMapGen.Init(true, ShaderByteCode(g_mip_1_cs), ShaderByteCode(g_mip_2_cs), ShaderByteCode(g_mip_3_cs));
|
||||||
|
prepass.Init();
|
||||||
opaque.Init();
|
opaque.Init();
|
||||||
transp.Init();
|
transp.Init();
|
||||||
transpResolve.Init();
|
transpResolve.Init();
|
||||||
|
@ -464,6 +487,7 @@ void CRP::ProcessShader(shader_t& shader)
|
||||||
{
|
{
|
||||||
if(shader.isOpaque)
|
if(shader.isOpaque)
|
||||||
{
|
{
|
||||||
|
prepass.ProcessShader(shader);
|
||||||
opaque.ProcessShader(shader);
|
opaque.ProcessShader(shader);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -553,6 +577,7 @@ void CRP::TessellationOverflow()
|
||||||
{
|
{
|
||||||
switch(tess.tessellator)
|
switch(tess.tessellator)
|
||||||
{
|
{
|
||||||
|
case Tessellator::Prepass: prepass.TessellationOverflow(); break;
|
||||||
case Tessellator::Opaque: opaque.TessellationOverflow(); break;
|
case Tessellator::Opaque: opaque.TessellationOverflow(); break;
|
||||||
case Tessellator::Transp: transp.TessellationOverflow(); break;
|
case Tessellator::Transp: transp.TessellationOverflow(); break;
|
||||||
default: break;
|
default: break;
|
||||||
|
@ -598,6 +623,7 @@ void CRP::DrawSceneView(const drawSceneViewCommand_t& cmd)
|
||||||
CmdTextureBarrier(renderTarget, ResourceStates::RenderTargetBit);
|
CmdTextureBarrier(renderTarget, ResourceStates::RenderTargetBit);
|
||||||
CmdEndBarrier();
|
CmdEndBarrier();
|
||||||
CmdClearColorTarget(renderTarget, cmd.clearColor, &rect);
|
CmdClearColorTarget(renderTarget, cmd.clearColor, &rect);
|
||||||
|
prepass.Draw(newCmd);
|
||||||
opaque.Draw(newCmd);
|
opaque.Draw(newCmd);
|
||||||
fog.Draw();
|
fog.Draw();
|
||||||
transp.Draw(newCmd);
|
transp.Draw(newCmd);
|
||||||
|
@ -620,6 +646,7 @@ void CRP::DrawSceneView(const drawSceneViewCommand_t& cmd)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
prepass.Draw(cmd);
|
||||||
opaque.Draw(cmd);
|
opaque.Draw(cmd);
|
||||||
fog.Draw();
|
fog.Draw();
|
||||||
transp.Draw(cmd);
|
transp.Draw(cmd);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Copyright (C) 2023 Gian 'myT' Schellenbaum
|
Copyright (C) 2023-2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
This file is part of Challenge Quake 3 (CNQ3).
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
@ -65,47 +65,17 @@ void WorldOpaque::Draw(const drawSceneViewCommand_t& cmd)
|
||||||
|
|
||||||
backEnd.refdef = cmd.refdef;
|
backEnd.refdef = cmd.refdef;
|
||||||
backEnd.viewParms = cmd.viewParms;
|
backEnd.viewParms = cmd.viewParms;
|
||||||
|
RB_CreateClipPlane(clipPlane);
|
||||||
if(backEnd.viewParms.isPortal)
|
|
||||||
{
|
|
||||||
float plane[4];
|
|
||||||
plane[0] = backEnd.viewParms.portalPlane.normal[0];
|
|
||||||
plane[1] = backEnd.viewParms.portalPlane.normal[1];
|
|
||||||
plane[2] = backEnd.viewParms.portalPlane.normal[2];
|
|
||||||
plane[3] = backEnd.viewParms.portalPlane.dist;
|
|
||||||
|
|
||||||
float plane2[4];
|
|
||||||
plane2[0] = DotProduct(backEnd.viewParms.orient.axis[0], plane);
|
|
||||||
plane2[1] = DotProduct(backEnd.viewParms.orient.axis[1], plane);
|
|
||||||
plane2[2] = DotProduct(backEnd.viewParms.orient.axis[2], plane);
|
|
||||||
plane2[3] = DotProduct(plane, backEnd.viewParms.orient.origin) - plane[3];
|
|
||||||
|
|
||||||
float* o = plane;
|
|
||||||
const float* m = s_flipMatrix;
|
|
||||||
const float* v = plane2;
|
|
||||||
o[0] = m[0] * v[0] + m[4] * v[1] + m[8] * v[2] + m[12] * v[3];
|
|
||||||
o[1] = m[1] * v[0] + m[5] * v[1] + m[9] * v[2] + m[13] * v[3];
|
|
||||||
o[2] = m[2] * v[0] + m[6] * v[1] + m[10] * v[2] + m[14] * v[3];
|
|
||||||
o[3] = m[3] * v[0] + m[7] * v[1] + m[11] * v[2] + m[15] * v[3];
|
|
||||||
|
|
||||||
memcpy(clipPlane, plane, sizeof(clipPlane));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memset(clipPlane, 0, sizeof(clipPlane));
|
|
||||||
}
|
|
||||||
|
|
||||||
CmdSetViewportAndScissor(backEnd.viewParms);
|
CmdSetViewportAndScissor(backEnd.viewParms);
|
||||||
batchOldDepthHack = false;
|
batchOldDepthHack = false;
|
||||||
batchDepthHack = false;
|
batchDepthHack = false;
|
||||||
|
|
||||||
CmdBeginBarrier();
|
CmdBeginBarrier();
|
||||||
CmdTextureBarrier(crp.depthTexture, ResourceStates::DepthWriteBit);
|
CmdTextureBarrier(crp.depthTexture, ResourceStates::DepthReadBit);
|
||||||
CmdBufferBarrier(srp.traceRenderBuffer, ResourceStates::UnorderedAccessBit);
|
CmdBufferBarrier(srp.traceRenderBuffer, ResourceStates::UnorderedAccessBit);
|
||||||
CmdEndBarrier();
|
CmdEndBarrier();
|
||||||
|
|
||||||
CmdClearDepthStencilTarget(crp.depthTexture, true, 0.0f);
|
|
||||||
|
|
||||||
GeoBuffers& db = crp.dynBuffers[GetFrameIndex()];
|
GeoBuffers& db = crp.dynBuffers[GetFrameIndex()];
|
||||||
db.BeginUpload();
|
db.BeginUpload();
|
||||||
|
|
||||||
|
@ -207,16 +177,13 @@ void WorldOpaque::ProcessShader(shader_t& shader)
|
||||||
desc.vertexShader = g_opaque_vs;
|
desc.vertexShader = g_opaque_vs;
|
||||||
desc.pixelShader = g_opaque_ps;
|
desc.pixelShader = g_opaque_ps;
|
||||||
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Position, DataType::Float32, 3, 0);
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Position, DataType::Float32, 3, 0);
|
||||||
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Normal, DataType::Float32, 2, 0);
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Normal, DataType::Float32, 3, 0);
|
||||||
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::TexCoord, DataType::Float32, 2, 0);
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::TexCoord, DataType::Float32, 2, 0);
|
||||||
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Color, DataType::UNorm8, 4, 0);
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Color, DataType::UNorm8, 4, 0);
|
||||||
desc.depthStencil.depthStencilFormat = TextureFormat::Depth32_Float;
|
desc.depthStencil.depthStencilFormat = TextureFormat::Depth32_Float;
|
||||||
desc.depthStencil.depthComparison =
|
desc.depthStencil.depthComparison = shader.isSky ? ComparisonFunction::GreaterEqual : ComparisonFunction::Equal;
|
||||||
(stateBits & GLS_DEPTHFUNC_EQUAL) != 0 ?
|
desc.depthStencil.enableDepthTest = true;
|
||||||
ComparisonFunction::Equal :
|
desc.depthStencil.enableDepthWrites = false;
|
||||||
ComparisonFunction::GreaterEqual;
|
|
||||||
desc.depthStencil.enableDepthTest = (stateBits & GLS_DEPTHTEST_DISABLE) == 0;
|
|
||||||
desc.depthStencil.enableDepthWrites = (stateBits & GLS_DEPTHMASK_TRUE) != 0;
|
|
||||||
desc.rasterizer.cullMode = shader.cullType;
|
desc.rasterizer.cullMode = shader.cullType;
|
||||||
desc.rasterizer.polygonOffset = shader.polygonOffset != 0;
|
desc.rasterizer.polygonOffset = shader.polygonOffset != 0;
|
||||||
desc.rasterizer.clampDepth = clampDepth;
|
desc.rasterizer.clampDepth = clampDepth;
|
||||||
|
|
294
code/renderer/crp_prepass.cpp
Normal file
294
code/renderer/crp_prepass.cpp
Normal file
|
@ -0,0 +1,294 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
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 - full opaque pre-pass
|
||||||
|
|
||||||
|
|
||||||
|
#include "crp_local.h"
|
||||||
|
#include "compshaders/crp/prepass.h"
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
|
||||||
|
struct PrepassVertexRC
|
||||||
|
{
|
||||||
|
float modelViewMatrix[16];
|
||||||
|
float projectionMatrix[16];
|
||||||
|
float normalMatrix[16];
|
||||||
|
float clipPlane[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PrepassPixelRC
|
||||||
|
{
|
||||||
|
uint32_t textureIndex;
|
||||||
|
uint32_t samplerIndex;
|
||||||
|
uint32_t alphaTest;
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
||||||
|
void Prepass::Init()
|
||||||
|
{
|
||||||
|
psoCache.Init(psoCacheEntries, ARRAY_LEN(psoCacheEntries));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Prepass::Draw(const drawSceneViewCommand_t& cmd)
|
||||||
|
{
|
||||||
|
if(cmd.numDrawSurfs - cmd.numTranspSurfs <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
srp.renderMode = RenderMode::World;
|
||||||
|
|
||||||
|
backEnd.refdef = cmd.refdef;
|
||||||
|
backEnd.viewParms = cmd.viewParms;
|
||||||
|
RB_CreateClipPlane(clipPlane);
|
||||||
|
|
||||||
|
CmdSetViewportAndScissor(backEnd.viewParms);
|
||||||
|
batchOldDepthHack = false;
|
||||||
|
batchDepthHack = false;
|
||||||
|
|
||||||
|
CmdBeginBarrier();
|
||||||
|
CmdTextureBarrier(crp.depthTexture, ResourceStates::DepthWriteBit);
|
||||||
|
CmdTextureBarrier(crp.normalTexture, ResourceStates::RenderTargetBit);
|
||||||
|
CmdTextureBarrier(crp.motionVectorTexture, ResourceStates::RenderTargetBit);
|
||||||
|
CmdEndBarrier();
|
||||||
|
|
||||||
|
CmdClearDepthStencilTarget(crp.depthTexture, true, 0.0f);
|
||||||
|
CmdClearColorTarget(crp.normalTexture, vec4_zero, NULL);
|
||||||
|
CmdClearColorTarget(crp.motionVectorTexture, vec4_zero, NULL);
|
||||||
|
|
||||||
|
GeoBuffers& db = crp.dynBuffers[GetFrameIndex()];
|
||||||
|
db.BeginUpload();
|
||||||
|
|
||||||
|
SCOPED_RENDER_PASS("Pre-pass", 1.0f, 0.5f, 0.5f);
|
||||||
|
|
||||||
|
const HTexture renderTargets[] = { crp.normalTexture, crp.motionVectorTexture };
|
||||||
|
CmdBindRenderTargets(ARRAY_LEN(renderTargets), renderTargets, &crp.depthTexture);
|
||||||
|
CmdBindVertexBuffers(ARRAY_LEN(db.vertexBuffers), db.vertexBuffers, db.vertexBufferStrides, NULL);
|
||||||
|
CmdBindIndexBuffer(db.indexBuffer.buffer, IndexType::UInt32, 0);
|
||||||
|
|
||||||
|
const drawSurf_t* drawSurfs = cmd.drawSurfs;
|
||||||
|
const int surfCount = cmd.numDrawSurfs - cmd.numTranspSurfs;
|
||||||
|
const double originalTime = backEnd.refdef.floatTime;
|
||||||
|
|
||||||
|
const shader_t* shader = NULL;
|
||||||
|
const shader_t* oldShader = NULL;
|
||||||
|
int oldEntityNum = -1;
|
||||||
|
backEnd.currentEntity = &tr.worldEntity;
|
||||||
|
|
||||||
|
tess.numVertexes = 0;
|
||||||
|
tess.numIndexes = 0;
|
||||||
|
|
||||||
|
int ds;
|
||||||
|
const drawSurf_t* drawSurf;
|
||||||
|
for(ds = 0, drawSurf = drawSurfs; ds < surfCount; ++ds, ++drawSurf)
|
||||||
|
{
|
||||||
|
int entityNum;
|
||||||
|
R_DecomposeSort(drawSurf->sort, &entityNum, &shader);
|
||||||
|
Q_assert(shader != NULL);
|
||||||
|
Q_assert(shader->isOpaque);
|
||||||
|
|
||||||
|
if(shader->isSky || shader->numStages <= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool shaderChanged = shader != oldShader;
|
||||||
|
const bool entityChanged = entityNum != oldEntityNum;
|
||||||
|
if(shaderChanged || entityChanged)
|
||||||
|
{
|
||||||
|
oldShader = shader;
|
||||||
|
oldEntityNum = entityNum;
|
||||||
|
EndBatch();
|
||||||
|
BeginBatch(shader);
|
||||||
|
tess.greyscale = drawSurf->greyscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(entityChanged)
|
||||||
|
{
|
||||||
|
UpdateEntityData(batchDepthHack, entityNum, originalTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
R_TessellateSurface(drawSurf->surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
backEnd.refdef.floatTime = originalTime;
|
||||||
|
|
||||||
|
EndBatch();
|
||||||
|
|
||||||
|
db.EndUpload();
|
||||||
|
|
||||||
|
// restores the potentially "hacked" depth range as well
|
||||||
|
CmdSetViewportAndScissor(backEnd.viewParms);
|
||||||
|
batchOldDepthHack = false;
|
||||||
|
batchDepthHack = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Prepass::ProcessShader(shader_t& shader)
|
||||||
|
{
|
||||||
|
if(shader.isSky)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_assert(shader.isOpaque);
|
||||||
|
|
||||||
|
if(shader.numStages < 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool clampDepth = r_depthClamp->integer != 0 || shader.isSky;
|
||||||
|
|
||||||
|
const shaderStage_t& stage = *shader.stages[0];
|
||||||
|
const unsigned int stateBits = stage.stateBits & (~GLS_POLYMODE_LINE);
|
||||||
|
int a = 0;
|
||||||
|
|
||||||
|
Q_assert((stateBits & GLS_DEPTHTEST_DISABLE) == 0); // depth test enabled
|
||||||
|
Q_assert((stateBits & GLS_DEPTHMASK_TRUE) != 0); // depth write enabled
|
||||||
|
Q_assert((stateBits & GLS_DEPTHFUNC_EQUAL) == 0); // depth comparison GE
|
||||||
|
|
||||||
|
// @NOTE: we are not using any CTOR because we deliberately want to 0-init the struct
|
||||||
|
// this is necessary for padding bytes not to mess up comparisons in the PSO cache
|
||||||
|
GraphicsPipelineDesc desc = {};
|
||||||
|
desc.name = "pre-pass";
|
||||||
|
desc.rootSignature = RHI_MAKE_NULL_HANDLE();
|
||||||
|
desc.shortLifeTime = true; // the PSO cache is only valid for this map!
|
||||||
|
desc.vertexShader = g_prepass_vs;
|
||||||
|
desc.pixelShader = g_prepass_ps;
|
||||||
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Position, DataType::Float32, 3, 0);
|
||||||
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Normal, DataType::Float32, 3, 0);
|
||||||
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::TexCoord, DataType::Float32, 2, 0);
|
||||||
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Color, DataType::UNorm8, 4, 0);
|
||||||
|
desc.depthStencil.depthStencilFormat = TextureFormat::Depth32_Float;
|
||||||
|
desc.depthStencil.depthComparison = ComparisonFunction::GreaterEqual;
|
||||||
|
desc.depthStencil.enableDepthTest = true;
|
||||||
|
desc.depthStencil.enableDepthWrites = true;
|
||||||
|
desc.rasterizer.cullMode = shader.cullType;
|
||||||
|
desc.rasterizer.polygonOffset = shader.polygonOffset != 0;
|
||||||
|
desc.rasterizer.clampDepth = clampDepth;
|
||||||
|
desc.AddRenderTarget(0, TextureFormat::RG32_SNorm);
|
||||||
|
desc.AddRenderTarget(0, TextureFormat::RG32_Float);
|
||||||
|
|
||||||
|
pipeline_t& p = shader.prepassPipeline;
|
||||||
|
p.firstStage = 0;
|
||||||
|
p.numStages = 1;
|
||||||
|
p.pipeline = psoCache.AddPipeline(desc, va("pre-pass %d", psoCache.entryCount));
|
||||||
|
desc.rasterizer.cullMode = GetMirrorredCullType(desc.rasterizer.cullMode);
|
||||||
|
p.mirrorPipeline = psoCache.AddPipeline(desc, va("pre-pass %d mirrored", psoCache.entryCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Prepass::TessellationOverflow()
|
||||||
|
{
|
||||||
|
EndBatch();
|
||||||
|
BeginBatch(tess.shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Prepass::BeginBatch(const shader_t* shader)
|
||||||
|
{
|
||||||
|
tess.tessellator = Tessellator::Prepass;
|
||||||
|
tess.numVertexes = 0;
|
||||||
|
tess.numIndexes = 0;
|
||||||
|
tess.depthFade = DFT_NONE;
|
||||||
|
tess.deformsPreApplied = qfalse;
|
||||||
|
tess.xstages = (const shaderStage_t**)shader->stages;
|
||||||
|
tess.shader = shader;
|
||||||
|
tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
|
||||||
|
if(tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime)
|
||||||
|
{
|
||||||
|
tess.shaderTime = tess.shader->clampTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Prepass::EndBatch()
|
||||||
|
{
|
||||||
|
PrepassVertexRC vertexRC = {};
|
||||||
|
PrepassPixelRC pixelRC = {};
|
||||||
|
float tempMatrix[16];
|
||||||
|
|
||||||
|
const int vertexCount = tess.numVertexes;
|
||||||
|
const int indexCount = tess.numIndexes;
|
||||||
|
if(vertexCount <= 0 ||
|
||||||
|
indexCount <= 0 ||
|
||||||
|
tess.shader->numStages <= 0)
|
||||||
|
{
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shader_t* const shader = tess.shader;
|
||||||
|
|
||||||
|
GeoBuffers& db = crp.dynBuffers[GetFrameIndex()];
|
||||||
|
if(!db.CanAdd(vertexCount, indexCount, shader->numStages))
|
||||||
|
{
|
||||||
|
Q_assert(!"World surface geometry buffer too small!");
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_DeformTessGeometry(0, vertexCount, 0, indexCount);
|
||||||
|
db.UploadBase();
|
||||||
|
|
||||||
|
if(batchDepthHack != batchOldDepthHack)
|
||||||
|
{
|
||||||
|
const viewParms_t& vp = backEnd.viewParms;
|
||||||
|
CmdSetViewport(vp.viewportX, vp.viewportY, vp.viewportWidth, vp.viewportHeight, batchDepthHack ? 0.7f : 0.0f, 1.0f);
|
||||||
|
batchOldDepthHack = batchDepthHack;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(vertexRC.modelViewMatrix, backEnd.orient.modelMatrix, sizeof(vertexRC.modelViewMatrix));
|
||||||
|
memcpy(vertexRC.projectionMatrix, backEnd.viewParms.projectionMatrix, sizeof(vertexRC.projectionMatrix));
|
||||||
|
memcpy(vertexRC.clipPlane, clipPlane, sizeof(vertexRC.clipPlane));
|
||||||
|
R_InvMatrix(backEnd.modelMatrix, tempMatrix);
|
||||||
|
R_TransposeMatrix(tempMatrix, vertexRC.normalMatrix);
|
||||||
|
CmdSetGraphicsRootConstants(0, sizeof(vertexRC), &vertexRC);
|
||||||
|
|
||||||
|
const shaderStage_t* const stage = shader->stages[0];
|
||||||
|
|
||||||
|
R_ComputeColors(stage, tess.svars[0], 0, vertexCount);
|
||||||
|
R_ComputeTexCoords(stage, tess.svars[0], 0, vertexCount, qfalse);
|
||||||
|
db.UploadStage(0);
|
||||||
|
|
||||||
|
const pipeline_t& pipeline = shader->prepassPipeline;
|
||||||
|
const int psoIndex = backEnd.viewParms.isMirror ? pipeline.mirrorPipeline : pipeline.pipeline;
|
||||||
|
Q_assert(psoIndex > 0);
|
||||||
|
CmdBindPipeline(psoCache.entries[psoIndex].handle);
|
||||||
|
|
||||||
|
const image_t* image = GetBundleImage(stage->bundle);
|
||||||
|
const uint32_t texIdx = image->textureIndex;
|
||||||
|
const uint32_t sampIdx = GetSamplerIndex(image);
|
||||||
|
const uint32_t alphaTest = AlphaTestShaderConstFromStateBits(stage->stateBits);
|
||||||
|
Q_assert(sampIdx < ARRAY_LEN(crp.samplers));
|
||||||
|
|
||||||
|
pixelRC.textureIndex = texIdx;
|
||||||
|
pixelRC.samplerIndex = sampIdx;
|
||||||
|
pixelRC.alphaTest = alphaTest;
|
||||||
|
CmdSetGraphicsRootConstants(sizeof(vertexRC), sizeof(pixelRC), &pixelRC);
|
||||||
|
|
||||||
|
db.DrawStage(vertexCount, indexCount);
|
||||||
|
|
||||||
|
db.EndBaseBatch(vertexCount);
|
||||||
|
|
||||||
|
clean_up:
|
||||||
|
tess.tessellator = Tessellator::None;
|
||||||
|
tess.numVertexes = 0;
|
||||||
|
tess.numIndexes = 0;
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Copyright (C) 2023 Gian 'myT' Schellenbaum
|
Copyright (C) 2023-2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
This file is part of Challenge Quake 3 (CNQ3).
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Copyright (C) 2023 Gian 'myT' Schellenbaum
|
Copyright (C) 2023-2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
This file is part of Challenge Quake 3 (CNQ3).
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
@ -83,35 +83,7 @@ void WorldTransp::Draw(const drawSceneViewCommand_t& cmd)
|
||||||
|
|
||||||
backEnd.refdef = cmd.refdef;
|
backEnd.refdef = cmd.refdef;
|
||||||
backEnd.viewParms = cmd.viewParms;
|
backEnd.viewParms = cmd.viewParms;
|
||||||
|
RB_CreateClipPlane(clipPlane);
|
||||||
if(backEnd.viewParms.isPortal)
|
|
||||||
{
|
|
||||||
float plane[4];
|
|
||||||
plane[0] = backEnd.viewParms.portalPlane.normal[0];
|
|
||||||
plane[1] = backEnd.viewParms.portalPlane.normal[1];
|
|
||||||
plane[2] = backEnd.viewParms.portalPlane.normal[2];
|
|
||||||
plane[3] = backEnd.viewParms.portalPlane.dist;
|
|
||||||
|
|
||||||
float plane2[4];
|
|
||||||
plane2[0] = DotProduct(backEnd.viewParms.orient.axis[0], plane);
|
|
||||||
plane2[1] = DotProduct(backEnd.viewParms.orient.axis[1], plane);
|
|
||||||
plane2[2] = DotProduct(backEnd.viewParms.orient.axis[2], plane);
|
|
||||||
plane2[3] = DotProduct(plane, backEnd.viewParms.orient.origin) - plane[3];
|
|
||||||
|
|
||||||
float* o = plane;
|
|
||||||
const float* m = s_flipMatrix;
|
|
||||||
const float* v = plane2;
|
|
||||||
o[0] = m[0] * v[0] + m[4] * v[1] + m[8] * v[2] + m[12] * v[3];
|
|
||||||
o[1] = m[1] * v[0] + m[5] * v[1] + m[9] * v[2] + m[13] * v[3];
|
|
||||||
o[2] = m[2] * v[0] + m[6] * v[1] + m[10] * v[2] + m[14] * v[3];
|
|
||||||
o[3] = m[3] * v[0] + m[7] * v[1] + m[11] * v[2] + m[15] * v[3];
|
|
||||||
|
|
||||||
memcpy(clipPlane, plane, sizeof(clipPlane));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memset(clipPlane, 0, sizeof(clipPlane));
|
|
||||||
}
|
|
||||||
|
|
||||||
SCOPED_RENDER_PASS("Transparent", 1.0f, 0.5f, 0.5f);
|
SCOPED_RENDER_PASS("Transparent", 1.0f, 0.5f, 0.5f);
|
||||||
|
|
||||||
|
@ -222,7 +194,7 @@ void WorldTransp::ProcessShader(shader_t& shader)
|
||||||
desc.vertexShader = g_transp_draw_vs;
|
desc.vertexShader = g_transp_draw_vs;
|
||||||
desc.pixelShader = g_transp_draw_ps;
|
desc.pixelShader = g_transp_draw_ps;
|
||||||
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Position, DataType::Float32, 3, 0);
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Position, DataType::Float32, 3, 0);
|
||||||
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Normal, DataType::Float32, 2, 0);
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Normal, DataType::Float32, 3, 0);
|
||||||
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::TexCoord, DataType::Float32, 2, 0);
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::TexCoord, DataType::Float32, 2, 0);
|
||||||
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Color, DataType::UNorm8, 4, 0);
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Color, DataType::UNorm8, 4, 0);
|
||||||
desc.depthStencil.depthStencilFormat = TextureFormat::Depth32_Float;
|
desc.depthStencil.depthStencilFormat = TextureFormat::Depth32_Float;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Copyright (C) 2023 Gian 'myT' Schellenbaum
|
Copyright (C) 2023-2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
This file is part of Challenge Quake 3 (CNQ3).
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
|
|
@ -552,7 +552,7 @@ uint32_t GRP::CreatePSO(CachedPSO& cache, const char* name)
|
||||||
desc.vertexShader = vertexShaderByteCodes[cache.stageCount - 1];
|
desc.vertexShader = vertexShaderByteCodes[cache.stageCount - 1];
|
||||||
desc.pixelShader = pixelShaderByteCode;
|
desc.pixelShader = pixelShaderByteCode;
|
||||||
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Position, DataType::Float32, 3, 0);
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Position, DataType::Float32, 3, 0);
|
||||||
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Normal, DataType::Float32, 2, 0);
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::Normal, DataType::Float32, 3, 0);
|
||||||
for(int s = 0; s < cache.stageCount; ++s)
|
for(int s = 0; s < cache.stageCount; ++s)
|
||||||
{
|
{
|
||||||
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::TexCoord, DataType::Float32, 2, 0);
|
desc.vertexLayout.AddAttribute(a++, ShaderSemantic::TexCoord, DataType::Float32, 2, 0);
|
||||||
|
|
|
@ -363,34 +363,7 @@ void World::Begin()
|
||||||
{
|
{
|
||||||
srp.renderMode = RenderMode::World;
|
srp.renderMode = RenderMode::World;
|
||||||
|
|
||||||
if(backEnd.viewParms.isPortal)
|
RB_CreateClipPlane(clipPlane);
|
||||||
{
|
|
||||||
float plane[4];
|
|
||||||
plane[0] = backEnd.viewParms.portalPlane.normal[0];
|
|
||||||
plane[1] = backEnd.viewParms.portalPlane.normal[1];
|
|
||||||
plane[2] = backEnd.viewParms.portalPlane.normal[2];
|
|
||||||
plane[3] = backEnd.viewParms.portalPlane.dist;
|
|
||||||
|
|
||||||
float plane2[4];
|
|
||||||
plane2[0] = DotProduct(backEnd.viewParms.orient.axis[0], plane);
|
|
||||||
plane2[1] = DotProduct(backEnd.viewParms.orient.axis[1], plane);
|
|
||||||
plane2[2] = DotProduct(backEnd.viewParms.orient.axis[2], plane);
|
|
||||||
plane2[3] = DotProduct(plane, backEnd.viewParms.orient.origin) - plane[3];
|
|
||||||
|
|
||||||
float* o = plane;
|
|
||||||
const float* m = s_flipMatrix;
|
|
||||||
const float* v = plane2;
|
|
||||||
o[0] = m[0] * v[0] + m[4] * v[1] + m[8] * v[2] + m[12] * v[3];
|
|
||||||
o[1] = m[1] * v[0] + m[5] * v[1] + m[9] * v[2] + m[13] * v[3];
|
|
||||||
o[2] = m[2] * v[0] + m[6] * v[1] + m[10] * v[2] + m[14] * v[3];
|
|
||||||
o[3] = m[3] * v[0] + m[7] * v[1] + m[11] * v[2] + m[15] * v[3];
|
|
||||||
|
|
||||||
memcpy(clipPlane, plane, sizeof(clipPlane));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memset(clipPlane, 0, sizeof(clipPlane));
|
|
||||||
}
|
|
||||||
|
|
||||||
CmdSetViewportAndScissor(backEnd.viewParms);
|
CmdSetViewportAndScissor(backEnd.viewParms);
|
||||||
batchOldDepthHack = false;
|
batchOldDepthHack = false;
|
||||||
|
|
|
@ -1715,6 +1715,8 @@ namespace RHI
|
||||||
case TextureFormat::R8_UNorm: return DXGI_FORMAT_R8_UNORM;
|
case TextureFormat::R8_UNorm: return DXGI_FORMAT_R8_UNORM;
|
||||||
case TextureFormat::R10G10B10A2_UNorm: return DXGI_FORMAT_R10G10B10A2_UNORM;
|
case TextureFormat::R10G10B10A2_UNorm: return DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||||
case TextureFormat::R32_UInt: return DXGI_FORMAT_R32_UINT;
|
case TextureFormat::R32_UInt: return DXGI_FORMAT_R32_UINT;
|
||||||
|
case TextureFormat::RG32_SNorm: return DXGI_FORMAT_R16G16_SNORM;
|
||||||
|
case TextureFormat::RG32_Float: return DXGI_FORMAT_R16G16_FLOAT;
|
||||||
default: Q_assert(!"Unsupported texture format"); return DXGI_FORMAT_R8G8B8A8_UNORM;
|
default: Q_assert(!"Unsupported texture format"); return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,6 +170,8 @@ namespace RHI
|
||||||
Depth24_Stencil8,
|
Depth24_Stencil8,
|
||||||
R10G10B10A2_UNorm,
|
R10G10B10A2_UNorm,
|
||||||
R32_UInt,
|
R32_UInt,
|
||||||
|
RG32_SNorm,
|
||||||
|
RG32_Float,
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Copyright (C) 2023 Gian 'myT' Schellenbaum
|
Copyright (C) 2023-2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
This file is part of Challenge Quake 3 (CNQ3).
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
@ -138,7 +138,45 @@ float EaseInQuad(float x)
|
||||||
return x * x;
|
return x * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
float SmoothStep(float x)
|
float smoothstep01(float x)
|
||||||
{
|
{
|
||||||
return smoothstep(0.0, 1.0, x);
|
return smoothstep(0.0, 1.0, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Oct*: octahedron normal vector encoding
|
||||||
|
// original code from "A Survey of Efficient Representations for Independent Unit Vectors"
|
||||||
|
// further improved by Krzysztof Narkowicz and Rune Stubbe
|
||||||
|
|
||||||
|
float2 OctWrap(float2 v)
|
||||||
|
{
|
||||||
|
return (1.0 - abs(v.yx)) * (v.xy >= 0.0 ? 1.0 : -1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float2 OctEncode(float3 n)
|
||||||
|
{
|
||||||
|
n /= (abs(n.x) + abs(n.y) + abs(n.z));
|
||||||
|
n.xy = n.z >= 0.0 ? n.xy : OctWrap(n.xy);
|
||||||
|
n.xy = n.xy * 0.5 + 0.5;
|
||||||
|
|
||||||
|
return n.xy;
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 OctDecode(float2 f)
|
||||||
|
{
|
||||||
|
f = f * 2.0 - 1.0;
|
||||||
|
float3 n = float3(f.x, f.y, 1.0 - abs(f.x) - abs(f.y));
|
||||||
|
float t = saturate(-n.z);
|
||||||
|
n.xy += n.xy >= 0.0 ? -t : t;
|
||||||
|
|
||||||
|
return normalize(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 GetPositionFromDepth(float2 tc01, float depthZW, float4x4 invMatrix)
|
||||||
|
{
|
||||||
|
float x = tc01.x * 2.0 - 1.0;
|
||||||
|
float y = (1.0 - tc01.y) * 2.0 - 1.0;
|
||||||
|
float4 position = mul(float4(x, y, depthZW, 1.0), invMatrix);
|
||||||
|
float3 result = position.xyz / position.w;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Copyright (C) 2023 Gian 'myT' Schellenbaum
|
Copyright (C) 2023-2024 Gian 'myT' Schellenbaum
|
||||||
|
|
||||||
This file is part of Challenge Quake 3 (CNQ3).
|
This file is part of Challenge Quake 3 (CNQ3).
|
||||||
|
|
||||||
|
@ -76,9 +76,7 @@ VOut vs(VIn input)
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO: enable early-Z here once the full pre-pass is implemented
|
[earlydepthstencil]
|
||||||
// this will prevent fragments failing the depth test from writing to the shader ID buffer
|
|
||||||
//[earlydepthstencil]
|
|
||||||
float4 ps(VOut input) : SV_Target
|
float4 ps(VOut input) : SV_Target
|
||||||
{
|
{
|
||||||
// @TODO: Voronoi tiling
|
// @TODO: Voronoi tiling
|
||||||
|
|
98
code/renderer/shaders/crp/prepass.hlsl
Normal file
98
code/renderer/shaders/crp/prepass.hlsl
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
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/>.
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
// generic shader for the prepass of opaque surfaces
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.hlsli"
|
||||||
|
#include "world.h.hlsli"
|
||||||
|
#include "world.hlsli"
|
||||||
|
|
||||||
|
|
||||||
|
cbuffer RootConstants
|
||||||
|
{
|
||||||
|
// geometry
|
||||||
|
matrix modelViewMatrix;
|
||||||
|
matrix projectionMatrix;
|
||||||
|
matrix normalMatrix;
|
||||||
|
float4 clipPlane;
|
||||||
|
|
||||||
|
// general
|
||||||
|
uint textureIndex;
|
||||||
|
uint samplerIndex;
|
||||||
|
uint alphaTest;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VIn
|
||||||
|
{
|
||||||
|
float3 position : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
float2 texCoords : TEXCOORD0;
|
||||||
|
float4 color : COLOR0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VOut
|
||||||
|
{
|
||||||
|
float4 position : SV_Position;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
float2 texCoords : TEXCOORD0;
|
||||||
|
float4 color : COLOR0;
|
||||||
|
float clipDist : SV_ClipDistance0;
|
||||||
|
};
|
||||||
|
|
||||||
|
VOut vs(VIn input)
|
||||||
|
{
|
||||||
|
float4 positionVS = mul(modelViewMatrix, float4(input.position.xyz, 1));
|
||||||
|
|
||||||
|
VOut output;
|
||||||
|
output.position = mul(projectionMatrix, positionVS);
|
||||||
|
output.normal = mul(normalMatrix, float4(input.normal, 0)).xyz;
|
||||||
|
output.texCoords = input.texCoords;
|
||||||
|
output.color = input.color;
|
||||||
|
output.clipDist = dot(positionVS, clipPlane);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct POut
|
||||||
|
{
|
||||||
|
float2 normal : SV_Target0;
|
||||||
|
float2 motionVector : SV_Target1;
|
||||||
|
};
|
||||||
|
|
||||||
|
POut ps(VOut input)
|
||||||
|
{
|
||||||
|
if(alphaTest != ATEST_NONE)
|
||||||
|
{
|
||||||
|
Texture2D texture0 = ResourceDescriptorHeap[textureIndex];
|
||||||
|
SamplerState sampler0 = ResourceDescriptorHeap[samplerIndex];
|
||||||
|
float4 dst = texture0.Sample(sampler0, input.texCoords) * input.color;
|
||||||
|
if(FailsAlphaTest(dst.a, alphaTest))
|
||||||
|
{
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
POut output;
|
||||||
|
output.normal = OctEncode(normalize(input.normal));
|
||||||
|
output.motionVector = float2(0, 0); // @TODO:
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
|
@ -181,7 +181,7 @@ void UpdateEntityData(bool& depthHack, int entityNum, double originalTime)
|
||||||
tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
|
tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
|
||||||
|
|
||||||
// set up the transformation matrix
|
// set up the transformation matrix
|
||||||
R_RotateForEntity(backEnd.currentEntity, &backEnd.viewParms, &backEnd.orient);
|
R_RotateForEntity(backEnd.currentEntity, &backEnd.viewParms, &backEnd.orient, backEnd.modelMatrix);
|
||||||
|
|
||||||
if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK)
|
if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK)
|
||||||
{
|
{
|
||||||
|
@ -193,6 +193,7 @@ void UpdateEntityData(bool& depthHack, int entityNum, double originalTime)
|
||||||
backEnd.currentEntity = &tr.worldEntity;
|
backEnd.currentEntity = &tr.worldEntity;
|
||||||
backEnd.refdef.floatTime = originalTime;
|
backEnd.refdef.floatTime = originalTime;
|
||||||
backEnd.orient = backEnd.viewParms.world;
|
backEnd.orient = backEnd.viewParms.world;
|
||||||
|
R_MakeIdentityMatrix(backEnd.modelMatrix);
|
||||||
// we have to reset the shaderTime as well otherwise image animations on
|
// we have to reset the shaderTime as well otherwise image animations on
|
||||||
// the world (like water) continue with the wrong frame
|
// the world (like water) continue with the wrong frame
|
||||||
tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
|
tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
|
||||||
|
|
|
@ -64,8 +64,7 @@ void RB_PopShader()
|
||||||
// used when a player has predicted a teleport, but hasn't arrived yet
|
// used when a player has predicted a teleport, but hasn't arrived yet
|
||||||
float RB_HyperspaceColor()
|
float RB_HyperspaceColor()
|
||||||
{
|
{
|
||||||
if ( r_teleporterFlash->integer == 0 )
|
if (r_teleporterFlash->integer == 0) {
|
||||||
{
|
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,3 +72,33 @@ float RB_HyperspaceColor()
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RB_CreateClipPlane( float* clipPlane )
|
||||||
|
{
|
||||||
|
if (backEnd.viewParms.isPortal) {
|
||||||
|
float plane[4];
|
||||||
|
plane[0] = backEnd.viewParms.portalPlane.normal[0];
|
||||||
|
plane[1] = backEnd.viewParms.portalPlane.normal[1];
|
||||||
|
plane[2] = backEnd.viewParms.portalPlane.normal[2];
|
||||||
|
plane[3] = backEnd.viewParms.portalPlane.dist;
|
||||||
|
|
||||||
|
float plane2[4];
|
||||||
|
plane2[0] = DotProduct(backEnd.viewParms.orient.axis[0], plane);
|
||||||
|
plane2[1] = DotProduct(backEnd.viewParms.orient.axis[1], plane);
|
||||||
|
plane2[2] = DotProduct(backEnd.viewParms.orient.axis[2], plane);
|
||||||
|
plane2[3] = DotProduct(plane, backEnd.viewParms.orient.origin) - plane[3];
|
||||||
|
|
||||||
|
float* o = plane;
|
||||||
|
const float* m = s_flipMatrix;
|
||||||
|
const float* v = plane2;
|
||||||
|
o[0] = m[0] * v[0] + m[4] * v[1] + m[8] * v[2] + m[12] * v[3];
|
||||||
|
o[1] = m[1] * v[0] + m[5] * v[1] + m[9] * v[2] + m[13] * v[3];
|
||||||
|
o[2] = m[2] * v[0] + m[6] * v[1] + m[10] * v[2] + m[14] * v[3];
|
||||||
|
o[3] = m[3] * v[0] + m[7] * v[1] + m[11] * v[2] + m[15] * v[3];
|
||||||
|
|
||||||
|
memcpy(clipPlane, plane, 4 * sizeof(float));
|
||||||
|
} else {
|
||||||
|
memset(clipPlane, 0, 4 * sizeof(float));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -435,6 +435,8 @@ struct shader_t {
|
||||||
pipeline_t transpPipelines[MAX_SHADER_STAGES];
|
pipeline_t transpPipelines[MAX_SHADER_STAGES];
|
||||||
int numTranspPipelines;
|
int numTranspPipelines;
|
||||||
|
|
||||||
|
pipeline_t prepassPipeline;
|
||||||
|
|
||||||
shader_t* next;
|
shader_t* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -857,6 +859,7 @@ typedef struct {
|
||||||
viewParms_t viewParms;
|
viewParms_t viewParms;
|
||||||
orientationr_t orient;
|
orientationr_t orient;
|
||||||
trRefEntity_t* currentEntity;
|
trRefEntity_t* currentEntity;
|
||||||
|
float modelMatrix[16]; // real model matrix, not model-view
|
||||||
|
|
||||||
qbool projection2D; // if qtrue, drawstretchpic doesn't need to change modes
|
qbool projection2D; // if qtrue, drawstretchpic doesn't need to change modes
|
||||||
byte color2D[4];
|
byte color2D[4];
|
||||||
|
@ -1121,7 +1124,7 @@ int R_CullLocalBox( const vec3_t bounds[2] );
|
||||||
int R_CullPointAndRadius( const vec3_t origin, float radius );
|
int R_CullPointAndRadius( const vec3_t origin, float radius );
|
||||||
int R_CullLocalPointAndRadius( const vec3_t origin, float radius );
|
int R_CullLocalPointAndRadius( const vec3_t origin, float radius );
|
||||||
|
|
||||||
void R_RotateForEntity( const trRefEntity_t* ent, const viewParms_t* viewParms, orientationr_t* orient );
|
void R_RotateForEntity( const trRefEntity_t* ent, const viewParms_t* viewParms, orientationr_t* orient, float* modelMatrix = NULL );
|
||||||
void R_CreateWorldModelMatrix( const vec3_t origin, const vec3_t axis[3], float* viewMatrix );
|
void R_CreateWorldModelMatrix( const vec3_t origin, const vec3_t axis[3], float* viewMatrix );
|
||||||
|
|
||||||
typedef void (*updateAnimatedImage_t)( image_t* image, int w, int h, const byte* data, qbool dirty );
|
typedef void (*updateAnimatedImage_t)( image_t* image, int w, int h, const byte* data, qbool dirty );
|
||||||
|
@ -1572,8 +1575,8 @@ void RB_TakeVideoFrameCmd( const videoFrameCommand_t* cmd );
|
||||||
|
|
||||||
void RB_PushSingleStageShader( int stateBits, cullType_t cullType );
|
void RB_PushSingleStageShader( int stateBits, cullType_t cullType );
|
||||||
void RB_PopShader();
|
void RB_PopShader();
|
||||||
|
|
||||||
float RB_HyperspaceColor();
|
float RB_HyperspaceColor();
|
||||||
|
void RB_CreateClipPlane( float* clipPlane );
|
||||||
|
|
||||||
void RB_DrawSky();
|
void RB_DrawSky();
|
||||||
void R_BuildCloudData();
|
void R_BuildCloudData();
|
||||||
|
|
|
@ -493,7 +493,7 @@ Does NOT produce any GL calls
|
||||||
Called by both the front end and the back end
|
Called by both the front end and the back end
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
void R_RotateForEntity( const trRefEntity_t* ent, const viewParms_t* viewParms, orientationr_t* orient )
|
void R_RotateForEntity( const trRefEntity_t* ent, const viewParms_t* viewParms, orientationr_t* orient, float* modelMatrix )
|
||||||
{
|
{
|
||||||
float glMatrix[16];
|
float glMatrix[16];
|
||||||
vec3_t delta;
|
vec3_t delta;
|
||||||
|
@ -530,6 +530,10 @@ void R_RotateForEntity( const trRefEntity_t* ent, const viewParms_t* viewParms,
|
||||||
glMatrix[11] = 0;
|
glMatrix[11] = 0;
|
||||||
glMatrix[15] = 1;
|
glMatrix[15] = 1;
|
||||||
|
|
||||||
|
if ( modelMatrix != NULL ) {
|
||||||
|
Com_Memcpy( modelMatrix, glMatrix, sizeof( glMatrix ) );
|
||||||
|
}
|
||||||
|
|
||||||
R_MultMatrix( glMatrix, viewParms->world.modelMatrix, orient->modelMatrix );
|
R_MultMatrix( glMatrix, viewParms->world.modelMatrix, orient->modelMatrix );
|
||||||
|
|
||||||
// calculate the viewer origin in the model's space
|
// calculate the viewer origin in the model's space
|
||||||
|
|
|
@ -388,6 +388,7 @@ void ProcessCRP()
|
||||||
CompileCompute("mip_1.h", "mip_1.hlsl", "mip_1");
|
CompileCompute("mip_1.h", "mip_1.hlsl", "mip_1");
|
||||||
CompileCompute("mip_2.h", "mip_2.hlsl", "mip_2");
|
CompileCompute("mip_2.h", "mip_2.hlsl", "mip_2");
|
||||||
CompileCompute("mip_3.h", "mip_3.hlsl", "mip_3");
|
CompileCompute("mip_3.h", "mip_3.hlsl", "mip_3");
|
||||||
|
CompileGraphics("prepass.h", "prepass.hlsl", "prepass");
|
||||||
CompileGraphics("opaque.h", "opaque.hlsl", "opaque");
|
CompileGraphics("opaque.h", "opaque.hlsl", "opaque");
|
||||||
CompileGraphics("transp_draw.h", "transp_draw.hlsl", "transp_draw");
|
CompileGraphics("transp_draw.h", "transp_draw.hlsl", "transp_draw");
|
||||||
CompilePixelShader("transp_resolve.h", "transp_resolve.hlsl", "transp_resolve");
|
CompilePixelShader("transp_resolve.h", "transp_resolve.hlsl", "transp_resolve");
|
||||||
|
|
|
@ -134,6 +134,7 @@
|
||||||
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
||||||
|
<ClCompile Include="..\..\code\renderer\crp_prepass.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_tone_map.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_tone_map.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_transp_draw.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_transp_draw.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_transp_resolve.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_transp_resolve.cpp" />
|
||||||
|
@ -236,6 +237,9 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\opaque.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\opaque.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\prepass.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
||||||
|
<ClCompile Include="..\..\code\renderer\crp_prepass.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_tone_map.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_tone_map.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_transp_draw.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_transp_draw.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_transp_resolve.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_transp_resolve.cpp" />
|
||||||
|
@ -140,6 +141,9 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\opaque.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\opaque.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\prepass.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
|
|
@ -136,6 +136,7 @@
|
||||||
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
||||||
|
<ClCompile Include="..\..\code\renderer\crp_prepass.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_tone_map.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_tone_map.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_transp_draw.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_transp_draw.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_transp_resolve.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_transp_resolve.cpp" />
|
||||||
|
@ -238,6 +239,9 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\opaque.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\opaque.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\prepass.hlsl">
|
||||||
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_magnifier.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_main.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_opaque.cpp" />
|
||||||
|
<ClCompile Include="..\..\code\renderer\crp_prepass.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_tone_map.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_tone_map.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_transp_draw.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_transp_draw.cpp" />
|
||||||
<ClCompile Include="..\..\code\renderer\crp_transp_resolve.cpp" />
|
<ClCompile Include="..\..\code\renderer\crp_transp_resolve.cpp" />
|
||||||
|
@ -140,6 +141,9 @@
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\opaque.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\opaque.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
<FxCompile Include="..\..\code\renderer\shaders\crp\prepass.hlsl">
|
||||||
|
<Filter>shaders\crp</Filter>
|
||||||
|
</FxCompile>
|
||||||
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
<FxCompile Include="..\..\code\renderer\shaders\crp\tone_map.hlsl">
|
||||||
<Filter>shaders\crp</Filter>
|
<Filter>shaders\crp</Filter>
|
||||||
</FxCompile>
|
</FxCompile>
|
||||||
|
|
Loading…
Reference in a new issue