Removed unimplemented renderer passes

This commit is contained in:
Robert Beckebans 2023-10-13 16:14:49 +02:00
parent f408fcad38
commit 80ca705d8d
8 changed files with 2 additions and 2573 deletions

View file

@ -57,9 +57,8 @@ idCVar r_syncEveryFrame( "r_syncEveryFrame", "1", CVAR_BOOL, "Don't let the GPU
idCVar r_uploadBufferSizeMB( "r_uploadBufferSizeMB", "64", CVAR_INTEGER | CVAR_INIT, "Size of gpu upload buffer (Vulkan only)" );
// SRS - What is GLimp_SwapBuffers() used for? Disable for now
//void GLimp_SwapBuffers();
void RB_SetMVP( const idRenderMatrix& mvp );
constexpr std::size_t MAX_IMAGE_PARMS = 16;
class NvrhiContext
{

View file

@ -1,855 +0,0 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 2022 Stephen Pridham
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include <precompiled.h>
#pragma hdrstop
#include "framework/Common_local.h"
#include "renderer/RenderCommon.h"
#include "renderer/Framebuffer.h"
#include "FowardShadingPass.h"
#if 0
/*
same as D3DXMatrixOrthoOffCenterRH
http://msdn.microsoft.com/en-us/library/bb205348(VS.85).aspx
*/
static void MatrixOrthogonalProjectionRH( float m[16], float left, float right, float bottom, float top, float zNear, float zFar )
{
m[0] = 2 / ( right - left );
m[4] = 0;
m[8] = 0;
m[12] = ( left + right ) / ( left - right );
m[1] = 0;
m[5] = 2 / ( top - bottom );
m[9] = 0;
m[13] = ( top + bottom ) / ( bottom - top );
m[2] = 0;
m[6] = 0;
m[10] = 1 / ( zNear - zFar );
m[14] = zNear / ( zNear - zFar );
m[3] = 0;
m[7] = 0;
m[11] = 0;
m[15] = 1;
}
void ForwardShadingPass::Init( nvrhi::DeviceHandle deviceHandle )
{
device = deviceHandle;
auto texturedBindingLayoutDesc = nvrhi::BindingLayoutDesc()
.setVisibility( nvrhi::ShaderType::All )
.addItem( nvrhi::BindingLayoutItem::VolatileConstantBuffer( 0 ) )
.addItem( nvrhi::BindingLayoutItem::Texture_SRV( 0 ) )
.addItem( nvrhi::BindingLayoutItem::Sampler( 0 ) );
auto geometrySkinnedBindingLayoutDesc = nvrhi::BindingLayoutDesc()
.setVisibility( nvrhi::ShaderType::All )
.addItem( nvrhi::BindingLayoutItem::VolatileConstantBuffer( 0 ) )
.addItem( nvrhi::BindingLayoutItem::VolatileConstantBuffer( 1 ) );
auto geometryBindingLayoutDesc = nvrhi::BindingLayoutDesc()
.setVisibility( nvrhi::ShaderType::All )
.addItem( nvrhi::BindingLayoutItem::VolatileConstantBuffer( 0 ) );
texturedBindingLayout = device->createBindingLayout( texturedBindingLayoutDesc );
geometryBindingLayout = device->createBindingLayout( geometryBindingLayoutDesc );
pipelineDesc.bindingLayouts = { geometryBindingLayout };
geometryBindingSetDesc = nvrhi::BindingSetDesc()
.addItem( nvrhi::BindingSetItem::ConstantBuffer( 0, renderProgManager.ConstantBuffer() ) );
samplerCache.Init( deviceHandle.Get() );
pipeline = nullptr;
}
void ForwardShadingPass::DrawInteractions( nvrhi::ICommandList* commandList, const viewDef_t* viewDef )
{
if( r_skipInteractions.GetBool() || viewDef->viewLights == NULL )
{
return;
}
commandList->beginMarker( "DrawInteractions" );
GL_SelectTexture( 0 );
const bool useLightDepthBounds = r_useLightDepthBounds.GetBool() && !r_useShadowMapping.GetBool();
Framebuffer* previousFramebuffer = currentFramebuffer;
//
// for each light, perform shadowing and adding
//
for( const viewLight_t* vLight = viewDef->viewLights; vLight != NULL; vLight = vLight->next )
{
// do fogging later
if( vLight->lightShader->IsFogLight() )
{
continue;
}
if( vLight->lightShader->IsBlendLight() )
{
continue;
}
if( vLight->localInteractions == NULL && vLight->globalInteractions == NULL && vLight->translucentInteractions == NULL )
{
continue;
}
const idMaterial* lightShader = vLight->lightShader;
commandList->beginMarker( lightShader->GetName() );
// set the depth bounds for the whole light
if( useLightDepthBounds )
{
GL_DepthBoundsTest( vLight->scissorRect.zmin, vLight->scissorRect.zmax );
}
// RB: shadow mapping
if( r_useShadowMapping.GetBool() )
{
int side, sideStop;
if( vLight->parallel )
{
side = 0;
sideStop = r_shadowMapSplits.GetInteger() + 1;
}
else if( vLight->pointLight )
{
if( r_shadowMapSingleSide.GetInteger() != -1 )
{
side = r_shadowMapSingleSide.GetInteger();
sideStop = side + 1;
}
else
{
side = 0;
sideStop = 6;
}
}
else
{
side = -1;
sideStop = 0;
}
for( ; side < sideStop; side++ )
{
ShadowMapPass( commandList, vLight->globalShadows, vLight, side );
}
// go back to main render target
if( previousFramebuffer != NULL )
{
previousFramebuffer->Bind();
}
else
{
Framebuffer::Unbind();
}
renderProgManager.Unbind();
GL_State( GLS_DEFAULT, false );
}
// RB end
commandList->endMarker();
}
// disable stencil shadow test
GL_State( GLS_DEFAULT );
// unbind texture units
GL_SelectTexture( 0 );
// reset depth bounds
if( useLightDepthBounds )
{
GL_DepthBoundsTest( 0.0f, 0.0f );
}
commandList->endMarker();
}
void ForwardShadingPass::ShadowMapPass( nvrhi::ICommandList* commandList, const drawSurf_t* drawSurfs, const viewLight_t* vLight, int side )
{
if( r_skipShadows.GetBool() )
{
return;
}
if( drawSurfs == NULL )
{
return;
}
if( viewDef->renderView.rdflags & RDF_NOSHADOWS )
{
return;
}
renderProgManager.BindShader_Depth();
GL_SelectTexture( 0 );
uint64 glState = 0;
// the actual stencil func will be set in the draw code, but we need to make sure it isn't
// disabled here, and that the value will get reset for the interactions without looking
// like a no-change-required
GL_State( glState | GLS_POLYGON_OFFSET );
switch( r_shadowMapOccluderFacing.GetInteger() )
{
case 0:
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_FRONTSIDED );
GL_PolygonOffset( r_shadowMapPolygonFactor.GetFloat(), r_shadowMapPolygonOffset.GetFloat() );
break;
case 1:
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_BACKSIDED );
GL_PolygonOffset( -r_shadowMapPolygonFactor.GetFloat(), -r_shadowMapPolygonOffset.GetFloat() );
break;
default:
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_TWOSIDED );
GL_PolygonOffset( r_shadowMapPolygonFactor.GetFloat(), r_shadowMapPolygonOffset.GetFloat() );
break;
}
idRenderMatrix lightProjectionRenderMatrix;
idRenderMatrix lightViewRenderMatrix;
if( vLight->parallel && side >= 0 )
{
assert( side >= 0 && side < 6 );
// original light direction is from surface to light origin
idVec3 lightDir = -vLight->lightCenter;
if( lightDir.Normalize() == 0.0f )
{
lightDir[2] = -1.0f;
}
idMat3 rotation = lightDir.ToMat3();
//idAngles angles = lightDir.ToAngles();
//idMat3 rotation = angles.ToMat3();
const idVec3 viewDir = viewDef->renderView.viewaxis[0];
const idVec3 viewPos = viewDef->renderView.vieworg;
#if 1
idRenderMatrix::CreateViewMatrix( viewDef->renderView.vieworg, rotation, lightViewRenderMatrix );
#else
float lightViewMatrix[16];
MatrixLookAtRH( lightViewMatrix, viewPos, lightDir, viewDir );
idRenderMatrix::Transpose( *( idRenderMatrix* )lightViewMatrix, lightViewRenderMatrix );
#endif
idBounds lightBounds;
lightBounds.Clear();
ALIGNTYPE16 frustumCorners_t corners;
idRenderMatrix::GetFrustumCorners( corners, vLight->inverseBaseLightProject, bounds_zeroOneCube );
idVec4 point, transf;
for( int j = 0; j < 8; j++ )
{
point[0] = corners.x[j];
point[1] = corners.y[j];
point[2] = corners.z[j];
point[3] = 1;
lightViewRenderMatrix.TransformPoint( point, transf );
transf[0] /= transf[3];
transf[1] /= transf[3];
transf[2] /= transf[3];
lightBounds.AddPoint( transf.ToVec3() );
}
float lightProjectionMatrix[16];
MatrixOrthogonalProjectionRH( lightProjectionMatrix, lightBounds[0][0], lightBounds[1][0], lightBounds[0][1], lightBounds[1][1], -lightBounds[1][2], -lightBounds[0][2] );
idRenderMatrix::Transpose( *( idRenderMatrix* )lightProjectionMatrix, lightProjectionRenderMatrix );
// 'frustumMVP' goes from global space -> camera local space -> camera projective space
// invert the MVP projection so we can deform zero-to-one cubes into the frustum pyramid shape and calculate global bounds
idRenderMatrix splitFrustumInverse;
if( !idRenderMatrix::Inverse( viewDef->frustumMVPs[FRUSTUM_CASCADE1 + side], splitFrustumInverse ) )
{
idLib::Warning( "splitFrustumMVP invert failed" );
}
// splitFrustumCorners in global space
ALIGNTYPE16 frustumCorners_t splitFrustumCorners;
idRenderMatrix::GetFrustumCorners( splitFrustumCorners, splitFrustumInverse, bounds_unitCube );
idRenderMatrix lightViewProjectionRenderMatrix;
idRenderMatrix::Multiply( lightProjectionRenderMatrix, lightViewRenderMatrix, lightViewProjectionRenderMatrix );
// find the bounding box of the current split in the light's clip space
idBounds cropBounds;
cropBounds.Clear();
for( int j = 0; j < 8; j++ )
{
point[0] = splitFrustumCorners.x[j];
point[1] = splitFrustumCorners.y[j];
point[2] = splitFrustumCorners.z[j];
point[3] = 1;
lightViewRenderMatrix.TransformPoint( point, transf );
transf[0] /= transf[3];
transf[1] /= transf[3];
transf[2] /= transf[3];
cropBounds.AddPoint( transf.ToVec3() );
}
// don't let the frustum AABB be bigger than the light AABB
if( cropBounds[0][0] < lightBounds[0][0] )
{
cropBounds[0][0] = lightBounds[0][0];
}
if( cropBounds[0][1] < lightBounds[0][1] )
{
cropBounds[0][1] = lightBounds[0][1];
}
if( cropBounds[1][0] > lightBounds[1][0] )
{
cropBounds[1][0] = lightBounds[1][0];
}
if( cropBounds[1][1] > lightBounds[1][1] )
{
cropBounds[1][1] = lightBounds[1][1];
}
cropBounds[0][2] = lightBounds[0][2];
cropBounds[1][2] = lightBounds[1][2];
//float cropMatrix[16];
//MatrixCrop(cropMatrix, cropBounds[0], cropBounds[1]);
//idRenderMatrix cropRenderMatrix;
//idRenderMatrix::Transpose( *( idRenderMatrix* )cropMatrix, cropRenderMatrix );
//idRenderMatrix tmp = lightProjectionRenderMatrix;
//idRenderMatrix::Multiply( cropRenderMatrix, tmp, lightProjectionRenderMatrix );
MatrixOrthogonalProjectionRH( lightProjectionMatrix, cropBounds[0][0], cropBounds[1][0], cropBounds[0][1], cropBounds[1][1], -cropBounds[1][2], -cropBounds[0][2] );
idRenderMatrix::Transpose( *( idRenderMatrix* )lightProjectionMatrix, lightProjectionRenderMatrix );
shadowV[side] = lightViewRenderMatrix;
shadowP[side] = lightProjectionRenderMatrix;
}
else if( vLight->pointLight && side >= 0 )
{
assert( side >= 0 && side < 6 );
// FIXME OPTIMIZE no memset
float viewMatrix[16];
idVec3 vec;
idVec3 origin = vLight->globalLightOrigin;
// side of a point light
memset( viewMatrix, 0, sizeof( viewMatrix ) );
switch( side )
{
case 0:
viewMatrix[0] = 1;
viewMatrix[9] = 1;
viewMatrix[6] = -1;
break;
case 1:
viewMatrix[0] = -1;
viewMatrix[9] = -1;
viewMatrix[6] = -1;
break;
case 2:
viewMatrix[4] = 1;
viewMatrix[1] = -1;
viewMatrix[10] = 1;
break;
case 3:
viewMatrix[4] = -1;
viewMatrix[1] = -1;
viewMatrix[10] = -1;
break;
case 4:
viewMatrix[8] = 1;
viewMatrix[1] = -1;
viewMatrix[6] = -1;
break;
case 5:
viewMatrix[8] = -1;
viewMatrix[1] = 1;
viewMatrix[6] = -1;
break;
}
viewMatrix[12] = -origin[0] * viewMatrix[0] + -origin[1] * viewMatrix[4] + -origin[2] * viewMatrix[8];
viewMatrix[13] = -origin[0] * viewMatrix[1] + -origin[1] * viewMatrix[5] + -origin[2] * viewMatrix[9];
viewMatrix[14] = -origin[0] * viewMatrix[2] + -origin[1] * viewMatrix[6] + -origin[2] * viewMatrix[10];
viewMatrix[3] = 0;
viewMatrix[7] = 0;
viewMatrix[11] = 0;
viewMatrix[15] = 1;
// from world space to light origin, looking down the X axis
float unflippedLightViewMatrix[16];
// from world space to OpenGL view space, looking down the negative Z axis
float lightViewMatrix[16];
static float s_flipMatrix[16] =
{
// convert from our coordinate system (looking down X)
// to OpenGL's coordinate system (looking down -Z)
0, 0, -1, 0,
-1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 0, 1
};
memcpy( unflippedLightViewMatrix, viewMatrix, sizeof( unflippedLightViewMatrix ) );
R_MatrixMultiply( viewMatrix, s_flipMatrix, lightViewMatrix );
idRenderMatrix::Transpose( *( idRenderMatrix* )lightViewMatrix, lightViewRenderMatrix );
// set up 90 degree projection matrix
const float zNear = 4;
const float fov = r_shadowMapFrustumFOV.GetFloat();
float ymax = zNear * tan( fov * idMath::PI / 360.0f );
float ymin = -ymax;
float xmax = zNear * tan( fov * idMath::PI / 360.0f );
float xmin = -xmax;
const float width = xmax - xmin;
const float height = ymax - ymin;
// from OpenGL view space to OpenGL NDC ( -1 : 1 in XYZ )
float lightProjectionMatrix[16];
lightProjectionMatrix[0 * 4 + 0] = 2.0f * zNear / width;
lightProjectionMatrix[1 * 4 + 0] = 0.0f;
lightProjectionMatrix[2 * 4 + 0] = ( xmax + xmin ) / width; // normally 0
lightProjectionMatrix[3 * 4 + 0] = 0.0f;
lightProjectionMatrix[0 * 4 + 1] = 0.0f;
lightProjectionMatrix[1 * 4 + 1] = 2.0f * zNear / height;
lightProjectionMatrix[2 * 4 + 1] = ( ymax + ymin ) / height; // normally 0
lightProjectionMatrix[3 * 4 + 1] = 0.0f;
// this is the far-plane-at-infinity formulation, and
// crunches the Z range slightly so w=0 vertexes do not
// rasterize right at the wraparound point
lightProjectionMatrix[0 * 4 + 2] = 0.0f;
lightProjectionMatrix[1 * 4 + 2] = 0.0f;
lightProjectionMatrix[2 * 4 + 2] = -0.999f; // adjust value to prevent imprecision issues
lightProjectionMatrix[3 * 4 + 2] = -2.0f * zNear;
lightProjectionMatrix[0 * 4 + 3] = 0.0f;
lightProjectionMatrix[1 * 4 + 3] = 0.0f;
lightProjectionMatrix[2 * 4 + 3] = -1.0f;
lightProjectionMatrix[3 * 4 + 3] = 0.0f;
idRenderMatrix::Transpose( *( idRenderMatrix* )lightProjectionMatrix, lightProjectionRenderMatrix );
shadowV[side] = lightViewRenderMatrix;
shadowP[side] = lightProjectionRenderMatrix;
}
else
{
lightViewRenderMatrix.Identity();
lightProjectionRenderMatrix = vLight->baseLightProject;
shadowV[0] = lightViewRenderMatrix;
shadowP[0] = lightProjectionRenderMatrix;
}
GL_ViewportAndScissor( 0, 0, shadowMapResolutions[vLight->shadowLOD], shadowMapResolutions[vLight->shadowLOD] );
//glClear( GL_DEPTH_BUFFER_BIT );
// process the chain of shadows with the current rendering state
currentSpace = NULL;
nvrhi::GraphicsState graphicsState;
graphicsState.framebuffer = currentFramebuffer->GetApiObject();
nvrhi::Viewport viewport;
viewport.minX = currentViewport.x1;
viewport.minY = currentViewport.y1;
viewport.maxX = currentViewport.x2;
viewport.maxY = currentViewport.y2;
viewport.minZ = currentViewport.zmin;
viewport.maxZ = currentViewport.zmax;
graphicsState.viewport.addViewportAndScissorRect( viewport );
graphicsState.viewport.addScissorRect( nvrhi::Rect( currentScissor.x1, currentScissor.y1, currentScissor.x2, currentScissor.y2 ) );
renderProgManager.BindShader_Depth();
auto currentBindingSet = bindingCache.GetOrCreateBindingSet( geometryBindingSetDesc, renderProgManager.BindingLayout() );
graphicsState.bindings = { currentBindingSet };
bool stateValid = false;
nvrhi::DrawArguments currentDraw;
currentDraw.instanceCount = 0;
shaderStage_t lastStage;
bool changedStage = false;
int lastShader = -1;
for( const drawSurf_t* drawSurf = drawSurfs; drawSurf != NULL; drawSurf = drawSurf->nextOnLight )
{
stateValid = false;
// Make sure the shadow occluder geometry is done
if( drawSurf->shadowVolumeState != SHADOWVOLUME_DONE )
{
assert( drawSurf->shadowVolumeState == SHADOWVOLUME_UNFINISHED || drawSurf->shadowVolumeState == SHADOWVOLUME_DONE );
uint64 start = Sys_Microseconds();
while( drawSurf->shadowVolumeState == SHADOWVOLUME_UNFINISHED )
{
Sys_Yield();
}
uint64 end = Sys_Microseconds();
// TODO(Stephen): will probably need to change this if we're going to make this multi-threaded.
tr.backend.pc.cpuShadowMicroSec += end - start;
}
if( drawSurf->numIndexes == 0 )
{
continue; // a job may have created an empty shadow geometry
}
if( drawSurf->space != currentSpace )
{
idRenderMatrix modelRenderMatrix;
idRenderMatrix::Transpose( *( idRenderMatrix* )drawSurf->space->modelMatrix, modelRenderMatrix );
idRenderMatrix modelToLightRenderMatrix;
idRenderMatrix::Multiply( lightViewRenderMatrix, modelRenderMatrix, modelToLightRenderMatrix );
idRenderMatrix clipMVP;
idRenderMatrix::Multiply( lightProjectionRenderMatrix, modelToLightRenderMatrix, clipMVP );
if( vLight->parallel )
{
idRenderMatrix MVP;
idRenderMatrix::Multiply( renderMatrix_clipSpaceToWindowSpace, clipMVP, MVP );
RB_SetMVP( clipMVP );
}
else if( side < 0 )
{
// from OpenGL view space to OpenGL NDC ( -1 : 1 in XYZ )
idRenderMatrix MVP;
idRenderMatrix::Multiply( renderMatrix_windowSpaceToClipSpace, clipMVP, MVP );
RB_SetMVP( MVP );
}
else
{
RB_SetMVP( clipMVP );
}
// set the local light position to allow the vertex program to project the shadow volume end cap to infinity
/*
idVec4 localLight( 0.0f );
R_GlobalPointToLocal( drawSurf->space->modelMatrix, vLight->globalLightOrigin, localLight.ToVec3() );
SetVertexParm( RENDERPARM_LOCALLIGHTORIGIN, localLight.ToFloatPtr() );
*/
currentSpace = drawSurf->space;
}
bool didDraw = false;
const idMaterial* shader = drawSurf->material;
// get the expressions for conditionals / color / texcoords
const float* regs = drawSurf->shaderRegisters;
idVec4 color( 0, 0, 0, 1 );
uint64 surfGLState = 0;
// set polygon offset if necessary
if( shader && shader->TestMaterialFlag( MF_POLYGONOFFSET ) )
{
surfGLState |= GLS_POLYGON_OFFSET;
GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() );
}
if( shader && shader->Coverage() == MC_PERFORATED )
{
// perforated surfaces may have multiple alpha tested stages
for( int stage = 0; stage < shader->GetNumStages(); stage++ )
{
const shaderStage_t* pStage = shader->GetStage( stage );
if( !pStage->hasAlphaTest )
{
continue;
}
// check the stage enable condition
if( regs[pStage->conditionRegister] == 0 )
{
continue;
}
// if we at least tried to draw an alpha tested stage,
// we won't draw the opaque surface
didDraw = true;
// set the alpha modulate
color[3] = regs[pStage->color.registers[3]];
// skip the entire stage if alpha would be black
if( color[3] <= 0.0f )
{
continue;
}
uint64 stageGLState = surfGLState;
// set privatePolygonOffset if necessary
if( pStage->privatePolygonOffset )
{
GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * pStage->privatePolygonOffset );
stageGLState |= GLS_POLYGON_OFFSET;
}
GL_Color( color );
GL_State( stageGLState );
idVec4 alphaTestValue( regs[pStage->alphaTestRegister] );
renderProgManager.SetRenderParm( RENDERPARM_ALPHA_TEST, alphaTestValue.ToFloatPtr() );
if( drawSurf->jointCache )
{
renderProgManager.BindShader_TextureVertexColorSkinned();
}
else
{
renderProgManager.BindShader_TextureVertexColor();
}
RB_SetVertexColorParms( SVC_IGNORE );
bool imageChanged = ( imageParms[0] != pStage->texture.image );
// bind the texture
GL_SelectTexture( 0 );
GL_BindTexture( pStage->texture.image );
// set texture matrix and texGens
PrepareStageTexturing( pStage, drawSurf );
if( imageChanged )
{
auto bindingSetDesc = nvrhi::BindingSetDesc()
.addItem( nvrhi::BindingSetItem::ConstantBuffer( 0, renderProgManager.ConstantBuffer() ) )
.addItem( nvrhi::BindingSetItem::Texture_SRV( 0, ( nvrhi::ITexture* )imageParms[0]->GetTextureID() ) )
.addItem( nvrhi::BindingSetItem::Sampler( 0, ( nvrhi::ISampler* )imageParms[0]->GetSampler( samplerCache ) ) );
auto currentBindingSet = bindingCache.GetOrCreateBindingSet( bindingSetDesc, renderProgManager.BindingLayout() );
graphicsState.bindings = { currentBindingSet };
stateValid = false;
}
// must render with less-equal for Z-Cull to work properly
assert( ( GL_GetCurrentState() & GLS_DEPTHFUNC_BITS ) == GLS_DEPTHFUNC_LESS );
SetupInputBuffers( drawSurf, graphicsState );
renderProgManager.CommitConstantBuffer( commandList );
if( !stateValid )
{
commandList->setGraphicsState( graphicsState );
stateValid = true;
}
if( !pipeline )
{
pipeline = CreateGraphicsPipeline( currentFramebuffer->GetApiObject() );
}
nvrhi::DrawArguments args;
args.vertexCount = drawSurf->numIndexes;
args.instanceCount = 1;
commandList->drawIndexed( args );
// clean up
FinishStageTexturing( pStage, drawSurf );
// unset privatePolygonOffset if necessary
if( pStage->privatePolygonOffset )
{
GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() );
}
}
}
if( !didDraw )
{
if( drawSurf->jointCache )
{
renderProgManager.BindShader_DepthSkinned();
}
else
{
renderProgManager.BindShader_Depth();
}
// must render with less-equal for Z-Cull to work properly
assert( ( GL_GetCurrentState() & GLS_DEPTHFUNC_BITS ) == GLS_DEPTHFUNC_LESS );
SetupInputBuffers( drawSurf, graphicsState );
if( !stateValid )
{
commandList->setGraphicsState( graphicsState );
stateValid = true;
}
if( !pipeline )
{
pipeline = CreateGraphicsPipeline( currentFramebuffer->GetApiObject() );
}
renderProgManager.CommitConstantBuffer( commandList );
nvrhi::DrawArguments args;
args.vertexCount = drawSurf->numIndexes;
args.instanceCount = 1;
commandList->drawIndexed( args );
}
}
}
nvrhi::GraphicsPipelineHandle ForwardShadingPass::CreateGraphicsPipeline( nvrhi::IFramebuffer* framebuffer )
{
return device->createGraphicsPipeline( pipelineDesc, framebuffer );
}
void ForwardShadingPass::SetupView( nvrhi::ICommandList* commandList, viewDef_t* viewDef )
{
}
bool ForwardShadingPass::SetupMaterial( const idMaterial* material, nvrhi::RasterCullMode cullMode, nvrhi::GraphicsState& state )
{
if( !pipeline )
{
pipeline = CreateGraphicsPipeline( state.framebuffer );
}
if( !pipeline )
{
return false;
}
assert( pipeline->getFramebufferInfo() == state.framebuffer->getFramebufferInfo() );
state.pipeline = pipeline;
return true;
}
void ForwardShadingPass::SetupInputBuffers( const drawSurf_t* surf, nvrhi::GraphicsState& state )
{
// Get vertex buffer
const vertCacheHandle_t vbHandle = surf->ambientCache;
idVertexBuffer* vertexBuffer;
if( vertexCache.CacheIsStatic( vbHandle ) )
{
vertexBuffer = &vertexCache.staticData.vertexBuffer;
}
else
{
const uint64 frameNum = ( int )( vbHandle >> VERTCACHE_FRAME_SHIFT ) & VERTCACHE_FRAME_MASK;
if( frameNum != ( ( vertexCache.currentFrame - 1 ) & VERTCACHE_FRAME_MASK ) )
{
idLib::Warning( "RB_DrawElementsWithCounters, vertexBuffer == NULL" );
return;
}
vertexBuffer = &vertexCache.frameData[vertexCache.drawListNum].vertexBuffer;
}
const uint vertOffset = ( uint )( vbHandle >> VERTCACHE_OFFSET_SHIFT ) & VERTCACHE_OFFSET_MASK;
// Get index buffer
const vertCacheHandle_t ibHandle = surf->indexCache;
idIndexBuffer* indexBuffer;
if( vertexCache.CacheIsStatic( ibHandle ) )
{
indexBuffer = &vertexCache.staticData.indexBuffer;
}
else
{
const uint64 frameNum = ( int )( ibHandle >> VERTCACHE_FRAME_SHIFT ) & VERTCACHE_FRAME_MASK;
if( frameNum != ( ( vertexCache.currentFrame - 1 ) & VERTCACHE_FRAME_MASK ) )
{
idLib::Warning( "RB_DrawElementsWithCounters, indexBuffer == NULL" );
return;
}
indexBuffer = &vertexCache.frameData[vertexCache.drawListNum].indexBuffer;
}
const uint indexOffset = ( uint )( ibHandle >> VERTCACHE_OFFSET_SHIFT ) & VERTCACHE_OFFSET_MASK;
state.indexBuffer = { indexBuffer->GetAPIObject(), nvrhi::Format::R16_UINT, indexOffset };
state.vertexBuffers = { { vertexBuffer->GetAPIObject(), 0, vertOffset } };
}
void ForwardShadingPass::SetPushConstants( nvrhi::ICommandList* commandList, nvrhi::GraphicsState& state, nvrhi::DrawArguments& args )
{
}
#endif

