2021-03-15 17:55:56 +00:00
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2000-2018 Christoph Oelckers
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
2021-04-02 16:22:54 +00:00
// the Free Software Foundation, either version 2 of the License, or
2021-03-15 17:55:56 +00:00
// (at your option) any later version.
//
// This program 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
/*
* * gl_drawinfo . cpp
* * Basic scene draw info management class
* *
*/
# include "hw_portal.h"
# include "build.h"
# include "hw_renderstate.h"
# include "hw_drawinfo.h"
2022-09-30 14:25:21 +00:00
# include "models/modeldata.h"
2021-03-15 17:55:56 +00:00
# include "hw_clock.h"
# include "hw_cvars.h"
# include "hw_viewpointbuffer.h"
# include "flatvertices.h"
# include "hw_lightbuffer.h"
# include "hw_vrmodes.h"
# include "hw_clipper.h"
# include "v_draw.h"
2021-03-18 16:18:03 +00:00
# include "gamecvars.h"
2021-03-26 14:06:14 +00:00
# include "gamestruct.h"
2021-04-01 18:47:05 +00:00
# include "automap.h"
2021-04-05 11:55:36 +00:00
# include "hw_voxels.h"
2021-12-04 18:08:50 +00:00
# include "coreactor.h"
2022-12-07 16:10:27 +00:00
# include "tiletexture.h"
# include "buildtiles.h"
2021-03-15 17:55:56 +00:00
EXTERN_CVAR ( Float , r_visibility )
CVAR ( Bool , gl_no_skyclear , false , CVAR_ARCHIVE | CVAR_GLOBALCONFIG )
CVAR ( Bool , gl_texture , true , 0 )
CVAR ( Float , gl_mask_threshold , 0.5f , CVAR_ARCHIVE | CVAR_GLOBALCONFIG )
CVAR ( Float , gl_mask_sprite_threshold , 0.5f , CVAR_ARCHIVE | CVAR_GLOBALCONFIG )
2021-12-06 19:08:32 +00:00
BitArray gotsector ;
2021-04-01 18:47:05 +00:00
2021-03-15 17:55:56 +00:00
//==========================================================================
//
//
//
//==========================================================================
class FDrawInfoList
{
public :
TDeletingArray < HWDrawInfo * > mList ;
HWDrawInfo * GetNew ( ) ;
void Release ( HWDrawInfo * ) ;
} ;
FDrawInfoList di_list ;
//==========================================================================
//
// Try to reuse the lists as often as possible as they contain resources that
// are expensive to create and delete.
//
// Note: If multithreading gets used, this class needs synchronization.
//
//==========================================================================
HWDrawInfo * FDrawInfoList : : GetNew ( )
{
if ( mList . Size ( ) > 0 )
{
HWDrawInfo * di ;
mList . Pop ( di ) ;
return di ;
}
return new HWDrawInfo ( ) ;
}
void FDrawInfoList : : Release ( HWDrawInfo * di )
{
di - > ClearBuffers ( ) ;
mList . Push ( di ) ;
}
//==========================================================================
//
// Sets up a new drawinfo struct
//
//==========================================================================
HWDrawInfo * HWDrawInfo : : StartDrawInfo ( HWDrawInfo * parent , FRenderViewpoint & parentvp , HWViewpointUniforms * uniforms )
{
HWDrawInfo * di = di_list . GetNew ( ) ;
di - > StartScene ( parentvp , uniforms ) ;
return di ;
}
//==========================================================================
//
//
//
//==========================================================================
static Clipper staticClipper ; // Since all scenes are processed sequentially we only need one clipper.
static HWDrawInfo * gl_drawinfo ; // This is a linked list of all active DrawInfos and needed to free the memory arena after the last one goes out of scope.
2021-03-22 22:40:25 +00:00
void HWDrawInfo : : StartScene ( FRenderViewpoint & parentvp , HWViewpointUniforms * uniforms )
2021-03-15 17:55:56 +00:00
{
mClipper = & staticClipper ;
Viewpoint = parentvp ;
//lightmode = Level->lightMode;
if ( uniforms )
{
VPUniforms = * uniforms ;
// The clip planes will never be inherited from the parent drawinfo.
VPUniforms . mClipLine . X = - 1000001.f ;
VPUniforms . mClipHeight = 0 ;
}
else
{
VPUniforms . mProjectionMatrix . loadIdentity ( ) ;
VPUniforms . mViewMatrix . loadIdentity ( ) ;
VPUniforms . mNormalViewMatrix . loadIdentity ( ) ;
//VPUniforms.mViewHeight = viewheight;
2022-01-10 16:15:46 +00:00
VPUniforms . mGlobVis = ( 2 / 65536.f ) * ( g_visibility + g_relvisibility ) / r_ambientlight ;
VPUniforms . mPalLightLevels = numshades | ( static_cast < int > ( gl_fogmode ) < < 8 ) ;
if ( isBuildSoftwareLighting ( ) ) VPUniforms . mPalLightLevels | = ( 5 < < 16 ) ;
2021-03-15 17:55:56 +00:00
VPUniforms . mClipLine . X = - 10000000.0f ;
VPUniforms . mShadowmapFilter = gl_shadowmap_filter ;
}
ClearBuffers ( ) ;
for ( int i = 0 ; i < GLDL_TYPES ; i + + ) drawlists [ i ] . Reset ( ) ;
vpIndex = 0 ;
// Fullbright information needs to be propagated from the main view.
if ( outer ! = nullptr ) FullbrightFlags = outer - > FullbrightFlags ;
else FullbrightFlags = 0 ;
outer = gl_drawinfo ;
gl_drawinfo = this ;
}
//==========================================================================
//
//
//
//==========================================================================
HWDrawInfo * HWDrawInfo : : EndDrawInfo ( )
{
assert ( this = = gl_drawinfo ) ;
for ( int i = 0 ; i < GLDL_TYPES ; i + + ) drawlists [ i ] . Reset ( ) ;
gl_drawinfo = outer ;
di_list . Release ( this ) ;
if ( gl_drawinfo = = nullptr )
ResetRenderDataAllocator ( ) ;
return gl_drawinfo ;
}
//==========================================================================
//
//
//
//==========================================================================
void HWDrawInfo : : ClearBuffers ( )
{
spriteindex = 0 ;
mClipPortal = nullptr ;
mCurrentPortal = nullptr ;
}
//-----------------------------------------------------------------------------
//
// R_FrustumAngle
//
//-----------------------------------------------------------------------------
angle_t HWDrawInfo : : FrustumAngle ( )
{
2022-01-08 22:43:08 +00:00
float WidescreenRatio = ( float ) screen - > GetWidth ( ) / screen - > GetHeight ( ) ;
2022-08-26 16:28:22 +00:00
float tilt = fabs ( Viewpoint . HWAngles . Pitch . Degrees ( ) ) ;
2021-03-15 17:55:56 +00:00
// If the pitch is larger than this you can look all around at a FOV of 90°
if ( tilt > 46.0f ) return 0xffffffff ;
// ok, this is a gross hack that barely works...
// but at least it doesn't overestimate too much...
2022-08-26 16:28:22 +00:00
double floatangle = 2.0 + ( 45.0 + ( ( tilt / 1.9 ) ) ) * Viewpoint . FieldOfView . Degrees ( ) * 48.0 / AspectMultiplier ( WidescreenRatio ) / 90.0 ;
angle_t a1 = DAngle : : fromDeg ( floatangle ) . BAMs ( ) ;
2021-04-06 22:02:36 +00:00
if ( a1 > = ANGLE_90 ) return 0xffffffff ; // it's either below 90 or bust.
2021-03-15 17:55:56 +00:00
return a1 ;
}
//-----------------------------------------------------------------------------
//
// Setup the modelview matrix
//
//-----------------------------------------------------------------------------
void HWDrawInfo : : SetViewMatrix ( const FRotator & angles , float vx , float vy , float vz , bool mirror , bool planemirror )
{
float mult = mirror ? - 1.f : 1.f ;
float planemult = planemirror ? - 1 : 1 ; // Level->info->pixelstretch : Level->info->pixelstretch;
VPUniforms . mViewMatrix . loadIdentity ( ) ;
2022-08-26 16:28:22 +00:00
VPUniforms . mViewMatrix . rotate ( angles . Roll . Degrees ( ) , 0.0f , 0.0f , 1.0f ) ;
VPUniforms . mViewMatrix . rotate ( angles . Pitch . Degrees ( ) , 1.0f , 0.0f , 0.0f ) ;
VPUniforms . mViewMatrix . rotate ( angles . Yaw . Degrees ( ) , 0.0f , mult , 0.0f ) ;
2021-03-15 17:55:56 +00:00
VPUniforms . mViewMatrix . translate ( vx * mult , - vz * planemult , - vy ) ;
VPUniforms . mViewMatrix . scale ( - mult , planemult , 1 ) ;
}
//-----------------------------------------------------------------------------
//
// SetupView
// Setup the view rotation matrix for the given viewpoint
//
//-----------------------------------------------------------------------------
void HWDrawInfo : : SetupView ( FRenderState & state , float vx , float vy , float vz , bool mirror , bool planemirror )
{
auto & vp = Viewpoint ;
//vp.SetViewAngle(r_viewwindow); // todo: need to pass in.
SetViewMatrix ( vp . HWAngles , vx , vy , vz , mirror , planemirror ) ;
SetCameraPos ( vp . Pos ) ;
VPUniforms . CalcDependencies ( ) ;
2023-01-15 08:30:01 +00:00
VPUniforms . mLightBlendMode = 0 ;
2021-03-15 17:55:56 +00:00
vpIndex = screen - > mViewpoints - > SetViewpoint ( state , & VPUniforms ) ;
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
HWPortal * HWDrawInfo : : FindPortal ( const void * src )
{
int i = Portals . Size ( ) - 1 ;
while ( i > = 0 & & Portals [ i ] & & Portals [ i ] - > GetSource ( ) ! = src ) i - - ;
return i > = 0 ? Portals [ i ] : nullptr ;
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
2021-03-26 19:28:44 +00:00
void HWDrawInfo : : DispatchSprites ( )
{
2022-08-07 08:25:15 +00:00
for ( unsigned i = 0 ; i < tsprites . Size ( ) ; i + + )
2021-03-26 19:28:44 +00:00
{
2022-08-07 08:25:15 +00:00
auto tspr = tsprites . get ( i ) ;
2021-12-04 18:08:50 +00:00
auto actor = tspr - > ownerActor ;
2022-12-07 16:10:27 +00:00
auto texid = tspr - > spritetexture ( ) ;
2021-03-26 19:28:44 +00:00
2022-12-19 12:49:34 +00:00
if ( actor = = nullptr | | tspr - > scale . X = = 0 | | tspr - > scale . Y = = 0 | | ! texid . isValid ( ) ) continue ;
2022-12-08 17:26:09 +00:00
2021-12-21 22:18:23 +00:00
actor - > spr . cstat2 | = CSTAT2_SPRITE_MAPPED ;
2021-04-01 18:47:05 +00:00
2022-12-08 17:26:09 +00:00
if ( ! ( tspr - > cstat2 & CSTAT2_SPRITE_NOANIMATE ) )
2022-12-07 16:10:27 +00:00
{
tileUpdatePicnum ( texid , ( actor - > GetIndex ( ) & 16383 ) ) ;
}
2022-12-03 14:01:21 +00:00
if ( tspr - > cstat2 & CSTAT2_SPRITE_FULLBRIGHT )
tspr - > shade = - 127 ;
2022-12-07 16:10:27 +00:00
tspr - > picnum = legacyTileNum ( texid ) ;
int tilenum = tspr - > picnum ;
2021-03-26 19:28:44 +00:00
2022-12-08 17:26:09 +00:00
if ( ! ( actor - > sprext . renderflags & SPREXT_NOTMD ) & & ! ( tspr - > cstat2 & CSTAT2_SPRITE_NOMODEL ) )
2021-03-26 19:28:44 +00:00
{
2022-12-07 16:10:27 +00:00
auto pt = modelManager . GetModel ( tspr - > picnum , tspr - > pal ) ;
2022-09-30 14:25:21 +00:00
if ( hw_models & & pt & & pt - > modelid > = 0 & & pt - > framenum > = 0 )
2021-03-26 19:28:44 +00:00
{
//HWSprite hwsprite;
2021-04-04 11:45:43 +00:00
//if (hwsprite.ProcessModel(pt, tspr)) continue;
2021-03-26 19:28:44 +00:00
}
if ( r_voxels )
{
2022-12-08 17:26:09 +00:00
auto vox = GetExtInfo ( texid ) . tiletovox ;
if ( vox > = 0 & & voxmodels [ vox ] )
2021-03-26 19:28:44 +00:00
{
2021-04-02 16:20:07 +00:00
HWSprite hwsprite ;
2022-12-08 17:26:09 +00:00
if ( hwsprite . ProcessVoxel ( this , voxmodels [ vox ] , tspr , tspr - > sectp , voxrotate [ vox ] ) )
2021-04-04 11:45:43 +00:00
continue ;
2021-03-26 19:28:44 +00:00
}
}
}
2022-01-23 18:03:14 +00:00
if ( actor - > sprext . renderflags & SPREXT_AWAY1 )
2021-03-26 19:28:44 +00:00
{
2022-11-25 12:13:50 +00:00
tspr - > pos . XY ( ) + = tspr - > Angles . Yaw . ToVector ( ) * 0.125 ;
2021-03-26 19:28:44 +00:00
}
2022-01-23 18:03:14 +00:00
else if ( actor - > sprext . renderflags & SPREXT_AWAY2 )
2021-03-26 19:28:44 +00:00
{
2022-11-25 12:13:50 +00:00
tspr - > pos . XY ( ) - = tspr - > Angles . Yaw . ToVector ( ) * 0.125 ;
2021-03-26 19:28:44 +00:00
}
2021-12-18 15:39:44 +00:00
switch ( tspr - > cstat & CSTAT_SPRITE_ALIGNMENT_MASK )
2021-03-26 19:28:44 +00:00
{
case CSTAT_SPRITE_ALIGNMENT_FACING :
2021-03-27 22:12:41 +00:00
{
HWSprite sprite ;
2021-12-30 15:58:48 +00:00
sprite . Process ( this , tspr , tspr - > sectp , false ) ;
2021-03-26 19:28:44 +00:00
break ;
2021-03-27 22:12:41 +00:00
}
2021-03-26 19:28:44 +00:00
case CSTAT_SPRITE_ALIGNMENT_WALL :
2021-03-27 12:22:34 +00:00
{
HWWall wall ;
2021-12-30 15:58:48 +00:00
wall . ProcessWallSprite ( this , tspr , tspr - > sectp ) ;
2021-03-26 19:28:44 +00:00
break ;
2021-03-27 12:22:34 +00:00
}
2021-03-26 19:28:44 +00:00
case CSTAT_SPRITE_ALIGNMENT_FLOOR :
{
HWFlat flat ;
2021-12-30 15:58:48 +00:00
flat . ProcessFlatSprite ( this , tspr , tspr - > sectp ) ;
2021-03-26 19:28:44 +00:00
break ;
}
default :
break ;
}
}
}
2021-03-15 17:55:56 +00:00
//-----------------------------------------------------------------------------
//
// CreateScene
//
// creates the draw lists for the current scene
//
//-----------------------------------------------------------------------------
2021-04-06 17:25:40 +00:00
void HWDrawInfo : : CreateScene ( bool portal )
2021-03-15 17:55:56 +00:00
{
2021-03-18 16:18:03 +00:00
const auto & vp = Viewpoint ;
2021-03-18 11:32:31 +00:00
2021-03-15 17:55:56 +00:00
angle_t a1 = FrustumAngle ( ) ;
// reset the portal manager
portalState . StartFrame ( ) ;
ProcessAll . Clock ( ) ;
// clip the scene and fill the drawlists
screen - > mVertexData - > Map ( ) ;
screen - > mLights - > Map ( ) ;
2022-08-07 08:25:15 +00:00
tsprites . clear ( ) ;
2021-04-02 20:52:46 +00:00
ingeo = false ;
geoofs = { 0 , 0 } ;
2021-03-26 14:06:14 +00:00
2021-04-24 10:08:38 +00:00
if ( ! portal ) mClipper - > SetVisibleRange ( vp . RotAngle , a1 ) ;
2022-09-16 17:13:06 +00:00
if ( a1 ! = 0xffffffff ) mDrawer . Init ( this , mClipper , vp . Pos , vp . RotAngle - a1 , vp . RotAngle + a1 ) ;
else mDrawer . Init ( this , mClipper , vp . Pos , 0 , 0 ) ;
2021-03-24 22:11:06 +00:00
if ( vp . SectNums )
2021-04-06 17:25:40 +00:00
mDrawer . RenderScene ( vp . SectNums , vp . SectCount , portal ) ;
2021-03-24 22:11:06 +00:00
else
2021-04-06 17:25:40 +00:00
mDrawer . RenderScene ( & vp . SectCount , 1 , portal ) ;
2021-03-15 17:55:56 +00:00
2021-03-26 14:06:14 +00:00
SetupSprite . Clock ( ) ;
2022-09-16 17:13:06 +00:00
// vp is in render space, so we must convert back.
2022-09-16 17:20:35 +00:00
gi - > processSprites ( tsprites , DVector3 ( vp . Pos . X , - vp . Pos . Y , - vp . Pos . Z ) , DAngle : : fromBam ( vp . RotAngle ) , vp . TicFrac ) ;
2021-03-26 19:28:44 +00:00
DispatchSprites ( ) ;
2021-03-26 14:06:14 +00:00
SetupSprite . Unclock ( ) ;
2021-04-02 20:52:46 +00:00
GeoEffect eff ;
int effsect = vp . SectNums ? vp . SectNums [ 0 ] : vp . SectCount ;
2021-11-21 08:08:05 +00:00
auto drawsectp = & sector [ effsect ] ;
auto orgdrawsectp = drawsectp ;
2021-04-02 20:52:46 +00:00
// RR geometry hack. Ugh...
// This just adds to the existing render list, so we must offset the effect areas to the same xy-space as the main one as we cannot change the view matrix.
2021-11-21 08:08:05 +00:00
if ( gi - > GetGeoEffect ( & eff , drawsectp ) )
2021-04-02 20:52:46 +00:00
{
ingeo = true ;
geoofs = { ( float ) eff . geox [ 0 ] , ( float ) eff . geoy [ 0 ] } ;
// process the first layer.
for ( int i = 0 ; i < eff . geocnt ; i + + )
{
2021-11-21 08:08:05 +00:00
auto sect = eff . geosectorwarp [ i ] ;
2022-11-15 13:59:28 +00:00
for ( unsigned w = 0 ; w < sect - > walls . Size ( ) ; w + + )
2021-04-02 20:52:46 +00:00
{
2022-11-15 14:31:52 +00:00
auto wal = & sect - > walls [ w ] ;
2022-01-27 17:52:52 +00:00
wal - > pos . X + = eff . geox [ i ] ;
wal - > pos . Y + = eff . geoy [ i ] ;
2021-04-02 20:52:46 +00:00
}
2021-12-17 17:22:42 +00:00
sect - > dirty = EDirty : : AllDirty ;
2021-11-21 08:08:05 +00:00
if ( eff . geosector [ i ] = = drawsectp ) drawsectp = eff . geosectorwarp [ i ] ;
2021-04-02 20:52:46 +00:00
}
2022-09-16 17:13:06 +00:00
if ( a1 ! = 0xffffffff ) mDrawer . Init ( this , mClipper , vp . Pos , vp . RotAngle - a1 , vp . RotAngle + a1 ) ;
else mDrawer . Init ( this , mClipper , vp . Pos , 0 , 0 ) ;
2021-04-24 10:08:38 +00:00
2022-11-15 11:03:44 +00:00
int drawsect = sectindex ( drawsectp ) ;
2021-04-06 17:25:40 +00:00
mDrawer . RenderScene ( & drawsect , 1 , false ) ;
2021-04-02 20:52:46 +00:00
for ( int i = 0 ; i < eff . geocnt ; i + + )
{
2021-11-21 08:08:05 +00:00
auto sect = eff . geosectorwarp [ i ] ;
2022-11-15 13:59:28 +00:00
for ( unsigned w = 0 ; w < sect - > walls . Size ( ) ; w + + )
2021-04-02 20:52:46 +00:00
{
2022-11-15 14:31:52 +00:00
auto wal = & sect - > walls [ w ] ;
2022-01-27 17:52:52 +00:00
wal - > pos . X - = eff . geox [ i ] ;
wal - > pos . Y - = eff . geoy [ i ] ;
2021-04-02 20:52:46 +00:00
}
}
// Now the second layer. Same shit, different arrays.
geoofs = { ( float ) eff . geox2 [ 0 ] , ( float ) eff . geoy2 [ 0 ] } ;
for ( int i = 0 ; i < eff . geocnt ; i + + )
{
2021-11-21 08:08:05 +00:00
auto sect = eff . geosectorwarp2 [ i ] ;
2022-11-15 13:59:28 +00:00
for ( unsigned w = 0 ; w < sect - > walls . Size ( ) ; w + + )
2021-04-02 20:52:46 +00:00
{
2022-11-15 14:31:52 +00:00
auto wal = & sect - > walls [ w ] ;
2022-01-27 17:52:52 +00:00
wal - > pos . X + = eff . geox2 [ i ] ;
wal - > pos . Y + = eff . geoy2 [ i ] ;
2021-04-02 20:52:46 +00:00
}
2021-12-17 17:22:42 +00:00
sect - > dirty = EDirty : : AllDirty ;
2021-11-21 08:08:05 +00:00
if ( eff . geosector [ i ] = = orgdrawsectp ) drawsectp = eff . geosectorwarp2 [ i ] ;
2021-04-02 20:52:46 +00:00
}
2022-09-16 17:13:06 +00:00
if ( a1 ! = 0xffffffff ) mDrawer . Init ( this , mClipper , vp . Pos , vp . RotAngle - a1 , vp . RotAngle + a1 ) ;
else mDrawer . Init ( this , mClipper , vp . Pos , 0 , 0 ) ;
2022-11-15 11:03:44 +00:00
drawsect = sectindex ( drawsectp ) ;
2021-04-06 17:25:40 +00:00
mDrawer . RenderScene ( & drawsect , 1 , false ) ;
2021-04-02 20:52:46 +00:00
for ( int i = 0 ; i < eff . geocnt ; i + + )
{
2021-11-21 08:08:05 +00:00
auto sect = eff . geosectorwarp2 [ i ] ;
2022-11-15 13:59:28 +00:00
for ( unsigned w = 0 ; w < sect - > walls . Size ( ) ; w + + )
2021-04-02 20:52:46 +00:00
{
2022-11-15 14:31:52 +00:00
auto wal = & sect - > walls [ w ] ;
2022-01-27 17:52:52 +00:00
wal - > pos . X - = eff . geox2 [ i ] ;
wal - > pos . Y - = eff . geoy2 [ i ] ;
2021-04-02 20:52:46 +00:00
}
}
ingeo = false ;
}
2021-03-15 17:55:56 +00:00
screen - > mLights - > Unmap ( ) ;
screen - > mVertexData - > Unmap ( ) ;
ProcessAll . Unclock ( ) ;
}
//-----------------------------------------------------------------------------
//
// RenderScene
//
// Draws the current draw lists for the non GLSL renderer
//
//-----------------------------------------------------------------------------
void HWDrawInfo : : RenderScene ( FRenderState & state )
{
RenderAll . Clock ( ) ;
state . SetDepthMask ( true ) ;
state . EnableFog ( true ) ;
state . SetRenderStyle ( STYLE_Source ) ;
// Part 1: solid geometry. This is set up so that there are no transparent parts
state . SetDepthFunc ( DF_Less ) ;
state . AlphaFunc ( Alpha_GEqual , 0.f ) ;
state . ClearDepthBias ( ) ;
state . EnableTexture ( gl_texture ) ;
state . EnableBrightmap ( true ) ;
drawlists [ GLDL_PLAINWALLS ] . DrawWalls ( this , state , false ) ;
2021-03-26 19:28:44 +00:00
2021-03-15 17:55:56 +00:00
drawlists [ GLDL_PLAINFLATS ] . DrawFlats ( this , state , false ) ;
// Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show
state . AlphaFunc ( Alpha_GEqual , gl_mask_threshold ) ;
2021-03-26 19:28:44 +00:00
// This list is masked, non-translucent walls.
2021-03-15 17:55:56 +00:00
drawlists [ GLDL_MASKEDWALLS ] . DrawWalls ( this , state , false ) ;
2021-03-26 19:28:44 +00:00
// These lists must be drawn in two passes for color and depth to avoid depth fighting with overlapping entries
drawlists [ GLDL_MASKEDFLATS ] . SortFlats ( this ) ;
2021-03-28 11:09:26 +00:00
drawlists [ GLDL_MASKEDWALLSV ] . SortWallsHorz ( this ) ;
drawlists [ GLDL_MASKEDWALLSH ] . SortWallsVert ( this ) ;
2022-01-13 19:55:55 +00:00
drawlists [ GLDL_MASKEDWALLSD ] . SortWallsDiag ( this ) ;
2021-03-26 19:28:44 +00:00
2021-03-27 14:24:09 +00:00
2021-03-26 19:28:44 +00:00
// these lists are only wall and floor sprites - often attached to walls and floors - so they need to be offset from the plane they may be attached to.
drawlists [ GLDL_MASKEDWALLSS ] . DrawWalls ( this , state , false ) ;
2021-03-27 12:22:34 +00:00
// Each list must draw both its passes before the next one to ensure proper depth buffer contents.
2022-07-04 07:10:32 +00:00
auto & list = drawlists [ GLDL_MASKEDWALLSD ] . drawitems ;
unsigned i = 0 ;
RenderWall . Clock ( ) ;
while ( i < list . Size ( ) )
{
unsigned j ;
auto check = drawlists [ GLDL_MASKEDWALLSD ] . walls [ list [ i ] . index ] - > walldist ;
state . SetDepthMask ( false ) ;
for ( j = i ; j < list . Size ( ) & & drawlists [ GLDL_MASKEDWALLSD ] . walls [ list [ j ] . index ] - > walldist = = check ; j + + )
{
drawlists [ GLDL_MASKEDWALLSD ] . walls [ list [ j ] . index ] - > DrawWall ( this , state , false ) ;
}
state . SetDepthMask ( true ) ;
for ( unsigned k = i ; k < j ; k + + )
{
drawlists [ GLDL_MASKEDWALLSD ] . walls [ list [ k ] . index ] - > DrawWall ( this , state , false ) ;
}
i = j ;
}
RenderWall . Unclock ( ) ;
2022-01-13 19:55:55 +00:00
state . SetDepthMask ( false ) ;
drawlists [ GLDL_MASKEDWALLSD ] . DrawWalls ( this , state , false ) ;
state . SetDepthMask ( true ) ;
state . SetColorMask ( false ) ;
drawlists [ GLDL_MASKEDWALLSD ] . DrawWalls ( this , state , false ) ;
state . SetColorMask ( true ) ;
2021-03-26 19:28:44 +00:00
state . SetDepthMask ( false ) ;
drawlists [ GLDL_MASKEDWALLSV ] . DrawWalls ( this , state , false ) ;
state . SetDepthMask ( true ) ;
state . SetColorMask ( false ) ;
drawlists [ GLDL_MASKEDWALLSV ] . DrawWalls ( this , state , false ) ;
2021-03-27 12:22:34 +00:00
state . SetColorMask ( true ) ;
state . SetDepthMask ( false ) ;
2021-03-26 19:28:44 +00:00
drawlists [ GLDL_MASKEDWALLSH ] . DrawWalls ( this , state , false ) ;
2021-03-27 12:22:34 +00:00
state . SetDepthMask ( true ) ;
state . SetColorMask ( false ) ;
drawlists [ GLDL_MASKEDWALLSH ] . DrawWalls ( this , state , false ) ;
state . SetColorMask ( true ) ;
2021-06-08 22:47:13 +00:00
state . SetDepthBias ( - 1 , - 128 ) ;
2022-01-03 20:10:04 +00:00
drawlists [ GLDL_MASKEDSLOPEFLATS ] . DrawFlats ( this , state , false ) ;
2021-03-27 12:22:34 +00:00
state . SetDepthMask ( false ) ;
drawlists [ GLDL_MASKEDFLATS ] . DrawFlats ( this , state , false ) ;
state . SetDepthMask ( true ) ;
state . SetColorMask ( false ) ;
2021-03-26 19:28:44 +00:00
drawlists [ GLDL_MASKEDFLATS ] . DrawFlats ( this , state , false ) ;
state . SetColorMask ( true ) ;
state . ClearDepthBias ( ) ;
2021-03-15 17:55:56 +00:00
drawlists [ GLDL_MODELS ] . Draw ( this , state , false ) ;
state . SetRenderStyle ( STYLE_Translucent ) ;
state . SetDepthFunc ( DF_LEqual ) ;
RenderAll . Unclock ( ) ;
}
//-----------------------------------------------------------------------------
//
// RenderTranslucent
//
//-----------------------------------------------------------------------------
void HWDrawInfo : : RenderTranslucent ( FRenderState & state )
{
RenderAll . Clock ( ) ;
2021-06-13 07:39:07 +00:00
state . SetDepthBias ( - 1 , - 160 ) ;
2021-03-29 17:45:04 +00:00
2021-03-15 17:55:56 +00:00
// final pass: translucent stuff
state . AlphaFunc ( Alpha_GEqual , gl_mask_sprite_threshold ) ;
state . SetRenderStyle ( STYLE_Translucent ) ;
state . EnableBrightmap ( true ) ;
drawlists [ GLDL_TRANSLUCENTBORDER ] . Draw ( this , state , true ) ;
state . SetDepthMask ( false ) ;
drawlists [ GLDL_TRANSLUCENT ] . DrawSorted ( this , state ) ;
state . EnableBrightmap ( false ) ;
2021-03-29 17:45:04 +00:00
state . ClearDepthBias ( ) ;
2021-03-15 17:55:56 +00:00
state . AlphaFunc ( Alpha_GEqual , 0.5f ) ;
state . SetDepthMask ( true ) ;
RenderAll . Unclock ( ) ;
}
//-----------------------------------------------------------------------------
//
// RenderTranslucent
//
//-----------------------------------------------------------------------------
void HWDrawInfo : : RenderPortal ( HWPortal * p , FRenderState & state , bool usestencil )
{
auto gp = static_cast < HWPortal * > ( p ) ;
gp - > SetupStencil ( this , state , usestencil ) ;
auto new_di = StartDrawInfo ( this , Viewpoint , & VPUniforms ) ;
2023-01-13 23:41:22 +00:00
new_di - > eye = eye ;
2022-01-10 21:22:37 +00:00
new_di - > visibility = visibility ;
new_di - > rellight = rellight ;
2021-03-15 17:55:56 +00:00
new_di - > mCurrentPortal = gp ;
state . SetLightIndex ( - 1 ) ;
gp - > DrawContents ( new_di , state ) ;
new_di - > EndDrawInfo ( ) ;
state . SetVertexBuffer ( screen - > mVertexData ) ;
screen - > mViewpoints - > Bind ( state , vpIndex ) ;
gp - > RemoveStencil ( this , state , usestencil ) ;
}
//-----------------------------------------------------------------------------
//
// Draws player sprites and color blend
//
//-----------------------------------------------------------------------------
2021-03-18 13:49:36 +00:00
void HWDrawInfo : : EndDrawScene ( FRenderState & state )
2021-03-15 17:55:56 +00:00
{
state . EnableFog ( false ) ;
#if 0
// [BB] HUD models need to be rendered here.
const bool renderHUDModel = IsHUDModelForPlayerAvailable ( players [ consoleplayer ] . camera - > player ) ;
if ( renderHUDModel )
{
// [BB] The HUD model should be drawn over everything else already drawn.
state . Clear ( CT_Depth ) ;
DrawPlayerSprites ( true , state ) ;
}
# endif
state . EnableStencil ( false ) ;
state . SetViewport ( screen - > mScreenViewport . left , screen - > mScreenViewport . top , screen - > mScreenViewport . width , screen - > mScreenViewport . height ) ;
// Restore standard rendering state
state . SetRenderStyle ( STYLE_Translucent ) ;
state . ResetColor ( ) ;
state . EnableTexture ( true ) ;
state . SetScissor ( 0 , 0 , - 1 , - 1 ) ;
}
//-----------------------------------------------------------------------------
//
// sets 3D viewport and initial state
//
//-----------------------------------------------------------------------------
void HWDrawInfo : : Set3DViewport ( FRenderState & state )
{
// Always clear all buffers with scissor test disabled.
// This is faster on newer hardware because it allows the GPU to skip
// reading from slower memory where the full buffers are stored.
state . SetScissor ( 0 , 0 , - 1 , - 1 ) ;
state . Clear ( CT_Color | CT_Depth | CT_Stencil ) ;
const auto & bounds = screen - > mSceneViewport ;
state . SetViewport ( bounds . left , bounds . top , bounds . width , bounds . height ) ;
state . SetScissor ( bounds . left , bounds . top , bounds . width , bounds . height ) ;
state . EnableMultisampling ( true ) ;
state . EnableDepthTest ( true ) ;
state . EnableStencil ( true ) ;
state . SetStencil ( 0 , SOP_Keep , SF_AllOn ) ;
}
//-----------------------------------------------------------------------------
//
// gl_drawscene - this function renders the scene from the current
// viewpoint, including mirrors and skyboxes and other portals
// It is assumed that the HWPortal::EndFrame returns with the
// stencil, z-buffer and the projection matrix intact!
//
//-----------------------------------------------------------------------------
2021-04-06 17:25:40 +00:00
void HWDrawInfo : : DrawScene ( int drawmode , bool portal )
2021-03-15 17:55:56 +00:00
{
static int recursion = 0 ;
static int ssao_portals_available = 0 ;
bool applySSAO = false ;
if ( drawmode = = DM_MAINVIEW )
{
ssao_portals_available = gl_ssao_portals ;
applySSAO = true ;
}
else if ( drawmode = = DM_OFFSCREEN )
{
ssao_portals_available = 0 ;
}
else if ( drawmode = = DM_PORTAL & & ssao_portals_available > 0 )
{
applySSAO = ( mCurrentPortal - > AllowSSAO ( ) /* || Level->flags3&LEVEL3_SKYBOXAO*/ ) ;
ssao_portals_available - - ;
}
2021-04-06 17:25:40 +00:00
CreateScene ( portal ) ;
2021-03-15 17:55:56 +00:00
auto & RenderState = * screen - > RenderState ( ) ;
RenderState . SetDepthMask ( true ) ;
2021-03-21 21:48:01 +00:00
2021-03-15 17:55:56 +00:00
if ( ! gl_no_skyclear ) portalState . RenderFirstSkyPortal ( recursion , this , RenderState ) ;
RenderScene ( RenderState ) ;
if ( applySSAO & & RenderState . GetPassType ( ) = = GBUFFER_PASS )
{
screen - > AmbientOccludeScene ( VPUniforms . mProjectionMatrix . get ( ) [ 5 ] ) ;
screen - > mViewpoints - > Bind ( RenderState , vpIndex ) ;
}
// Handle all portals after rendering the opaque objects but before
// doing all translucent stuff
recursion + + ;
portalState . EndFrame ( this , RenderState ) ;
recursion - - ;
RenderTranslucent ( RenderState ) ;
}
//-----------------------------------------------------------------------------
//
// R_RenderView - renders one view - either the screen or a camera texture
//
//-----------------------------------------------------------------------------
void HWDrawInfo : : ProcessScene ( bool toscreen )
{
portalState . BeginScene ( ) ;
2021-04-06 17:25:40 +00:00
DrawScene ( toscreen ? DM_MAINVIEW : DM_OFFSCREEN , false ) ;
2021-04-01 18:47:05 +00:00
if ( toscreen & & isBlood ( ) )
{
gotsector = mDrawer . GotSector ( ) ; // Blood needs this to implement some lighting effect hacks. Needs to be refactored to use better info.
}
2021-03-15 17:55:56 +00:00
}