Skip to content

Commit bf333c6

Browse files
committed
Fix portal surface blending, entity selection and recursive chains with mirrors
Fixes portal blending with portal surfaces, misc_portal_surface entity selection and GL_FrontFace for mirrors in chains of recursive portals/mirrors. Fixes #1011. Disables the 64qu distance limit for portal entities which wasn't working properly anyway. We only need to render one stage for portal surfaces in depth and stencil passes, so render the first one available in Tess_StageIteratorPortal(). Don't compute color and texMatrices since we don't use those at this stage.
1 parent 83a165d commit bf333c6

File tree

4 files changed

+113
-28
lines changed

4 files changed

+113
-28
lines changed

src/engine/renderer/tr_backend.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ void GL_PolygonOffset( float factor, float units )
386386

387387
void GL_Cull( cullType_t cullType )
388388
{
389-
if ( backEnd.viewParms.isMirror )
389+
if ( backEnd.viewParms.mirrorLevel % 2 == 1 )
390390
{
391391
GL_FrontFace( GL_CW );
392392
}
@@ -5543,7 +5543,7 @@ const RenderCommand *PreparePortalCommand::ExecuteSelf( ) const
55435543
GL_State( GLS_COLORMASK_BITS );
55445544
glState.glStateBitsMask = GLS_COLORMASK_BITS;
55455545

5546-
Tess_Begin( Tess_StageIteratorGeneric, nullptr, shader,
5546+
Tess_Begin( Tess_StageIteratorPortal, nullptr, shader,
55475547
nullptr, false, false, -1, -1 );
55485548
rb_surfaceTable[Util::ordinal(*(surface->surface))](surface->surface );
55495549
Tess_End();
@@ -5556,10 +5556,10 @@ const RenderCommand *PreparePortalCommand::ExecuteSelf( ) const
55565556
glStencilFunc( GL_EQUAL, backEnd.viewParms.portalLevel + 1, 0xff );
55575557
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
55585558

5559-
GL_State( GLS_DEPTHMASK_TRUE | GLS_DEPTHTEST_DISABLE | GLS_COLORMASK_BITS );
5560-
glState.glStateBitsMask = GLS_DEPTHMASK_TRUE | GLS_DEPTHTEST_DISABLE | GLS_COLORMASK_BITS;
5559+
GL_State( GLS_DEPTHMASK_TRUE | GLS_COLORMASK_BITS | GLS_DEPTHFUNC_ALWAYS);
5560+
glState.glStateBitsMask = GLS_DEPTHMASK_TRUE | GLS_COLORMASK_BITS | GLS_DEPTHFUNC_ALWAYS;
55615561

5562-
Tess_Begin( Tess_StageIteratorGeneric, nullptr, shader,
5562+
Tess_Begin( Tess_StageIteratorPortal, nullptr, shader,
55635563
nullptr, false, false, -1, -1 );
55645564
rb_surfaceTable[Util::ordinal(*(surface->surface))](surface->surface );
55655565
Tess_End();
@@ -5604,17 +5604,30 @@ const RenderCommand *FinalisePortalCommand::ExecuteSelf( ) const
56045604

56055605
GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix );
56065606

5607+
GL_State( GLS_DEPTHMASK_TRUE | GLS_DEPTHFUNC_ALWAYS );
5608+
glState.glStateBitsMask = GLS_DEPTHMASK_TRUE | GLS_DEPTHFUNC_ALWAYS;
5609+
56075610
glStencilFunc( GL_EQUAL, backEnd.viewParms.portalLevel + 1, 0xff );
5611+
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
5612+
5613+
Tess_Begin( Tess_StageIteratorGeneric, nullptr, shader,
5614+
nullptr, false, false, -1, -1 );
5615+
rb_surfaceTable[Util::ordinal( *( surface->surface ) )]( surface->surface );
5616+
Tess_End();
5617+
56085618
glStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
56095619

5610-
GL_State( GLS_DEPTHMASK_TRUE | GLS_DEPTHFUNC_ALWAYS | GLS_COLORMASK_BITS );
5611-
glState.glStateBitsMask = GLS_DEPTHMASK_TRUE | GLS_DEPTHFUNC_ALWAYS | GLS_COLORMASK_BITS;
5620+
GL_State( GLS_COLORMASK_BITS | GLS_DEPTHFUNC_ALWAYS);
5621+
glState.glStateBitsMask = GLS_COLORMASK_BITS | GLS_DEPTHFUNC_ALWAYS;
56125622

5613-
Tess_Begin( Tess_StageIteratorGeneric, nullptr, shader,
5623+
Tess_Begin( Tess_StageIteratorPortal, nullptr, shader,
56145624
nullptr, false, false, -1, -1 );
56155625
rb_surfaceTable[Util::ordinal(*(surface->surface))](surface->surface );
56165626
Tess_End();
56175627

5628+
glStencilFunc( GL_EQUAL, backEnd.viewParms.portalLevel, 0xff );
5629+
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
5630+
56185631
glState.glStateBitsMask = 0;
56195632

56205633
if( backEnd.viewParms.portalLevel == 0 ) {

src/engine/renderer/tr_local.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,7 @@ enum class deluxeMode_t { NONE, GRID, MAP };
16191619
vec3_t pvsOrigin; // may be different than or.origin for portals
16201620

16211621
int portalLevel; // number of portals this view is through
1622+
int mirrorLevel;
16221623
bool isMirror; // the portal is a mirror, invert the face culling
16231624

16241625
int frameSceneNum; // copied from tr.frameSceneNum
@@ -3521,6 +3522,7 @@ inline bool checkGLErrors()
35213522

35223523
void Tess_StageIteratorDebug();
35233524
void Tess_StageIteratorGeneric();
3525+
void Tess_StageIteratorPortal();
35243526
void Tess_StageIteratorDepthFill();
35253527
void Tess_StageIteratorShadowFill();
35263528
void Tess_StageIteratorLighting();

src/engine/renderer/tr_main.cpp

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,28 +1301,39 @@ static bool R_GetPortalOrientations( drawSurf_t *drawSurf, orientation_t *surfac
13011301
// locate the portal entity closest to this plane.
13021302
// origin will be the origin of the portal, origin2 will be
13031303
// the origin of the camera
1304-
for ( i = 0; i < tr.refdef.numEntities; i++ )
1305-
{
1306-
e = &tr.refdef.entities[ i ];
1307-
1308-
if ( e->e.reType != refEntityType_t::RT_PORTALSURFACE )
1309-
{
1304+
int numVertsOld = tess.numVertexes;
1305+
rb_surfaceTable[Util::ordinal( *( drawSurf->surface ) )]( drawSurf->surface );
1306+
int numVerts = tess.numVertexes - numVertsOld;
1307+
vec3_t portalCenter{ 0.0, 0.0, 0.0 };
1308+
for ( int vertIndex = 0; vertIndex < numVerts; vertIndex++ ) {
1309+
VectorAdd( portalCenter, tess.verts[vertIndex].xyz, portalCenter );
1310+
}
1311+
VectorScale( portalCenter, 1.0 / numVerts, portalCenter );
1312+
float minDistance = FLT_MAX;
1313+
trRefEntity_t* currentPortal = nullptr;
1314+
for ( i = 0; i < tr.refdef.numEntities; i++ ) {
1315+
e = &tr.refdef.entities[i];
1316+
1317+
if ( e->e.reType != refEntityType_t::RT_PORTALSURFACE ) {
13101318
continue;
13111319
}
13121320

1313-
d = DotProduct( e->e.origin, originalPlane.normal ) - originalPlane.dist;
1314-
1315-
if ( d > 64 || d < -64 )
1316-
{
1317-
continue;
1321+
float distance = Distance( e->e.origin, portalCenter );
1322+
if ( distance < minDistance ) {
1323+
minDistance = distance;
1324+
currentPortal = e;
13181325
}
1319-
1320-
// get the pvsOrigin from the entity
1326+
}
1327+
if( currentPortal) {
1328+
// project the origin onto the surface plane to get
1329+
// an origin point we can rotate around
1330+
e = currentPortal;
13211331
VectorCopy( e->e.oldorigin, pvsOrigin );
1332+
d = DotProduct( e->e.origin, plane.normal ) - plane.dist;
1333+
VectorMA( e->e.origin, -d, surface->axis[ 0 ], surface->origin );
13221334

13231335
// if the entity is just a mirror, don't use as a camera point
1324-
if ( e->e.oldorigin[ 0 ] == e->e.origin[ 0 ] && e->e.oldorigin[ 1 ] == e->e.origin[ 1 ] && e->e.oldorigin[ 2 ] == e->e.origin[ 2 ] )
1325-
{
1336+
if ( e->e.oldorigin[ 0 ] == e->e.origin[ 0 ] && e->e.oldorigin[ 1 ] == e->e.origin[ 1 ] && e->e.oldorigin[ 2 ] == e->e.origin[ 2 ] ) {
13261337
VectorScale( plane.normal, plane.dist, surface->origin );
13271338
VectorCopy( surface->origin, camera->origin );
13281339
VectorSubtract( vec3_origin, surface->axis[ 0 ], camera->axis[ 0 ] );
@@ -1333,11 +1344,6 @@ static bool R_GetPortalOrientations( drawSurf_t *drawSurf, orientation_t *surfac
13331344
return true;
13341345
}
13351346

1336-
// project the origin onto the surface plane to get
1337-
// an origin point we can rotate around
1338-
d = DotProduct( e->e.origin, plane.normal ) - plane.dist;
1339-
VectorMA( e->e.origin, -d, surface->axis[ 0 ], surface->origin );
1340-
13411347
// now get the camera origin and orientation
13421348
VectorCopy( e->e.oldorigin, camera->origin );
13431349
AxisCopy( e->e.axis, camera->axis );
@@ -1865,6 +1871,9 @@ static bool R_MirrorViewBySurface(drawSurf_t *drawSurf)
18651871
{
18661872
return false; // bad portal, no portalentity
18671873
}
1874+
if ( newParms.isMirror ) {
1875+
newParms.mirrorLevel++;
1876+
}
18681877

18691878
// draw stencil mask
18701879
R_AddPreparePortalCmd( drawSurf );

src/engine/renderer/tr_shade.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2876,6 +2876,67 @@ void Tess_StageIteratorGeneric()
28762876
}
28772877
}
28782878

2879+
2880+
void Tess_StageIteratorPortal() {
2881+
int stage;
2882+
2883+
// log this call
2884+
if ( r_logFile->integer ) {
2885+
// don't just call LogComment, or we will get
2886+
// a call to va() every frame!
2887+
GLimp_LogComment( va
2888+
( "--- Tess_StageIteratorPortal( %s, %i vertices, %i triangles ) ---\n", tess.surfaceShader->name,
2889+
tess.numVertexes, tess.numIndexes / 3 ) );
2890+
}
2891+
2892+
GL_CheckErrors();
2893+
2894+
if ( !glState.currentVBO || !glState.currentIBO || glState.currentVBO == tess.vbo || glState.currentIBO == tess.ibo ) {
2895+
Tess_UpdateVBOs();
2896+
}
2897+
2898+
// set face culling appropriately
2899+
if ( backEnd.currentEntity->e.renderfx & RF_SWAPCULL )
2900+
GL_Cull( ReverseCull( tess.surfaceShader->cullType ) );
2901+
else
2902+
GL_Cull( tess.surfaceShader->cullType );
2903+
2904+
// call shader function
2905+
for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) {
2906+
shaderStage_t* pStage = tess.surfaceStages[stage];
2907+
2908+
if ( !pStage ) {
2909+
break;
2910+
}
2911+
2912+
if ( !RB_EvalExpression( &pStage->ifExp, 1.0 ) ) {
2913+
continue;
2914+
}
2915+
2916+
switch ( pStage->type ) {
2917+
case stageType_t::ST_COLORMAP:
2918+
case stageType_t::ST_LIGHTMAP:
2919+
case stageType_t::ST_DIFFUSEMAP:
2920+
case stageType_t::ST_COLLAPSE_lighting_PHONG:
2921+
case stageType_t::ST_COLLAPSE_lighting_PBR:
2922+
case stageType_t::ST_COLLAPSE_reflection_CB:
2923+
case stageType_t::ST_REFLECTIONMAP:
2924+
case stageType_t::ST_REFRACTIONMAP:
2925+
case stageType_t::ST_DISPERSIONMAP:
2926+
case stageType_t::ST_SKYBOXMAP:
2927+
case stageType_t::ST_SCREENMAP:
2928+
case stageType_t::ST_PORTALMAP:
2929+
case stageType_t::ST_HEATHAZEMAP:
2930+
case stageType_t::ST_LIQUIDMAP:
2931+
Render_generic( pStage );
2932+
return;
2933+
2934+
default:
2935+
break;
2936+
}
2937+
}
2938+
}
2939+
28792940
void Tess_StageIteratorDepthFill()
28802941
{
28812942
int stage;

0 commit comments

Comments
 (0)