View file

@ -1,70 +0,0 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 2022 Stephen Pridham
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef RENDERER_PASSES_FORWARDSHADINGPASS_H_
#define RENDERER_PASSES_FORWARDSHADINGPASS_H_
#include "GeometryPasses.h"
#if 0
class ForwardShadingPass : IGeometryPass
{
public:
ForwardShadingPass() = default;
virtual ~ForwardShadingPass() = default;
void Init( nvrhi::DeviceHandle deviceHandle );
void DrawInteractions( nvrhi::ICommandList* commandList, const viewDef_t* _viewDef );
void ShadowMapPass( nvrhi::ICommandList* commandList, const drawSurf_t* drawSurfs, const viewLight_t* vLight, int side );
protected:
nvrhi::DeviceHandle device;
nvrhi::BindingLayoutHandle geometryBindingLayout;
nvrhi::BindingLayoutHandle texturedBindingLayout;
nvrhi::BindingSetDesc geometryBindingSetDesc;
SamplerCache samplerCache;
nvrhi::GraphicsPipelineHandle CreateGraphicsPipeline( nvrhi::IFramebuffer* framebuffer );
public:
void SetupView( nvrhi::ICommandList* commandList, viewDef_t* viewDef ) override;
bool SetupMaterial( const idMaterial* material, nvrhi::RasterCullMode cullMode, nvrhi::GraphicsState& state ) override;
void SetupInputBuffers( const drawSurf_t* drawSurf, nvrhi::GraphicsState& state ) override;
void SetPushConstants( nvrhi::ICommandList* commandList, nvrhi::GraphicsState& state, nvrhi::DrawArguments& args ) override;
private:
idRenderMatrix shadowV[6]; // shadow depth view matrix
idRenderMatrix shadowP[6]; // shadow depth projection matrix
};
#endif
#endif

