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"
//#include "models.h"
# 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-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-04-01 18:47:05 +00:00
FixedBitArray < MAXSECTORS > gotsector ;
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;
2021-03-18 16:18:03 +00:00
VPUniforms . mGlobVis = ( 2 / 65536.f ) * g_visibility / r_ambientlight ;
2021-03-15 17:55:56 +00:00
VPUniforms . mPalLightLevels = numshades | ( static_cast < int > ( gl_fogmode ) < < 8 ) | ( 5 < < 16 ) ;
VPUniforms . mClipLine . X = - 10000000.0f ;
VPUniforms . mShadowmapFilter = gl_shadowmap_filter ;
}
2021-03-23 20:23:49 +00:00
vec2_t view = { int ( Viewpoint . Pos . X * 16 ) , int ( Viewpoint . Pos . Y * - 16 ) } ;
mClipper - > SetViewpoint ( view ) ;
2021-03-15 17:55:56 +00:00
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 ( )
{
float WidescreenRatio = 1.6666f ; // fixme - this is a placeholder.
float tilt = fabs ( Viewpoint . HWAngles . Pitch . Degrees ) ;
// 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...
double floatangle = 2.0 + ( 45.0 + ( ( tilt / 1.9 ) ) ) * Viewpoint . FieldOfView . Degrees * 48.0 / AspectMultiplier ( WidescreenRatio ) / 90.0 ;
angle_t a1 = DAngle ( 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 ( ) ;
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 ) ;
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 ( ) ;
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 ( )
{
for ( int i = 0 ; i < spritesortcnt ; i + + )
{
auto tspr = & tsprite [ i ] ;
int tilenum = tspr - > picnum ;
int spritenum = tspr - > owner ;
if ( spritenum < 0 | | ( unsigned ) tilenum > = MAXTILES )
continue ;
2021-04-01 18:47:05 +00:00
if ( automapping = = 1 & & ( unsigned ) spritenum < MAXSPRITES )
show2dsprite . Set ( spritenum ) ;
2021-03-26 19:28:44 +00:00
setgotpic ( tilenum ) ;
2021-04-04 11:45:43 +00:00
if ( ! ( spriteext [ spritenum ] . flags & SPREXT_NOTMD ) )
2021-03-26 19:28:44 +00:00
{
int pt = Ptile2tile ( tspr - > picnum , tspr - > pal ) ;
if ( hw_models & & tile2model [ pt ] . modelid > = 0 & & tile2model [ pt ] . framenum > = 0 )
{
//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 )
{
if ( ( tspr - > cstat & CSTAT_SPRITE_ALIGNMENT ) ! = CSTAT_SPRITE_ALIGNMENT_SLAB & & tiletovox [ tspr - > picnum ] > = 0 & & voxmodels [ tiletovox [ tspr - > picnum ] ] )
{
2021-04-02 16:20:07 +00:00
HWSprite hwsprite ;
2021-04-04 11:24:33 +00:00
int num = tiletovox [ tspr - > picnum ] ;
2021-04-05 11:55:36 +00:00
if ( hwsprite . ProcessVoxel ( this , voxmodels [ tiletovox [ tspr - > picnum ] ] , tspr , & sector [ tspr - > sectnum ] , voxrotate [ num ] ) )
2021-04-04 11:45:43 +00:00
continue ;
2021-03-26 19:28:44 +00:00
}
else if ( ( tspr - > cstat & CSTAT_SPRITE_ALIGNMENT ) = = CSTAT_SPRITE_ALIGNMENT_SLAB & & tspr - > picnum < MAXVOXELS & & voxmodels [ tspr - > picnum ] )
{
2021-04-02 16:20:07 +00:00
HWSprite hwsprite ;
2021-04-04 11:24:33 +00:00
int num = tspr - > picnum ;
2021-04-05 11:55:36 +00:00
hwsprite . ProcessVoxel ( this , voxmodels [ tspr - > picnum ] , tspr , & sector [ tspr - > sectnum ] , voxrotate [ num ] ) ;
2021-04-04 11:45:43 +00:00
continue ;
2021-03-26 19:28:44 +00:00
}
}
}
if ( spriteext [ spritenum ] . flags & SPREXT_AWAY1 )
{
tspr - > pos . x + = bcos ( tspr - > ang , - 13 ) ;
tspr - > pos . y + = bsin ( tspr - > ang , - 13 ) ;
}
else if ( spriteext [ spritenum ] . flags & SPREXT_AWAY2 )
{
tspr - > pos . x - = bcos ( tspr - > ang , - 13 ) ;
tspr - > pos . y - = bsin ( tspr - > ang , - 13 ) ;
}
2021-03-27 13:18:33 +00:00
tileUpdatePicnum ( & tilenum , sprite - > owner + 32768 , 0 ) ;
tspr - > picnum = tilenum ;
2021-03-26 19:28:44 +00:00
switch ( tspr - > cstat & CSTAT_SPRITE_ALIGNMENT )
{
case CSTAT_SPRITE_ALIGNMENT_FACING :
2021-03-27 22:12:41 +00:00
{
HWSprite sprite ;
sprite . Process ( this , tspr , & sector [ tspr - > sectnum ] , 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 ;
wall . ProcessWallSprite ( this , tspr , & sector [ tspr - > sectnum ] ) ;
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 ;
flat . ProcessFlatSprite ( this , tspr , & sector [ tspr - > sectnum ] ) ;
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 ( ) ;
2021-03-26 14:06:14 +00:00
spritesortcnt = 0 ;
2021-04-02 20:52:46 +00:00
ingeo = false ;
geoofs = { 0 , 0 } ;
2021-03-26 14:06:14 +00:00
2021-03-18 16:18:03 +00:00
vec2_t view = { int ( vp . Pos . X * 16 ) , int ( vp . Pos . Y * - 16 ) } ;
2021-04-24 10:08:38 +00:00
if ( ! portal ) mClipper - > SetVisibleRange ( vp . RotAngle , a1 ) ;
2021-04-06 22:02:36 +00:00
if ( a1 ! = 0xffffffff ) mDrawer . Init ( this , mClipper , view , bamang ( vp . RotAngle - a1 ) , bamang ( vp . RotAngle + a1 ) ) ;
else mDrawer . Init ( this , mClipper , view , bamang ( 0 ) , bamang ( 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 ( ) ;
2021-04-02 08:28:40 +00:00
gi - > processSprites ( tsprite , spritesortcnt , view . x , view . y , vp . Pos . Z * - 256 , bamang ( vp . RotAngle ) , vp . TicFrac * 65536 ) ;
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 ;
int drawsect = effsect ;
// 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.
if ( gi - > GetGeoEffect ( & eff , effsect ) )
{
ingeo = true ;
geoofs = { ( float ) eff . geox [ 0 ] , ( float ) eff . geoy [ 0 ] } ;
// process the first layer.
for ( int i = 0 ; i < eff . geocnt ; i + + )
{
auto sect = & sector [ eff . geosectorwarp [ i ] ] ;
for ( auto w = 0 ; w < sect - > wallnum ; w + + )
{
auto wal = & wall [ sect - > wallptr + w ] ;
wal - > x + = eff . geox [ i ] ;
wal - > y + = eff . geoy [ i ] ;
}
sect - > dirty = 255 ;
if ( eff . geosector [ i ] = = effsect ) drawsect = eff . geosectorwarp [ i ] ;
}
2021-04-06 22:02:36 +00:00
if ( a1 ! = 0xffffffff ) mDrawer . Init ( this , mClipper , view , bamang ( vp . RotAngle - a1 ) , bamang ( vp . RotAngle + a1 ) ) ;
else mDrawer . Init ( this , mClipper , view , bamang ( 0 ) , bamang ( 0 ) ) ;
2021-04-24 10:08:38 +00:00
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 + + )
{
auto sect = & sector [ eff . geosectorwarp [ i ] ] ;
for ( auto w = 0 ; w < sect - > wallnum ; w + + )
{
auto wal = & wall [ sect - > wallptr + w ] ;
wal - > x - = eff . geox [ i ] ;
wal - > y - = eff . geoy [ i ] ;
}
}
// 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 + + )
{
auto sect = & sector [ eff . geosectorwarp2 [ i ] ] ;
for ( auto w = 0 ; w < sect - > wallnum ; w + + )
{
auto wal = & wall [ sect - > wallptr + w ] ;
wal - > x + = eff . geox2 [ i ] ;
wal - > y + = eff . geoy2 [ i ] ;
}
sect - > dirty = 255 ;
if ( eff . geosector [ i ] = = effsect ) drawsect = eff . geosectorwarp2 [ i ] ;
}
2021-04-06 22:02:36 +00:00
if ( a1 ! = 0xffffffff ) mDrawer . Init ( this , mClipper , view , bamang ( vp . RotAngle - a1 ) , bamang ( vp . RotAngle + a1 ) ) ;
else mDrawer . Init ( this , mClipper , view , bamang ( 0 ) , bamang ( 0 ) ) ;
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 + + )
{
auto sect = & sector [ eff . geosectorwarp2 [ i ] ] ;
for ( auto w = 0 ; w < sect - > wallnum ; w + + )
{
auto wal = & wall [ sect - > wallptr + w ] ;
wal - > x - = eff . geox2 [ i ] ;
wal - > y - = eff . geoy2 [ i ] ;
}
}
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 )
{
const auto & vp = Viewpoint ;
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 ) ;
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.
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 ) ;
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-03-29 17:45:04 +00:00
state . SetDepthBias ( - 1 , - 128 ) ;
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 ) ;
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 ;
const auto & vp = Viewpoint ;
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
}