2021-03-15 22:46:03 +00:00
# pragma once
//==========================================================================
//
// One wall segment in the draw list
//
//==========================================================================
# include "renderstyle.h"
# include "textures.h"
# include "fcolormap.h"
# include "build.h"
2021-03-18 20:50:02 +00:00
# include "gamefuncs.h"
2021-03-21 18:36:55 +00:00
# include "render.h"
2021-04-02 16:20:07 +00:00
# include "matrix.h"
2021-04-07 22:47:07 +00:00
# include "gamecontrol.h"
2021-04-10 07:57:03 +00:00
# include "hw_renderstate.h"
# include "hw_cvars.h"
2021-12-04 18:08:50 +00:00
# include "coreactor.h"
2021-03-15 22:46:03 +00:00
2021-10-08 17:06:41 +00:00
# ifdef _MSC_VER
2021-05-11 23:55:06 +00:00
# pragma warning(disable:4244) // this gets a bit annoying in the renderer...
2021-10-08 17:06:41 +00:00
# endif
2021-05-11 23:55:06 +00:00
2021-03-15 22:46:03 +00:00
struct HWHorizonInfo ;
struct HWSkyInfo ;
class FMaterial ;
struct FTexCoordInfo ;
struct FSectorPortalGroup ;
struct FFlatVertex ;
struct FDynLightData ;
class VSMatrix ;
struct FSpriteModelFrame ;
class FRenderState ;
2021-04-05 11:55:36 +00:00
struct voxmodel_t ;
2021-12-15 11:01:14 +00:00
struct Section ;
2021-03-15 22:46:03 +00:00
struct HWSectorPlane
{
FTextureID texture ;
//secplane_t plane;
float Texheight ;
float Angle ;
FVector2 Offs ;
FVector2 Scale ;
void GetFromSector ( sectortype * sec , int ceiling )
{
/*
Offs . X = ( float ) sec - > GetXOffset ( ceiling ) ;
Offs . Y = ( float ) sec - > GetYOffset ( ceiling ) ;
Scale . X = ( float ) sec - > GetXScale ( ceiling ) ;
Scale . Y = ( float ) sec - > GetYScale ( ceiling ) ;
Angle = ( float ) sec - > GetAngle ( ceiling ) . Degrees ;
texture = sec - > GetTexture ( ceiling ) ;
plane = sec - > GetSecPlane ( ceiling ) ;
Texheight = ( float ) ( ( ceiling = = sector_t : : ceiling ) ? plane . fD ( ) : - plane . fD ( ) ) ;
*/
}
} ;
enum HWRenderStyle
{
STYLEHW_Normal , // default
STYLEHW_Solid , // drawn solid (needs special treatment for sprites)
STYLEHW_NoAlphaTest , // disable alpha test
} ;
enum WallTypes
{
RENDERWALL_NONE ,
RENDERWALL_TOP ,
RENDERWALL_M1S ,
RENDERWALL_M2S ,
RENDERWALL_BOTTOM ,
RENDERWALL_FOGBOUNDARY ,
RENDERWALL_MIRRORSURFACE ,
RENDERWALL_M2SNF ,
RENDERWALL_COLOR ,
// Insert new types at the end!
} ;
enum PortalTypes
{
PORTALTYPE_SKY ,
PORTALTYPE_HORIZON ,
PORTALTYPE_SKYBOX ,
PORTALTYPE_SECTORSTACK ,
PORTALTYPE_PLANEMIRROR ,
PORTALTYPE_MIRROR ,
PORTALTYPE_LINETOLINE ,
2021-03-21 18:36:55 +00:00
PORTALTYPE_LINETOSPRITE ,
2021-03-15 22:46:03 +00:00
} ;
//==========================================================================
//
// One sector plane, still in fixed point
//
//==========================================================================
struct HWSeg
{
float x1 , x2 ;
float y1 , y2 ;
float fracleft , fracright ;
FVector3 Normal ( ) const
{
// we do not use the vector math inlines here because they are not optimized for speed but accuracy in the playsim and this is called quite frequently.
float x = y2 - y1 ;
float y = x1 - x2 ;
float ilength = 1.f / sqrtf ( x * x + y * y ) ;
return FVector3 ( x * ilength , 0 , y * ilength ) ;
}
} ;
struct texcoord
{
float u , v ;
} ;
struct HWDrawInfo ;
class HWWall
{
public :
static const char passflag [ ] ;
enum
{
HWF_CLAMPX = 1 ,
HWF_CLAMPY = 2 ,
HWF_SKYHACK = 4 ,
HWF_NOSPLIT = 64 ,
HWF_TRANSLUCENT = 128 ,
} ;
enum
{
RWF_BLANK = 0 ,
RWF_TEXTURED = 1 , // actually not being used anymore because with buffers it's even less efficient not writing the texture coordinates - but leave it here
2021-05-20 10:36:35 +00:00
RWF_TRANS = 2 ,
2021-03-15 22:46:03 +00:00
RWF_NORENDER = 8 ,
} ;
enum
{
LOLFT ,
UPLFT ,
UPRGT ,
LORGT ,
} ;
friend struct HWDrawList ;
friend class HWPortal ;
FGameTexture * texture ;
HWSeg glseg ;
float ztop [ 2 ] , zbottom [ 2 ] ;
texcoord tcs [ 4 ] ;
float alpha ;
2021-03-26 19:28:44 +00:00
FRenderStyle RenderStyle ;
2021-12-30 09:30:21 +00:00
2021-03-15 22:46:03 +00:00
float ViewDistance ;
float visibility ;
2021-12-29 17:16:50 +00:00
walltype * walldist ;
FVector2 wallpoint ;
2021-03-18 16:18:03 +00:00
short shade , palette ;
PalEntry fade ;
2021-03-15 22:46:03 +00:00
uint16_t flags ;
uint8_t type ;
int dynlightindex ;
union
{
// it's either one of them but never more!
2021-03-21 18:36:55 +00:00
//FSectorPortal *secportal; // sector portal (formerly skybox)
2021-03-15 22:46:03 +00:00
HWSkyInfo * sky ; // for normal sky
2021-03-21 18:36:55 +00:00
//HWHorizonInfo * horizon; // for horizon information
PortalDesc * portal ; // stacked sector portals
2021-12-27 21:32:26 +00:00
const int * planemirror ; // for plane mirrors
2021-03-15 22:46:03 +00:00
} ;
unsigned int vertindex ;
unsigned int vertcount ;
public :
2021-03-26 19:28:44 +00:00
walltype * seg ;
2021-12-04 18:08:50 +00:00
tspritetype * Sprite ;
2021-03-26 19:28:44 +00:00
sectortype * frontsector , * backsector ;
2021-03-15 22:46:03 +00:00
//private:
void PutWall ( HWDrawInfo * di , bool translucent ) ;
void PutPortal ( HWDrawInfo * di , int ptype , int plane ) ;
void CheckTexturePosition ( ) ;
void SetupLights ( HWDrawInfo * di , FDynLightData & lightdata ) ;
void MakeVertices ( HWDrawInfo * di , bool nosplit ) ;
void SkyPlane ( HWDrawInfo * di , sectortype * sector , int plane , bool allowmirror ) ;
void SkyLine ( HWDrawInfo * di , sectortype * sec , walltype * line ) ;
2021-03-22 15:02:52 +00:00
void SkyNormal ( HWDrawInfo * di , sectortype * fs , FVector2 & v1 , FVector2 & v2 , float fch1 , float fch2 , float ffh1 , float ffh2 ) ;
void SkyTop ( HWDrawInfo * di , walltype * seg , sectortype * fs , sectortype * bs , FVector2 & v1 , FVector2 & v2 , float fch1 , float fch2 ) ;
void SkyBottom ( HWDrawInfo * di , walltype * seg , sectortype * fs , sectortype * bs , FVector2 & v1 , FVector2 & v2 , float ffh1 , float ffh2 ) ;
2021-03-15 22:46:03 +00:00
bool DoHorizon ( HWDrawInfo * di , walltype * seg , sectortype * fs , DVector2 & v1 , DVector2 & v2 ) ;
bool SetWallCoordinates ( walltype * seg , float topleft , float topright , float bottomleft , float bottomright ) ;
void DoTexture ( HWDrawInfo * di , walltype * wal , walltype * refwall , float yref , float topleft , float topright , float bottomleft , float bottomright ) ;
void DoOneSidedTexture ( HWDrawInfo * di , walltype * seg , sectortype * frontsector , sectortype * backsector , float topleft , float topright , float bottomleft , float bottomright ) ;
void DoUpperTexture ( HWDrawInfo * di , walltype * seg , sectortype * frontsector , sectortype * backsector , float topleft , float topright , float bottomleft , float bottomright ) ;
void DoLowerTexture ( HWDrawInfo * di , walltype * seg , sectortype * frontsector , sectortype * backsector , float topleft , float topright , float bottomleft , float bottomright ) ;
void DoMidTexture ( HWDrawInfo * di , walltype * seg ,
sectortype * front , sectortype * back ,
float fch1 , float fch2 , float ffh1 , float ffh2 ,
float bch1 , float bch2 , float bfh1 , float bfh2 ) ;
int CreateVertices ( FFlatVertex * & ptr , bool nosplit ) ;
2021-12-28 18:33:27 +00:00
int CountVertices ( ) ;
void SplitLeftEdge ( FFlatVertex * & ptr ) ;
void SplitRightEdge ( FFlatVertex * & ptr ) ;
void CountLeftEdge ( unsigned & ptr ) ;
void CountRightEdge ( unsigned & ptr ) ;
2021-03-15 22:46:03 +00:00
void RenderWall ( HWDrawInfo * di , FRenderState & state , int textured ) ;
void RenderFogBoundary ( HWDrawInfo * di , FRenderState & state ) ;
void RenderMirrorSurface ( HWDrawInfo * di , FRenderState & state ) ;
void RenderTexturedWall ( HWDrawInfo * di , FRenderState & state , int rflags ) ;
void RenderTranslucentWall ( HWDrawInfo * di , FRenderState & state ) ;
public :
void Process ( HWDrawInfo * di , walltype * seg , sectortype * frontsector , sectortype * backsector ) ;
2021-12-04 18:08:50 +00:00
void ProcessWallSprite ( HWDrawInfo * di , tspritetype * spr , sectortype * frontsector ) ;
2021-03-15 22:46:03 +00:00
float PointOnSide ( float x , float y )
{
return - ( ( y - glseg . y1 ) * ( glseg . x2 - glseg . x1 ) - ( x - glseg . x1 ) * ( glseg . y2 - glseg . y1 ) ) ;
}
void DrawWall ( HWDrawInfo * di , FRenderState & state , bool translucent ) ;
} ;
//==========================================================================
//
2022-01-03 11:31:54 +00:00
// Common fields needed by the sprite sorter.
2021-03-15 22:46:03 +00:00
//
//==========================================================================
2022-01-03 11:31:54 +00:00
class HWFlatOrSprite
2021-03-15 22:46:03 +00:00
{
public :
2022-01-03 11:31:54 +00:00
float depth ;
2021-12-04 18:08:50 +00:00
tspritetype * Sprite ; // for flat sprites.
2022-01-03 11:31:54 +00:00
} ;
2021-03-15 22:46:03 +00:00
2022-01-03 11:31:54 +00:00
//==========================================================================
//
// One flat plane in the draw list
//
//==========================================================================
class HWFlat : public HWFlatOrSprite
{
public :
sectortype * sec ;
FGameTexture * texture ;
int section ;
2021-03-15 22:46:03 +00:00
float z ; // the z position of the flat (only valid for non-sloped planes)
2021-03-18 20:50:02 +00:00
PalEntry fade ;
2021-04-14 17:17:40 +00:00
int shade , palette ;
float visibility ;
2021-03-15 22:46:03 +00:00
float alpha ;
2021-03-26 19:28:44 +00:00
FRenderStyle RenderStyle ;
2021-03-15 22:46:03 +00:00
int iboindex ;
2021-03-30 21:27:11 +00:00
bool stack ;
2022-01-03 11:31:54 +00:00
uint8_t plane ;
short slopecount ;
2021-04-02 20:52:46 +00:00
FVector2 geoofs ;
2021-03-15 22:46:03 +00:00
//int vboheight;
2022-01-03 11:31:54 +00:00
int slopeindex ;
2021-03-18 20:50:02 +00:00
int vertindex , vertcount ; // this should later use a static vertex buffer, but that'd hinder the development phase, so for now vertex data gets created on the fly.
2021-12-21 12:46:11 +00:00
void MakeVertices ( HWDrawInfo * di ) ;
2021-03-18 20:50:02 +00:00
2021-03-15 22:46:03 +00:00
int dynlightindex ;
void CreateSkyboxVertices ( FFlatVertex * buffer ) ;
//void SetupLights(HWDrawInfo *di, FLightNode *head, FDynLightData &lightdata, int portalgroup);
2021-03-18 20:50:02 +00:00
void PutFlat ( HWDrawInfo * di , int whichplane ) ;
2021-12-15 11:23:50 +00:00
void ProcessSector ( HWDrawInfo * di , sectortype * frontsector , int sectionnum , int which = 7 /*SSRF_RENDERALL*/ ) ; // cannot use constant due to circular dependencies.
2021-12-04 18:08:50 +00:00
void ProcessFlatSprite ( HWDrawInfo * di , tspritetype * sprite , sectortype * sector ) ;
2021-12-30 09:30:21 +00:00
2021-03-15 22:46:03 +00:00
void DrawSubsectors ( HWDrawInfo * di , FRenderState & state ) ;
2021-03-18 20:50:02 +00:00
void DrawFlat ( HWDrawInfo * di , FRenderState & state , bool translucent ) ;
2021-03-15 22:46:03 +00:00
} ;
//==========================================================================
//
// One sprite in the draw list
//
//==========================================================================
2022-01-03 11:31:54 +00:00
class HWSprite : public HWFlatOrSprite
2021-03-15 22:46:03 +00:00
{
public :
2021-03-27 22:12:41 +00:00
PalEntry fade ;
2021-04-14 17:17:40 +00:00
int shade , palette ;
float visibility ;
2021-03-27 22:12:41 +00:00
float alpha ;
2021-03-15 22:46:03 +00:00
FRenderStyle RenderStyle ;
2021-04-02 16:20:07 +00:00
int modelframe ; // : sprite, 1: model, -1:voxel
voxmodel_t * voxel ;
2021-03-15 22:46:03 +00:00
int index ;
int vertexindex ;
float x , y , z ; // needed for sorting!
2021-04-02 16:20:07 +00:00
union
{
struct
{
float ul , ur ;
float vt , vb ;
float x1 , y1 , z1 ;
float x2 , y2 , z2 ;
} ;
VSMatrix rotmat ;
} ;
2021-03-15 22:46:03 +00:00
int dynlightindex ;
FGameTexture * texture ;
DRotator Angles ;
2021-03-27 22:12:41 +00:00
void CalculateVertices ( HWDrawInfo * di , FVector3 * v , DVector3 * vp ) ;
2021-03-15 22:46:03 +00:00
public :
2021-03-27 22:12:41 +00:00
void CreateVertices ( HWDrawInfo * di ) ;
2021-03-15 22:46:03 +00:00
void PutSprite ( HWDrawInfo * di , bool translucent ) ;
2021-12-04 18:08:50 +00:00
void Process ( HWDrawInfo * di , tspritetype * thing , sectortype * sector , int thruportal = false ) ;
bool ProcessVoxel ( HWDrawInfo * di , voxmodel_t * voxel , tspritetype * tspr , sectortype * sector , bool rotate ) ;
2021-03-15 22:46:03 +00:00
2021-03-27 22:12:41 +00:00
void DrawSprite ( HWDrawInfo * di , FRenderState & state , bool translucent ) ;
2021-03-15 22:46:03 +00:00
} ;
inline float Dist2 ( float x1 , float y1 , float x2 , float y2 )
{
return sqrtf ( ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ) ) ;
}
void hw_GetDynModelLight ( AActor * self , FDynLightData & modellightdata ) ;
extern const float LARGE_VALUE ;
struct FDynLightData ;
struct FDynamicLight ;
bool GetLight ( FDynLightData & dld , int group , Plane & p , FDynamicLight * light , bool checkside ) ;
void AddLightToList ( FDynLightData & dld , int group , FDynamicLight * light , bool forceAttenuate ) ;
2021-03-18 20:50:02 +00:00
inline float sectorVisibility ( sectortype * sec )
{
// Beware of wraparound madness...
int v = sec - > visibility ;
return v ? ( ( uint8_t ) ( v + 16 ) ) / 16.f : 1.f ;
}
2021-04-03 20:51:31 +00:00
inline const float hw_density = 0.35f ;
2021-04-07 22:47:07 +00:00
int checkTranslucentReplacement ( FTextureID picnum , int pal ) ;
inline bool maskWallHasTranslucency ( const walltype * wall )
{
return ( wall - > cstat & CSTAT_WALL_TRANSLUCENT ) | | checkTranslucentReplacement ( tileGetTexture ( wall - > picnum ) - > GetID ( ) , wall - > pal ) ;
}
2021-12-04 18:08:50 +00:00
inline bool spriteHasTranslucency ( const tspritetype * tspr )
2021-04-07 22:47:07 +00:00
{
if ( ( tspr - > cstat & CSTAT_SPRITE_TRANSLUCENT ) | | //(tspr->clipdist & TSPR_FLAGS_DRAW_LAST) ||
2021-12-22 20:06:31 +00:00
( tspr - > ownerActor - > sprext . alpha ) )
2021-04-07 22:47:07 +00:00
return true ;
return checkTranslucentReplacement ( tileGetTexture ( tspr - > picnum ) - > GetID ( ) , tspr - > pal ) ;
}
2021-12-04 18:08:50 +00:00
inline void SetSpriteTranslucency ( const tspritetype * sprite , float & alpha , FRenderStyle & RenderStyle )
2021-04-08 17:45:18 +00:00
{
bool trans = ( sprite - > cstat & CSTAT_SPRITE_TRANSLUCENT ) ;
if ( trans )
{
2021-12-17 19:24:48 +00:00
RenderStyle = GetRenderStyle ( 0 , ! ! ( sprite - > cstat & CSTAT_SPRITE_TRANS_FLIP ) ) ;
alpha = GetAlphaFromBlend ( ( sprite - > cstat & CSTAT_SPRITE_TRANS_FLIP ) ? DAMETH_TRANS2 : DAMETH_TRANS1 , 0 ) ;
2021-04-08 17:45:18 +00:00
}
else
{
RenderStyle = LegacyRenderStyles [ STYLE_Translucent ] ;
alpha = 1.f ;
}
2021-12-22 20:06:31 +00:00
alpha * = 1.f - sprite - > ownerActor - > sprext . alpha ;
2021-04-08 17:45:18 +00:00
}
2021-04-10 07:57:03 +00:00
//==========================================================================
//
//
//
//==========================================================================
extern PalEntry GlobalMapFog ;
extern float GlobalFogDensity ;
2021-05-15 08:40:25 +00:00
__forceinline void SetLightAndFog ( FRenderState & state , PalEntry fade , int palette , int shade , float visibility , float alpha )
2021-04-10 07:57:03 +00:00
{
// Fog must be done before the texture so that the texture selector can override it.
bool foggy = ( GlobalMapFog | | ( fade & 0xffffff ) ) ;
auto ShadeDiv = lookups . tables [ palette ] . ShadeFactor ;
2021-05-15 08:40:25 +00:00
if ( shade = = 127 ) state . SetObjectColor ( 0xff000000 ) ; // 127 is generally used for shadow objects that must be black, even in foggy areas.
2021-04-13 22:45:35 +00:00
2021-04-10 07:57:03 +00:00
// Disable brightmaps if non-black fog is used.
if ( ShadeDiv > = 1 / 1000.f & & foggy )
{
state . EnableFog ( 1 ) ;
float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale ( numshades - shade , 150 , numshades ) ;
state . SetFog ( ( GlobalMapFog ) ? GlobalMapFog : fade , density * hw_density ) ;
state . SetSoftLightLevel ( 255 ) ;
state . SetLightParms ( 128.f , 1 / 1000.f ) ;
}
2021-04-12 16:57:10 +00:00
else
2021-04-10 07:57:03 +00:00
{
state . EnableFog ( 0 ) ;
state . SetFog ( 0 , 0 ) ;
2021-05-16 16:50:54 +00:00
state . SetSoftLightLevel ( gl_fogmode ! = 0 & & ShadeDiv > = 1 / 1000.f ? max ( 0 , 255 - Scale ( shade , 255 , numshades ) ) : 255 ) ;
2021-04-21 20:48:55 +00:00
state . SetLightParms ( visibility , ShadeDiv / ( numshades - 2 ) ) ;
2021-04-10 07:57:03 +00:00
}
// The shade rgb from the tint is ignored here.
state . SetColor ( globalr * ( 1 / 255.f ) , globalg * ( 1 / 255.f ) , globalb * ( 1 / 255.f ) , alpha ) ;
}