View file

@ -1,678 +0,0 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 2022 Stephen Pridham
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include <precompiled.h>
#pragma hdrstop
#include "renderer/RenderCommon.h"
#include "GBufferFillPass.h"
#if 0
void GBufferFillPass::Init( nvrhi::DeviceHandle deviceHandle )
{
}
#if 0
void GBufferFillPass::RenderView( nvrhi::ICommandList* commandList, const drawSurf_t* const* drawSurfs, int numDrawSurfs, bool fillGbuffer )
{
Framebuffer* previousFramebuffer = Framebuffer::GetActiveFramebuffer();
if( numDrawSurfs == 0 )
{
return;
}
if( !drawSurfs )
{
return;
}
// if we are just doing 2D rendering, no need to fill the depth buffer
if( viewDef->viewEntitys == NULL )
{
return;
}
if( viewDef->renderView.rdflags & RDF_NOAMBIENT )
{
return;
}
/*
if( !fillGbuffer )
{
// clear gbuffer
GL_Clear( true, false, false, 0, 0.0f, 0.0f, 0.0f, 1.0f, false );
}
*/
if( !fillGbuffer && r_useSSAO.GetBool() && r_ssaoDebug.GetBool() )
{
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS );
// We just want to do a quad pass - so make sure we disable any texgen and
// set the texture matrix to the identity so we don't get anomalies from
// any stale uniform data being present from a previous draw call
const float texS[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
const float texT[4] = { 0.0f, 1.0f, 0.0f, 0.0f };
renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_S, texS );
renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_T, texT );
// disable any texgen
const float texGenEnabled[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
renderProgManager.SetRenderParm( RENDERPARM_TEXGEN_0_ENABLED, texGenEnabled );
currentSpace = NULL;
RB_SetMVP( renderMatrix_identity );
renderProgManager.BindShader_Texture();
GL_Color( idVec4( 1 ) );
GL_SelectTexture( 0 );
globalImages->ambientOcclusionImage[0]->Bind();
DrawElementsWithCounters( &tr.backend.unitSquareSurface );
renderProgManager.Unbind();
GL_State( GLS_DEFAULT );
renderProgManager.SetRenderParm( RENDERPARM_ALPHA_TEST, vec4_zero.ToFloatPtr() );
return;
}
renderLog.OpenMainBlock( fillGbuffer ? MRB_FILL_GEOMETRY_BUFFER : MRB_AMBIENT_PASS );
renderLog.OpenBlock( fillGbuffer ? "Fill_GeometryBuffer" : "Render_AmbientPass", colorBlue );
if( fillGbuffer )
{
globalFramebuffers.geometryBufferFBO->Bind();
GL_Clear( true, false, false, 0, 0.0f, 0.0f, 0.0f, 1.0f, false );
}
commandList->setEnableAutomaticBarriers( false );
commandList->setResourceStatesForFramebuffer( currentFrameBuffer->GetApiObject() );
commandList->commitBarriers();
// RB: not needed
// GL_StartDepthPass( backEnd.viewDef->scissor );
// force MVP change on first surface
currentSpace = NULL;
// draw all the subview surfaces, which will already be at the start of the sorted list,
// with the general purpose path
GL_State( GLS_DEFAULT );
#define BLEND_NORMALS 1
// RB: even use additive blending to blend the normals
//GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
GL_Color( colorWhite );
idVec4 diffuseColor;
idVec4 specularColor;
idVec4 ambientColor;
if( viewDef->renderView.rdflags & RDF_IRRADIANCE )
{
// RB: don't let artist run into a trap when baking multibounce lightgrids
// use default value of r_lightScale 3
const float lightScale = 3;
const idVec4 lightColor = colorWhite * lightScale;
// apply the world-global overbright and the 2x factor for specular
diffuseColor = lightColor;
specularColor = lightColor;// * 2.0f;
// loose 5% with every bounce like in DDGI
const float energyConservation = 0.95f;
//ambientColor.Set( energyConservation, energyConservation, energyConservation, 1.0f );
float a = r_forceAmbient.GetFloat();
ambientColor.Set( a, a, a, 1 );
}
else
{
const float lightScale = r_lightScale.GetFloat();
const idVec4 lightColor = colorWhite * lightScale;
// apply the world-global overbright and tune down specular a bit so we have less fresnel overglow
diffuseColor = lightColor;
specularColor = lightColor;// * 0.5f;
float ambientBoost = 1.0f;
if( !r_usePBR.GetBool() )
{
ambientBoost += r_useSSAO.GetBool() ? 0.2f : 0.0f;
ambientBoost *= 1.1f;
}
ambientColor.x = r_forceAmbient.GetFloat() * ambientBoost;
ambientColor.y = r_forceAmbient.GetFloat() * ambientBoost;
ambientColor.z = r_forceAmbient.GetFloat() * ambientBoost;
ambientColor.w = 1;
}
renderProgManager.SetRenderParm( RENDERPARM_AMBIENT_COLOR, ambientColor.ToFloatPtr() );
bool useIBL = r_usePBR.GetBool() && !fillGbuffer;
// setup renderparms assuming we will be drawing trivial surfaces first
RB_SetupForFastPathInteractions( diffuseColor, specularColor );
for( int i = 0; i < numDrawSurfs; i++ )
{
const drawSurf_t* drawSurf = drawSurfs[i];
const idMaterial* surfaceMaterial = drawSurf->material;
// translucent surfaces don't put anything in the depth buffer and don't
// test against it, which makes them fail the mirror clip plane operation
if( surfaceMaterial->Coverage() == MC_TRANSLUCENT )
{
continue;
}
// get the expressions for conditionals / color / texcoords
const float* surfaceRegs = drawSurf->shaderRegisters;
// if all stages of a material have been conditioned off, don't do anything
int stage = 0;
for( ; stage < surfaceMaterial->GetNumStages(); stage++ )
{
const shaderStage_t* pStage = surfaceMaterial->GetStage( stage );
// check the stage enable condition
if( surfaceRegs[pStage->conditionRegister] != 0 )
{
break;
}
}
if( stage == surfaceMaterial->GetNumStages() )
{
continue;
}
//bool isWorldModel = ( drawSurf->space->entityDef->parms.origin == vec3_origin );
//if( isWorldModel )
//{
// renderProgManager.BindShader_VertexLighting();
//}
//else
{
if( fillGbuffer )
{
// TODO support PBR textures and store roughness in the alpha channel
// fill geometry buffer with normal/roughness information
if( drawSurf->jointCache )
{
renderProgManager.BindShader_SmallGeometryBufferSkinned();
}
else
{
renderProgManager.BindShader_SmallGeometryBuffer();
}
}
else
{
// TODO support PBR textures
// draw Quake 4 style ambient
if( drawSurf->jointCache )
{
renderProgManager.BindShader_AmbientLightingSkinned();
}
else
{
renderProgManager.BindShader_AmbientLighting();
}
}
}
// change the matrix if needed
if( drawSurf->space != currentSpace )
{
currentSpace = drawSurf->space;
RB_SetMVP( drawSurf->space->mvp );
// tranform the view origin into model local space
idVec4 localViewOrigin( 1.0f );
R_GlobalPointToLocal( drawSurf->space->modelMatrix, viewDef->renderView.vieworg, localViewOrigin.ToVec3() );
SetVertexParm( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() );
// RB: if we want to store the normals in world space so we need the model -> world matrix
idRenderMatrix modelMatrix;
idRenderMatrix::Transpose( *( idRenderMatrix* )drawSurf->space->modelMatrix, modelMatrix );
SetVertexParms( RENDERPARM_MODELMATRIX_X, modelMatrix[0], 4 );
// RB: if we want to store the normals in camera space so we need the model -> camera matrix
float modelViewMatrixTranspose[16];
R_MatrixTranspose( drawSurf->space->modelViewMatrix, modelViewMatrixTranspose );
SetVertexParms( RENDERPARM_MODELVIEWMATRIX_X, modelViewMatrixTranspose, 4 );
}
/*
uint64 surfGLState = 0;
// set polygon offset if necessary
if( surfaceMaterial->TestMaterialFlag( MF_POLYGONOFFSET ) )
{
surfGLState |= GLS_POLYGON_OFFSET;
GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * surfaceMaterial->GetPolygonOffset() );
}
// subviews will just down-modulate the color buffer
idVec4 color;
if( surfaceMaterial->GetSort() == SS_SUBVIEW )
{
surfGLState |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHFUNC_LESS;
color[0] = 1.0f;
color[1] = 1.0f;
color[2] = 1.0f;
color[3] = 1.0f;
}
else
{
// others just draw black
#if 0
color[0] = 0.0f;
color[1] = 0.0f;
color[2] = 0.0f;
color[3] = 1.0f;
#else
color = colorWhite;
#endif
}
*/
drawInteraction_t inter = {};
inter.surf = drawSurf;
inter.diffuseColor[0] = inter.diffuseColor[1] = inter.diffuseColor[2] = inter.diffuseColor[3] = 1;
inter.specularColor[0] = inter.specularColor[1] = inter.specularColor[2] = inter.specularColor[3] = 0;
// check for the fast path
if( surfaceMaterial->GetFastPathBumpImage() && !r_skipInteractionFastPath.GetBool() )
{
renderLog.OpenBlock( surfaceMaterial->GetName(), colorMdGrey );
inter.bumpImage = surfaceMaterial->GetFastPathBumpImage();
inter.specularImage = surfaceMaterial->GetFastPathSpecularImage();
inter.diffuseImage = surfaceMaterial->GetFastPathDiffuseImage();
DrawSingleInteraction( &inter, true, useIBL, false );
renderLog.CloseBlock();
continue;
}
renderLog.OpenBlock( surfaceMaterial->GetName(), colorMdGrey );
//bool drawSolid = false;
inter.bumpImage = NULL;
inter.specularImage = NULL;
inter.diffuseImage = NULL;
// we may have multiple alpha tested stages
// if the only alpha tested stages are condition register omitted,
// draw a normal opaque surface
bool didDraw = false;
// perforated surfaces may have multiple alpha tested stages
for( stage = 0; stage < surfaceMaterial->GetNumStages(); stage++ )
{
const shaderStage_t* surfaceStage = surfaceMaterial->GetStage( stage );
switch( surfaceStage->lighting )
{
case SL_COVERAGE:
{
// ignore any coverage stages since they should only be used for the depth fill pass
// for diffuse stages that use alpha test.
break;
}
case SL_AMBIENT:
{
// ignore ambient stages while drawing interactions
break;
}
case SL_BUMP:
{
// ignore stage that fails the condition
if( !surfaceRegs[surfaceStage->conditionRegister] )
{
break;
}
// draw any previous interaction
if( inter.bumpImage != NULL )
{
#if BLEND_NORMALS
if( inter.vertexColor == SVC_IGNORE )
{
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
}
else
{
// RB: this is a bit hacky: use additive blending to blend the normals
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
}
#endif
DrawSingleInteraction( &inter, false, useIBL, false );
}
inter.bumpImage = surfaceStage->texture.image;
inter.diffuseImage = NULL;
inter.specularImage = NULL;
SetupInteractionStage( surfaceStage, surfaceRegs, NULL,
inter.bumpMatrix, NULL );
break;
}
case SL_DIFFUSE:
{
// ignore stage that fails the condition
if( !surfaceRegs[surfaceStage->conditionRegister] )
{
break;
}
// draw any previous interaction
if( inter.diffuseImage != NULL )
{
#if BLEND_NORMALS
if( inter.vertexColor == SVC_IGNORE )
{
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
}
else
{
// RB: this is a bit hacky: use additive blending to blend the normals
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
}
#endif
DrawSingleInteraction( &inter, false, useIBL, false );
}
inter.diffuseImage = surfaceStage->texture.image;
inter.vertexColor = surfaceStage->vertexColor;
SetupInteractionStage( surfaceStage, surfaceRegs, diffuseColor.ToFloatPtr(),
inter.diffuseMatrix, inter.diffuseColor.ToFloatPtr() );
break;
}
case SL_SPECULAR:
case SL_RMAO:
{
// ignore stage that fails the condition
if( !surfaceRegs[surfaceStage->conditionRegister] )
{
break;
}
// draw any previous interaction
if( inter.specularImage != NULL )
{
#if BLEND_NORMALS
if( inter.vertexColor == SVC_IGNORE )
{
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
}
else
{
// RB: this is a bit hacky: use additive blending to blend the normals
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
}
#endif
DrawSingleInteraction( &inter, false, useIBL, false );
}
inter.specularImage = surfaceStage->texture.image;
inter.vertexColor = surfaceStage->vertexColor;
SetupInteractionStage( surfaceStage, surfaceRegs, specularColor.ToFloatPtr(),
inter.specularMatrix, inter.specularColor.ToFloatPtr() );
break;
}
}
}
// draw the final interaction
#if BLEND_NORMALS
if( inter.vertexColor == SVC_IGNORE )
{
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
}
else
{
// RB: this is a bit hacky: use additive blending to blend the normals
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
}
#endif
DrawSingleInteraction( &inter, false, useIBL, false );
renderLog.CloseBlock();
}
// disable blending
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
SetFragmentParm( RENDERPARM_ALPHA_TEST, vec4_zero.ToFloatPtr() );
GL_SelectTexture( 0 );
if( fillGbuffer )
{
// go back to main render target
if( previousFramebuffer != NULL )
{
previousFramebuffer->Bind();
}
else
{
Framebuffer::Unbind();
}
}
renderProgManager.Unbind();
renderLog.CloseBlock();
renderLog.CloseMainBlock();
}
nvrhi::GraphicsPipelineHandle GBufferFillPass::CreateGraphicsPipeline( nvrhi::IFramebuffer* framebuffer )
{
return nvrhi::GraphicsPipelineHandle();
}
void GBufferFillPass::DrawElementsWithCounters( const drawSurf_t* surf )
{
// Get vertex buffer
const vertCacheHandle_t vbHandle = surf->ambientCache;
idVertexBuffer* vertexBuffer;
if( vertexCache.CacheIsStatic( vbHandle ) )
{
vertexBuffer = &vertexCache.staticData.vertexBuffer;
}
else
{
const uint64 frameNum = ( int )( vbHandle >> VERTCACHE_FRAME_SHIFT ) & VERTCACHE_FRAME_MASK;
if( frameNum != ( ( vertexCache.currentFrame - 1 ) & VERTCACHE_FRAME_MASK ) )
{
idLib::Warning( "RB_DrawElementsWithCounters, vertexBuffer == NULL" );
return;
}
vertexBuffer = &vertexCache.frameData[vertexCache.drawListNum].vertexBuffer;
}
const uint vertOffset = ( uint )( vbHandle >> VERTCACHE_OFFSET_SHIFT ) & VERTCACHE_OFFSET_MASK;
auto currentVertexBuffer = vertexBuffer->GetAPIObject();
// Get index buffer
const vertCacheHandle_t ibHandle = surf->indexCache;
idIndexBuffer* indexBuffer;
if( vertexCache.CacheIsStatic( ibHandle ) )
{
indexBuffer = &vertexCache.staticData.indexBuffer;
}
else
{
const uint64 frameNum = ( int )( ibHandle >> VERTCACHE_FRAME_SHIFT ) & VERTCACHE_FRAME_MASK;
if( frameNum != ( ( vertexCache.currentFrame - 1 ) & VERTCACHE_FRAME_MASK ) )
{
idLib::Warning( "RB_DrawElementsWithCounters, indexBuffer == NULL" );
return;
}
indexBuffer = &vertexCache.frameData[vertexCache.drawListNum].indexBuffer;
}
const uint indexOffset = ( uint )( ibHandle >> VERTCACHE_OFFSET_SHIFT ) & VERTCACHE_OFFSET_MASK;
auto currentIndexBuffer = ( nvrhi::IBuffer* )indexBuffer->GetAPIObject();
if( currentIndexBuffer != ( nvrhi::IBuffer* )indexBuffer->GetAPIObject() || !r_useStateCaching.GetBool() )
{
currentIndexBuffer = indexBuffer->GetAPIObject();
}
if( !pipeline )
{
nvrhi::GraphicsPipelineDesc psoDesc;
psoDesc.VS = vertexShader;
psoDesc.PS = pixelShader;
psoDesc.inputLayout = inputLayout;
psoDesc.bindingLayouts = { currentBindingLayout };
psoDesc.primType = nvrhi::PrimitiveType::TriangleList;
currentRenderState.rasterState.enableScissor();
psoDesc.setRenderState( currentRenderState );
pipeline = device->createGraphicsPipeline( psoDesc, currentFramebuffer->GetApiObject() );
}
nvrhi::BindingSetDesc bindingSetDesc;
if( renderProgManager.BindingLayoutType() == BINDING_LAYOUT_DEFAULT )
{
bindingSetDesc
.addItem( nvrhi::BindingSetItem::ConstantBuffer( 0, renderProgManager.ConstantBuffer() ) )
.addItem( nvrhi::BindingSetItem::Texture_SRV( 0, ( nvrhi::ITexture* )GetImageAt( 0 )->GetTextureID() ) )
.addItem( nvrhi::BindingSetItem::Sampler( 0, ( nvrhi::ISampler* )GetImageAt( 0 )->GetSampler() ) );
}
else if( renderProgManager.BindingLayoutType() == BINDING_LAYOUT_GBUFFER )
{
bindingSetDesc
.addItem( nvrhi::BindingSetItem::ConstantBuffer( 0, renderProgManager.ConstantBuffer() ) );
}
else if( renderProgManager.BindingLayoutType() == BINDING_LAYOUT_LIGHTGRID )
{
bindingSetDesc
.addItem( nvrhi::BindingSetItem::ConstantBuffer( 0, renderProgManager.ConstantBuffer() ) )
.addItem( nvrhi::BindingSetItem::Texture_SRV( 0, ( nvrhi::ITexture* )GetImageAt( 0 )->GetTextureID() ) )
.addItem( nvrhi::BindingSetItem::Texture_SRV( 1, ( nvrhi::ITexture* )GetImageAt( 1 )->GetTextureID() ) )
.addItem( nvrhi::BindingSetItem::Texture_SRV( 2, ( nvrhi::ITexture* )GetImageAt( 2 )->GetTextureID() ) )
.addItem( nvrhi::BindingSetItem::Texture_SRV( 3, ( nvrhi::ITexture* )GetImageAt( 3 )->GetTextureID() ) )
.addItem( nvrhi::BindingSetItem::Texture_SRV( 4, ( nvrhi::ITexture* )GetImageAt( 4 )->GetTextureID() ) )
.addItem( nvrhi::BindingSetItem::Texture_SRV( 7, ( nvrhi::ITexture* )GetImageAt( 7 )->GetTextureID() ) )
.addItem( nvrhi::BindingSetItem::Texture_SRV( 8, ( nvrhi::ITexture* )GetImageAt( 8 )->GetTextureID() ) )
.addItem( nvrhi::BindingSetItem::Texture_SRV( 9, ( nvrhi::ITexture* )GetImageAt( 9 )->GetTextureID() ) )
.addItem( nvrhi::BindingSetItem::Texture_SRV( 10, ( nvrhi::ITexture* )GetImageAt( 10 )->GetTextureID() ) )
.addItem( nvrhi::BindingSetItem::Sampler( 0, ( nvrhi::ISampler* )GetImageAt( 0 )->GetSampler() ) )
.addItem( nvrhi::BindingSetItem::Sampler( 1, ( nvrhi::ISampler* )GetImageAt( 1 )->GetSampler() ) )
.addItem( nvrhi::BindingSetItem::Sampler( 2, ( nvrhi::ISampler* )GetImageAt( 2 )->GetSampler() ) )
.addItem( nvrhi::BindingSetItem::Sampler( 3, ( nvrhi::ISampler* )GetImageAt( 3 )->GetSampler() ) )
.addItem( nvrhi::BindingSetItem::Sampler( 4, ( nvrhi::ISampler* )GetImageAt( 4 )->GetSampler() ) )
.addItem( nvrhi::BindingSetItem::Sampler( 7, ( nvrhi::ISampler* )GetImageAt( 7 )->GetSampler() ) )
.addItem( nvrhi::BindingSetItem::Sampler( 8, ( nvrhi::ISampler* )GetImageAt( 8 )->GetSampler() ) )
.addItem( nvrhi::BindingSetItem::Sampler( 9, ( nvrhi::ISampler* )GetImageAt( 9 )->GetSampler() ) )
.addItem( nvrhi::BindingSetItem::Sampler( 10, ( nvrhi::ISampler* )GetImageAt( 10 )->GetSampler() ) );
}
currentBindingSet = bindingCache.GetOrCreateBindingSet( bindingSetDesc, currentBindingLayout );
renderProgManager.CommitConstantBuffer( commandList );
nvrhi::GraphicsState state;
state.bindings = { currentBindingSet };
state.indexBuffer = { currentIndexBuffer, nvrhi::Format::R16_UINT, indexOffset };
state.vertexBuffers = { { currentVertexBuffer, 0, vertOffset } };
state.pipeline = currentPipeline;
state.framebuffer = currentFrameBuffer->GetApiObject();
// TODO(Stephen): use currentViewport instead.
nvrhi::Viewport viewport;
viewport.minX = currentViewport.x1;
viewport.minY = currentViewport.y1;
viewport.maxX = currentViewport.x2;
viewport.maxY = currentViewport.y2;
viewport.minZ = currentViewport.zmin;
viewport.maxZ = currentViewport.zmax;
state.viewport.addViewportAndScissorRect( viewport );
state.viewport.addScissorRect( nvrhi::Rect( currentScissor.x1, currentScissor.y1, currentScissor.x2, currentScissor.y2 ) );
commandList->setGraphicsState( state );
nvrhi::DrawArguments args;
args.vertexCount = surf->numIndexes;
commandList->drawIndexed( args );
// RB: added stats
pc.c_drawElements++;
pc.c_drawIndexes += surf->numIndexes;
}
#endif
void GBufferFillPass::SetupView( nvrhi::ICommandList* commandList, viewDef_t* viewDef )
{
}
bool GBufferFillPass::SetupMaterial( const idMaterial* material, nvrhi::RasterCullMode cullMode, nvrhi::GraphicsState& state )
{
return false;
}
void GBufferFillPass::SetupInputBuffers( const drawSurf_t* drawSurf, nvrhi::GraphicsState& state )
{
}
void GBufferFillPass::SetPushConstants( nvrhi::ICommandList* commandList, nvrhi::GraphicsState& state, nvrhi::DrawArguments& args )
{
}
#endif

View file

@ -1,68 +0,0 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 2022 Stephen Pridham
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef RENDERER_PASSES_GBUFFERFILLPASS_H_
#define RENDERER_PASSES_GBUFFERFILLPASS_H_
#include "GeometryPasses.h"
#if 0
// "Light" G-Buffer that renders the normals of the geometry
class GBufferFillPass : IGeometryPass
{
public:
GBufferFillPass() = default;
virtual ~GBufferFillPass() = default;
void Init( nvrhi::DeviceHandle deviceHandle );
void RenderView( nvrhi::ICommandList* commandList, const drawSurf_t* const* drawSurfs, int numDrawSurfs, bool fillGbuffer );
protected:
nvrhi::DeviceHandle device;
nvrhi::BindingLayoutHandle geometryBindingLayout;
nvrhi::BindingLayoutHandle texturedBindingLayout;
nvrhi::BindingSetDesc geometryBindingSetDesc;
nvrhi::GraphicsPipelineHandle CreateGraphicsPipeline( nvrhi::IFramebuffer* framebuffer );
void DrawElementsWithCounters( const drawSurf_t* surf );
public:
void SetupView( nvrhi::ICommandList* commandList, viewDef_t* viewDef ) override;
bool SetupMaterial( const idMaterial* material, nvrhi::RasterCullMode cullMode, nvrhi::GraphicsState& state ) override;
void SetupInputBuffers( const drawSurf_t* drawSurf, nvrhi::GraphicsState& state ) override;
void SetPushConstants( nvrhi::ICommandList* commandList, nvrhi::GraphicsState& state, nvrhi::DrawArguments& args ) override;
};
#endif
#endif

View file

@ -1,799 +0,0 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 2022 Stephen Pridham
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include <precompiled.h>
#pragma hdrstop
#include "renderer/RenderCommon.h"
#include "GeometryPasses.h"
#include "nvrhi/utils.h"
#if 0
static ID_INLINE void SetVertexParm( renderParm_t rp, const float* value )
{
renderProgManager.SetUniformValue( rp, value );
}
static ID_INLINE void SetVertexParms( renderParm_t rp, const float* value, int num )
{
for( int i = 0; i < num; i++ )
{
renderProgManager.SetUniformValue( ( renderParm_t )( rp + i ), value + ( i * 4 ) );
}
}
static ID_INLINE void SetFragmentParm( renderParm_t rp, const float* value )
{
renderProgManager.SetUniformValue( rp, value );
}
static void RB_GetShaderTextureMatrix( const float* shaderRegisters, const textureStage_t* texture, float matrix[16] )
{
matrix[0 * 4 + 0] = shaderRegisters[texture->matrix[0][0]];
matrix[1 * 4 + 0] = shaderRegisters[texture->matrix[0][1]];
matrix[2 * 4 + 0] = 0.0f;
matrix[3 * 4 + 0] = shaderRegisters[texture->matrix[0][2]];
matrix[0 * 4 + 1] = shaderRegisters[texture->matrix[1][0]];
matrix[1 * 4 + 1] = shaderRegisters[texture->matrix[1][1]];
matrix[2 * 4 + 1] = 0.0f;
matrix[3 * 4 + 1] = shaderRegisters[texture->matrix[1][2]];
// we attempt to keep scrolls from generating incredibly large texture values, but
// center rotations and center scales can still generate offsets that need to be > 1
if( matrix[3 * 4 + 0] < -40.0f || matrix[12] > 40.0f )
{
matrix[3 * 4 + 0] -= ( int )matrix[3 * 4 + 0];
}
if( matrix[13] < -40.0f || matrix[13] > 40.0f )
{
matrix[13] -= ( int )matrix[13];
}
matrix[0 * 4 + 2] = 0.0f;
matrix[1 * 4 + 2] = 0.0f;
matrix[2 * 4 + 2] = 1.0f;
matrix[3 * 4 + 2] = 0.0f;
matrix[0 * 4 + 3] = 0.0f;
matrix[1 * 4 + 3] = 0.0f;
matrix[2 * 4 + 3] = 0.0f;
matrix[3 * 4 + 3] = 1.0f;
}
static void RB_LoadShaderTextureMatrix( const float* shaderRegisters, const textureStage_t* texture )
{
float texS[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
float texT[4] = { 0.0f, 1.0f, 0.0f, 0.0f };
if( texture->hasMatrix )
{
float matrix[16];
RB_GetShaderTextureMatrix( shaderRegisters, texture, matrix );
texS[0] = matrix[0 * 4 + 0];
texS[1] = matrix[1 * 4 + 0];
texS[2] = matrix[2 * 4 + 0];
texS[3] = matrix[3 * 4 + 0];
texT[0] = matrix[0 * 4 + 1];
texT[1] = matrix[1 * 4 + 1];
texT[2] = matrix[2 * 4 + 1];
texT[3] = matrix[3 * 4 + 1];
}
SetVertexParm( RENDERPARM_TEXTUREMATRIX_S, texS );
SetVertexParm( RENDERPARM_TEXTUREMATRIX_T, texT );
}
void IGeometryPass::PrepareStageTexturing( const shaderStage_t* pStage, const drawSurf_t* surf )
{
float useTexGenParm[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
// set the texture matrix if needed
RB_LoadShaderTextureMatrix( surf->shaderRegisters, &pStage->texture );
// texgens
if( pStage->texture.texgen == TG_REFLECT_CUBE )
{
// see if there is also a bump map specified
const shaderStage_t* bumpStage = surf->material->GetBumpStage();
if( bumpStage != NULL )
{
// per-pixel reflection mapping with bump mapping
GL_SelectTexture( 1 );
bumpStage->texture.image->Bind();
GL_SelectTexture( 0 );
RENDERLOG_PRINTF( "TexGen: TG_REFLECT_CUBE: Bumpy Environment\n" );
if( surf->jointCache )
{
renderProgManager.BindShader_BumpyEnvironmentSkinned();
}
else
{
renderProgManager.BindShader_BumpyEnvironment();
}
}
else
{
RENDERLOG_PRINTF( "TexGen: TG_REFLECT_CUBE: Environment\n" );
if( surf->jointCache )
{
renderProgManager.BindShader_EnvironmentSkinned();
}
else
{
renderProgManager.BindShader_Environment();
}
}
}
else if( pStage->texture.texgen == TG_SKYBOX_CUBE )
{
renderProgManager.BindShader_SkyBox();
}
else if( pStage->texture.texgen == TG_WOBBLESKY_CUBE )
{
const int* parms = surf->material->GetTexGenRegisters();
float wobbleDegrees = surf->shaderRegisters[parms[0]] * ( idMath::PI / 180.0f );
float wobbleSpeed = surf->shaderRegisters[parms[1]] * ( 2.0f * idMath::PI / 60.0f );
float rotateSpeed = surf->shaderRegisters[parms[2]] * ( 2.0f * idMath::PI / 60.0f );
idVec3 axis[3];
{
// very ad-hoc "wobble" transform
float s, c;
idMath::SinCos( wobbleSpeed * viewDef->renderView.time[0] * 0.001f, s, c );
float ws, wc;
idMath::SinCos( wobbleDegrees, ws, wc );
axis[2][0] = ws * c;
axis[2][1] = ws * s;
axis[2][2] = wc;
axis[1][0] = -s * s * ws;
axis[1][2] = -s * ws * ws;
axis[1][1] = idMath::Sqrt( idMath::Fabs( 1.0f - ( axis[1][0] * axis[1][0] + axis[1][2] * axis[1][2] ) ) );
// make the second vector exactly perpendicular to the first
axis[1] -= ( axis[2] * axis[1] ) * axis[2];
axis[1].Normalize();
// construct the third with a cross
axis[0].Cross( axis[1], axis[2] );
}
// add the rotate
float rs, rc;
idMath::SinCos( rotateSpeed * viewDef->renderView.time[0] * 0.001f, rs, rc );
float transform[12];
transform[0 * 4 + 0] = axis[0][0] * rc + axis[1][0] * rs;
transform[0 * 4 + 1] = axis[0][1] * rc + axis[1][1] * rs;
transform[0 * 4 + 2] = axis[0][2] * rc + axis[1][2] * rs;
transform[0 * 4 + 3] = 0.0f;
transform[1 * 4 + 0] = axis[1][0] * rc - axis[0][0] * rs;
transform[1 * 4 + 1] = axis[1][1] * rc - axis[0][1] * rs;
transform[1 * 4 + 2] = axis[1][2] * rc - axis[0][2] * rs;
transform[1 * 4 + 3] = 0.0f;
transform[2 * 4 + 0] = axis[2][0];
transform[2 * 4 + 1] = axis[2][1];
transform[2 * 4 + 2] = axis[2][2];
transform[2 * 4 + 3] = 0.0f;
SetVertexParms( RENDERPARM_WOBBLESKY_X, transform, 3 );
renderProgManager.BindShader_WobbleSky();
}
else if( ( pStage->texture.texgen == TG_SCREEN ) || ( pStage->texture.texgen == TG_SCREEN2 ) )
{
useTexGenParm[0] = 1.0f;
useTexGenParm[1] = 1.0f;
useTexGenParm[2] = 1.0f;
useTexGenParm[3] = 1.0f;
float mat[16];
R_MatrixMultiply( surf->space->modelViewMatrix, viewDef->projectionMatrix, mat );
RENDERLOG_PRINTF( "TexGen : %s\n", ( pStage->texture.texgen == TG_SCREEN ) ? "TG_SCREEN" : "TG_SCREEN2" );
renderLog.Indent();
float plane[4];
plane[0] = mat[0 * 4 + 0];
plane[1] = mat[1 * 4 + 0];
plane[2] = mat[2 * 4 + 0];
plane[3] = mat[3 * 4 + 0];
SetVertexParm( RENDERPARM_TEXGEN_0_S, plane );
RENDERLOG_PRINTF( "TEXGEN_S = %4.3f, %4.3f, %4.3f, %4.3f\n", plane[0], plane[1], plane[2], plane[3] );
plane[0] = mat[0 * 4 + 1];
plane[1] = mat[1 * 4 + 1];
plane[2] = mat[2 * 4 + 1];
plane[3] = mat[3 * 4 + 1];
SetVertexParm( RENDERPARM_TEXGEN_0_T, plane );
RENDERLOG_PRINTF( "TEXGEN_T = %4.3f, %4.3f, %4.3f, %4.3f\n", plane[0], plane[1], plane[2], plane[3] );
plane[0] = mat[0 * 4 + 3];
plane[1] = mat[1 * 4 + 3];
plane[2] = mat[2 * 4 + 3];
plane[3] = mat[3 * 4 + 3];
SetVertexParm( RENDERPARM_TEXGEN_0_Q, plane );
RENDERLOG_PRINTF( "TEXGEN_Q = %4.3f, %4.3f, %4.3f, %4.3f\n", plane[0], plane[1], plane[2], plane[3] );
renderLog.Outdent();
}
else if( pStage->texture.texgen == TG_DIFFUSE_CUBE )
{
// As far as I can tell, this is never used
idLib::Warning( "Using Diffuse Cube! Please contact Brian!" );
}
else if( pStage->texture.texgen == TG_GLASSWARP )
{
// As far as I can tell, this is never used
idLib::Warning( "Using GlassWarp! Please contact Brian!" );
}
SetVertexParm( RENDERPARM_TEXGEN_0_ENABLED, useTexGenParm );
}
void IGeometryPass::FinishStageTexturing( const shaderStage_t* stage, const drawSurf_t* surf )
{
if( stage->texture.cinematic )
{
// unbind the extra bink textures
GL_SelectTexture( 0 );
}
if( stage->texture.texgen == TG_REFLECT_CUBE )
{
// see if there is also a bump map specified
const shaderStage_t* bumpStage = surf->material->GetBumpStage();
if( bumpStage != NULL )
{
// per-pixel reflection mapping with bump mapping
GL_SelectTexture( 0 );
}
else
{
// per-pixel reflection mapping without bump mapping
}
renderProgManager.Unbind();
}
}
bool IGeometryPass::GL_State( uint64 stateBits, bool forceGlState )
{
uint64 diff = stateBits ^ glStateBits;
if( !r_useStateCaching.GetBool() || forceGlState )
{
// make sure everything is set all the time, so we
// can see if our delta checking is screwing up
diff = 0xFFFFFFFFFFFFFFFF;
}
else if( diff == 0 )
{
return false;
}
// Reset pipeline
auto& currentBlendState = pipelineDesc.renderState.blendState;
auto& currentDepthStencilState = pipelineDesc.renderState.depthStencilState;
auto& currentRasterState = pipelineDesc.renderState.rasterState;
//
// culling
//
if( diff & ( GLS_CULL_BITS ) )//| GLS_MIRROR_VIEW ) )
{
switch( stateBits & GLS_CULL_BITS )
{
case GLS_CULL_TWOSIDED:
currentRasterState.setCullNone();
break;
case GLS_CULL_BACKSIDED:
if( viewDef != NULL && viewDef->isMirror )
{
stateBits |= GLS_MIRROR_VIEW;
currentRasterState.setCullFront();
}
else
{
currentRasterState.setCullBack();
}
break;
case GLS_CULL_FRONTSIDED:
default:
if( viewDef != NULL && viewDef->isMirror )
{
stateBits |= GLS_MIRROR_VIEW;
currentRasterState.setCullBack();
}
else
{
currentRasterState.setCullFront();
}
break;
}
}
//
// check depthFunc bits
//
if( diff & GLS_DEPTHFUNC_BITS )
{
switch( stateBits & GLS_DEPTHFUNC_BITS )
{
case GLS_DEPTHFUNC_EQUAL:
currentDepthStencilState.depthFunc = nvrhi::ComparisonFunc::Equal;
break;
case GLS_DEPTHFUNC_ALWAYS:
currentDepthStencilState.depthFunc = nvrhi::ComparisonFunc::Always;
break;
case GLS_DEPTHFUNC_LESS:
currentDepthStencilState.depthFunc = nvrhi::ComparisonFunc::Less;
break;
case GLS_DEPTHFUNC_GREATER:
currentDepthStencilState.depthFunc = nvrhi::ComparisonFunc::Greater;
break;
}
}
nvrhi::BlendState::RenderTarget renderTarget;
//
// check blend bits
//
if( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
{
nvrhi::BlendFactor srcFactor = nvrhi::BlendFactor::One;
nvrhi::BlendFactor dstFactor = nvrhi::BlendFactor::One;
switch( stateBits & GLS_SRCBLEND_BITS )
{
case GLS_SRCBLEND_ZERO:
srcFactor = nvrhi::BlendFactor::Zero;
break;
case GLS_SRCBLEND_ONE:
srcFactor = nvrhi::BlendFactor::One;
break;
case GLS_SRCBLEND_DST_COLOR:
srcFactor = nvrhi::BlendFactor::DstColor;
break;
case GLS_SRCBLEND_ONE_MINUS_DST_COLOR:
srcFactor = nvrhi::BlendFactor::OneMinusDstColor;
break;
case GLS_SRCBLEND_SRC_ALPHA:
srcFactor = nvrhi::BlendFactor::SrcAlpha;
break;
case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA:
srcFactor = nvrhi::BlendFactor::OneMinusSrcAlpha;
break;
case GLS_SRCBLEND_DST_ALPHA:
srcFactor = nvrhi::BlendFactor::DstAlpha;
break;
case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA:
srcFactor = nvrhi::BlendFactor::OneMinusDstAlpha;
break;
default:
assert( !"GL_State: invalid src blend state bits\n" );
break;
}
switch( stateBits & GLS_DSTBLEND_BITS )
{
case GLS_DSTBLEND_ZERO:
dstFactor = nvrhi::BlendFactor::Zero;
break;
case GLS_DSTBLEND_ONE:
dstFactor = nvrhi::BlendFactor::One;
break;
case GLS_DSTBLEND_SRC_COLOR:
dstFactor = nvrhi::BlendFactor::SrcColor;
break;
case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR:
dstFactor = nvrhi::BlendFactor::OneMinusSrcColor;
break;
case GLS_DSTBLEND_SRC_ALPHA:
dstFactor = nvrhi::BlendFactor::SrcAlpha;
break;
case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA:
dstFactor = nvrhi::BlendFactor::OneMinusSrcAlpha;
break;
case GLS_DSTBLEND_DST_ALPHA:
dstFactor = nvrhi::BlendFactor::DstAlpha;
break;
case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA:
dstFactor = nvrhi::BlendFactor::OneMinusDstAlpha;
break;
default:
assert( !"GL_State: invalid dst blend state bits\n" );
break;
}
// Only actually update GL's blend func if blending is enabled.
if( srcFactor == nvrhi::BlendFactor::One && dstFactor == nvrhi::BlendFactor::Zero )
{
renderTarget.disableBlend();
}
else
{
currentBlendState.setAlphaToCoverageEnable( true );
nvrhi::BlendState::RenderTarget renderTarget;
renderTarget.enableBlend();
renderTarget.setSrcBlend( srcFactor );
renderTarget.setDestBlend( dstFactor );
}
}
//
// check depthmask
//
if( diff & GLS_DEPTHMASK )
{
if( stateBits & GLS_DEPTHMASK )
{
currentDepthStencilState.disableDepthWrite();
currentDepthStencilState.disableDepthTest();
}
else
{
currentDepthStencilState.enableDepthWrite();
currentDepthStencilState.enableDepthTest();
}
}
//
// check colormask
//
if( diff & ( GLS_REDMASK | GLS_GREENMASK | GLS_BLUEMASK | GLS_ALPHAMASK ) )
{
nvrhi::ColorMask mask{ nvrhi::ColorMask::All };
if( stateBits & GLS_REDMASK )
{
mask = mask & ~nvrhi::ColorMask::Red;
}
if( stateBits & GLS_GREENMASK )
{
mask = mask & ~nvrhi::ColorMask::Green;
}
if( stateBits & GLS_BLUEMASK )
{
mask = mask & ~nvrhi::ColorMask::Blue;
}
if( stateBits & GLS_ALPHAMASK )
{
mask = mask & ~nvrhi::ColorMask::Alpha;
}
renderTarget.setColorWriteMask( mask );
}
currentBlendState.setRenderTarget( 0, renderTarget );
//
// fill/line mode
//
if( diff & GLS_POLYMODE_LINE )
{
if( stateBits & GLS_POLYMODE_LINE )
{
currentRasterState.setFillMode( nvrhi::RasterFillMode::Line );
currentRasterState.setCullNone();
}
else
{
currentRasterState.setCullNone();
currentRasterState.setFillMode( nvrhi::RasterFillMode::Fill );
}
}
//
// polygon offset
//
if( diff & GLS_POLYGON_OFFSET )
{
if( stateBits & GLS_POLYGON_OFFSET )
{
currentRasterState.enableQuadFill();
}
else
{
currentRasterState.disableQuadFill();
}
}
nvrhi::DepthStencilState::StencilOpDesc stencilOp;
//
// stencil
//
if( diff & ( GLS_STENCIL_FUNC_BITS | GLS_STENCIL_OP_BITS ) )
{
if( ( stateBits & ( GLS_STENCIL_FUNC_BITS | GLS_STENCIL_OP_BITS ) ) != 0 )
{
currentDepthStencilState.enableStencil();
currentDepthStencilState.enableDepthWrite();
}
else
{
currentDepthStencilState.disableStencil();
//currentDepthStencilState.disableDepthWrite();
}
}
if( diff & ( GLS_STENCIL_FUNC_BITS | GLS_STENCIL_FUNC_REF_BITS | GLS_STENCIL_FUNC_MASK_BITS ) )
{
GLuint ref = GLuint( ( stateBits & GLS_STENCIL_FUNC_REF_BITS ) >> GLS_STENCIL_FUNC_REF_SHIFT );
GLuint mask = GLuint( ( stateBits & GLS_STENCIL_FUNC_MASK_BITS ) >> GLS_STENCIL_FUNC_MASK_SHIFT );
GLenum func = 0;
currentDepthStencilState.setStencilRefValue( ( stateBits & GLS_STENCIL_FUNC_REF_BITS ) >> GLS_STENCIL_FUNC_REF_SHIFT );
currentDepthStencilState.setStencilReadMask( ( stateBits & GLS_STENCIL_FUNC_MASK_BITS ) >> GLS_STENCIL_FUNC_MASK_SHIFT );
currentDepthStencilState.setStencilWriteMask( ( stateBits & GLS_STENCIL_FUNC_MASK_BITS ) >> GLS_STENCIL_FUNC_MASK_SHIFT );
switch( stateBits & GLS_STENCIL_FUNC_BITS )
{
case GLS_STENCIL_FUNC_NEVER:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::Never );
break;
case GLS_STENCIL_FUNC_LESS:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::Less );
break;
case GLS_STENCIL_FUNC_EQUAL:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::Equal );
break;
case GLS_STENCIL_FUNC_LEQUAL:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::LessOrEqual );
break;
case GLS_STENCIL_FUNC_GREATER:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::Greater );
break;
case GLS_STENCIL_FUNC_NOTEQUAL:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::NotEqual );
break;
case GLS_STENCIL_FUNC_GEQUAL:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::GreaterOrEqual );
break;
case GLS_STENCIL_FUNC_ALWAYS:
stencilOp.setStencilFunc( nvrhi::ComparisonFunc::Always );
break;
}
}
if( diff & ( GLS_STENCIL_OP_FAIL_BITS | GLS_STENCIL_OP_ZFAIL_BITS | GLS_STENCIL_OP_PASS_BITS ) )
{
GLenum sFail = 0;
GLenum zFail = 0;
GLenum pass = 0;
switch( stateBits & GLS_STENCIL_OP_FAIL_BITS )
{
case GLS_STENCIL_OP_FAIL_KEEP:
stencilOp.setFailOp( nvrhi::StencilOp::Keep );
break;
case GLS_STENCIL_OP_FAIL_ZERO:
stencilOp.setFailOp( nvrhi::StencilOp::Zero );
break;
case GLS_STENCIL_OP_FAIL_REPLACE:
stencilOp.setFailOp( nvrhi::StencilOp::Replace );
break;
case GLS_STENCIL_OP_FAIL_INCR:
stencilOp.setFailOp( nvrhi::StencilOp::IncrementAndClamp );
break;
case GLS_STENCIL_OP_FAIL_DECR:
stencilOp.setFailOp( nvrhi::StencilOp::DecrementAndClamp );
break;
case GLS_STENCIL_OP_FAIL_INVERT:
stencilOp.setFailOp( nvrhi::StencilOp::Invert );
break;
case GLS_STENCIL_OP_FAIL_INCR_WRAP:
stencilOp.setFailOp( nvrhi::StencilOp::IncrementAndWrap );
break;
case GLS_STENCIL_OP_FAIL_DECR_WRAP:
stencilOp.setFailOp( nvrhi::StencilOp::DecrementAndWrap );
break;
}
switch( stateBits & GLS_STENCIL_OP_ZFAIL_BITS )
{
case GLS_STENCIL_OP_ZFAIL_KEEP:
stencilOp.setDepthFailOp( nvrhi::StencilOp::Keep );
break;
case GLS_STENCIL_OP_ZFAIL_ZERO:
stencilOp.setDepthFailOp( nvrhi::StencilOp::Zero );
break;
case GLS_STENCIL_OP_ZFAIL_REPLACE:
stencilOp.setDepthFailOp( nvrhi::StencilOp::Replace );
break;
case GLS_STENCIL_OP_ZFAIL_INCR:
stencilOp.setDepthFailOp( nvrhi::StencilOp::IncrementAndClamp );
break;
case GLS_STENCIL_OP_ZFAIL_DECR:
stencilOp.setDepthFailOp( nvrhi::StencilOp::DecrementAndClamp );
break;
case GLS_STENCIL_OP_ZFAIL_INVERT:
stencilOp.setDepthFailOp( nvrhi::StencilOp::Invert );
break;
case GLS_STENCIL_OP_ZFAIL_INCR_WRAP:
stencilOp.setDepthFailOp( nvrhi::StencilOp::IncrementAndWrap );
break;
case GLS_STENCIL_OP_ZFAIL_DECR_WRAP:
stencilOp.setDepthFailOp( nvrhi::StencilOp::DecrementAndWrap );
break;
}
switch( stateBits & GLS_STENCIL_OP_PASS_BITS )
{
case GLS_STENCIL_OP_PASS_KEEP:
stencilOp.setPassOp( nvrhi::StencilOp::Keep );
break;
case GLS_STENCIL_OP_PASS_ZERO:
stencilOp.setPassOp( nvrhi::StencilOp::Zero );
break;
case GLS_STENCIL_OP_PASS_REPLACE:
stencilOp.setPassOp( nvrhi::StencilOp::Replace );
break;
case GLS_STENCIL_OP_PASS_INCR:
stencilOp.setPassOp( nvrhi::StencilOp::IncrementAndClamp );
break;
case GLS_STENCIL_OP_PASS_DECR:
stencilOp.setPassOp( nvrhi::StencilOp::DecrementAndClamp );
break;
case GLS_STENCIL_OP_PASS_INVERT:
stencilOp.setPassOp( nvrhi::StencilOp::Invert );
break;
case GLS_STENCIL_OP_PASS_INCR_WRAP:
stencilOp.setPassOp( nvrhi::StencilOp::IncrementAndWrap );
break;
case GLS_STENCIL_OP_PASS_DECR_WRAP:
stencilOp.setPassOp( nvrhi::StencilOp::DecrementAndWrap );
break;
}
}
currentDepthStencilState.setFrontFaceStencil( stencilOp );
glStateBits = stateBits;
pipeline = nullptr;
}
void IGeometryPass::GL_SelectTexture( int imageParm )
{
currentImageParm = imageParm;
}
void IGeometryPass::GL_BindTexture( idImage* img )
{
imageParms[currentImageParm] = img;
}
void IGeometryPass::GL_BindFramebuffer( Framebuffer* framebuffer )
{
if( currentFramebuffer != framebuffer )
{
previousFramebuffer = currentFramebuffer;
pipeline = nullptr;
}
currentFramebuffer = framebuffer;
}
void IGeometryPass::GL_BindGraphicsShader( int shaderIndex )
{
nvrhi::ShaderHandle shader = renderProgManager.GetShader( shaderIndex );
if( shader->getDesc().shaderType == nvrhi::ShaderType::Vertex )
{
if( pipelineDesc.VS != shader )
{
pipeline = nullptr;
}
pipelineDesc.setVertexShader( shader );
}
if( shader->getDesc().shaderType == nvrhi::ShaderType::Pixel )
{
if( pipelineDesc.PS != shader )
{
pipeline = nullptr;
}
pipelineDesc.setPixelShader( shader );
}
}
void IGeometryPass::GL_DepthBoundsTest( const float zmin, const float zmax )
{
}
void IGeometryPass::GL_PolygonOffset( float scale, float bias )
{
pipelineDesc.renderState.rasterState.setSlopeScaleDepthBias( scale ).setDepthBias( bias );
pipeline = nullptr;
}
void IGeometryPass::GL_Viewport( int x, int y, int w, int h )
{
currentViewport.Clear();
currentViewport.AddPoint( x, y );
currentViewport.AddPoint( x + w, y + h );
}
void IGeometryPass::GL_Scissor( int x, int y, int w, int h )
{
currentScissor.Clear();
currentScissor.AddPoint( x, y );
currentScissor.AddPoint( x + w, y + h );
}
void IGeometryPass::GL_Color( const idVec4 color )
{
// TODO(Stephen): Hold local copy and then set in a constant buffer later.
float parm[4];
parm[0] = idMath::ClampFloat( 0.0f, 1.0f, color.x );
parm[1] = idMath::ClampFloat( 0.0f, 1.0f, color.y );
parm[2] = idMath::ClampFloat( 0.0f, 1.0f, color.z );
parm[3] = idMath::ClampFloat( 0.0f, 1.0f, color.w );
renderProgManager.SetRenderParm( RENDERPARM_COLOR, parm );
}
void IGeometryPass::GL_ClearColor( const idVec4 color )
{
clearColor = color;
}
void IGeometryPass::GL_ClearDepthStencilValue( float depthValue, byte stencilValue )
{
depthClearValue = depthValue;
stencilClearValue = stencilValue;
}
void IGeometryPass::GL_ClearColor( nvrhi::ICommandList* commandList, int attachmentIndex )
{
nvrhi::utils::ClearColorAttachment(
commandList,
currentFramebuffer->GetApiObject(),
attachmentIndex,
nvrhi::Color( clearColor.x, clearColor.y, clearColor.z, clearColor.w ) );
}
void IGeometryPass::GL_ClearDepthStencil( nvrhi::ICommandList* commandList )
{
nvrhi::utils::ClearDepthStencilAttachment( commandList, currentFramebuffer->GetApiObject(), depthClearValue, stencilClearValue );
}
#endif

View file

@ -1,99 +0,0 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 2022 Stephen Pridham
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code 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 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef RENDERER_PASSES_GEOMETRYPASSES_H_
#define RENDERER_PASSES_GEOMETRYPASSES_H_
constexpr std::size_t MAX_IMAGE_PARMS = 16;
#if 0
class IGeometryPass
{
public:
virtual ~IGeometryPass() = default;
virtual void SetupView( nvrhi::ICommandList* commandList, viewDef_t* viewDef ) = 0;
virtual bool SetupMaterial( const idMaterial* material, nvrhi::RasterCullMode cullMode, nvrhi::GraphicsState& state ) = 0;
virtual void SetupInputBuffers( const drawSurf_t* drawSurf, nvrhi::GraphicsState& state ) = 0;
virtual void SetPushConstants( nvrhi::ICommandList* commandList, nvrhi::GraphicsState& state, nvrhi::DrawArguments& args ) = 0;
protected:
void PrepareStageTexturing( const shaderStage_t* stage, const drawSurf_t* surf );
void FinishStageTexturing( const shaderStage_t* stage, const drawSurf_t* surf );
protected:
int currentImageParm = 0;
idArray< idImage*, MAX_IMAGE_PARMS > imageParms;
uint64 glStateBits;
nvrhi::GraphicsPipelineDesc pipelineDesc;
nvrhi::GraphicsPipelineHandle pipeline;
BindingCache bindingCache;
Framebuffer* previousFramebuffer;
Framebuffer* currentFramebuffer;
Framebuffer* lastFramebuffer;
const viewDef_t* viewDef;
const viewEntity_t* currentSpace;
idScreenRect currentViewport;
idScreenRect currentScissor;
idVec4 clearColor;
float depthClearValue;
byte stencilClearValue;
// Updates state to bits in stateBits. Only updates the different bits.
bool GL_State( uint64 stateBits, bool forceGlState = false );
void GL_SelectTexture( int textureNum );
void GL_BindTexture( idImage* img );
void GL_BindFramebuffer( Framebuffer* framebuffer );
void GL_BindGraphicsShader( int shader );
void GL_DepthBoundsTest( const float zmin, const float zmax );
void GL_PolygonOffset( float scale, float bias );
void GL_Viewport( int x, int y, int w, int h );
void GL_Scissor( int x, int y, int w, int h );
void GL_Color( const idVec4 color );
void GL_ClearColor( const idVec4 color );
void GL_ClearDepthStencilValue( float depthValue, byte stencilValue = 0xF );
void GL_ClearColor( nvrhi::ICommandList* commandList, int attachmentIndex = 0 );
void GL_ClearDepthStencil( nvrhi::ICommandList* commandList );
ID_INLINE uint64 GL_GetCurrentState() const
{
return glStateBits;
}
ID_INLINE void GL_ViewportAndScissor( int x, int y, int w, int h )
{
GL_Viewport( x, y, w, h );
GL_Scissor( x, y, w, h );
}
};
#endif
#endif

View file

@ -36,7 +36,6 @@ If you have questions concerning this license or the applicable additional terms
#include "Passes/CommonPasses.h"
#include "Passes/MipMapGenPass.h"
#include "Passes/FowardShadingPass.h"
#include "Passes/SsaoPass.h"
#include "Passes/TonemapPass.h"
#include "Passes/TemporalAntiAliasingPass.h"