2021-03-18 20:50:02 +00:00
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2000-2016 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
// the Free Software Foundation, either version 3 of the License, or
// (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_flat . cpp
* * Flat processing
* *
*/
# include "matrix.h"
# include "hw_dynlightdata.h"
# include "hw_cvars.h"
# include "hw_clock.h"
# include "hw_material.h"
# include "hw_drawinfo.h"
# include "flatvertices.h"
# include "hw_lightbuffer.h"
# include "hw_drawstructs.h"
# include "hw_renderstate.h"
2021-03-19 22:11:23 +00:00
# include "sectorgeometry.h"
2021-03-18 20:50:02 +00:00
# ifdef _DEBUG
CVAR ( Int , gl_breaksec , - 1 , 0 )
# endif
extern PalEntry GlobalMapFog ;
extern float GlobalFogDensity ;
//==========================================================================
//
//
//
//==========================================================================
#if 0
void HWFlat : : SetupLights ( HWDrawInfo * di , FLightNode * node , FDynLightData & lightdata , int portalgroup )
{
Plane p ;
lightdata . Clear ( ) ;
if ( renderstyle = = STYLE_Add & & ! di - > Level - > lightadditivesurfaces )
{
dynlightindex = - 1 ;
return ; // no lights on additively blended surfaces.
}
while ( node )
{
FDynamicLight * light = node - > lightsource ;
if ( ! light - > IsActive ( ) )
{
node = node - > nextLight ;
continue ;
}
iter_dlightf + + ;
// we must do the side check here because gl_GetLight needs the correct plane orientation
// which we don't have for Legacy-style 3D-floors
double planeh = plane . plane . ZatPoint ( light - > Pos ) ;
if ( ( planeh < light - > Z ( ) & & ceiling ) | | ( planeh > light - > Z ( ) & & ! ceiling ) )
{
node = node - > nextLight ;
continue ;
}
p . Set ( plane . plane . Normal ( ) , plane . plane . fD ( ) ) ;
draw_dlightf + = GetLight ( lightdata , portalgroup , p , light , false ) ;
node = node - > nextLight ;
}
dynlightindex = screen - > mLights - > UploadLights ( lightdata ) ;
}
# endif
//==========================================================================
//
//
//
//==========================================================================
void HWFlat : : MakeVertices ( )
{
2021-03-26 19:28:44 +00:00
if ( vertcount > 0 ) return ;
2021-03-28 19:00:24 +00:00
bool canvas = texture - > isHardwareCanvas ( ) ;
2021-03-26 19:28:44 +00:00
if ( sprite = = nullptr )
2021-03-18 20:50:02 +00:00
{
2021-03-26 19:28:44 +00:00
auto mesh = sectorGeometry . get ( sec - sector , plane ) ;
if ( ! mesh ) return ;
auto ret = screen - > mVertexData - > AllocVertices ( mesh - > vertices . Size ( ) ) ;
auto vp = ret . first ;
2021-03-30 18:30:35 +00:00
float base = ( plane = = 0 ? sec - > floorz : sec - > ceilingz ) * ( 1 / - 256.f ) ;
2021-03-26 19:28:44 +00:00
for ( unsigned i = 0 ; i < mesh - > vertices . Size ( ) ; i + + )
{
auto & pt = mesh - > vertices [ i ] ;
auto & uv = mesh - > texcoords [ i ] ;
2021-03-30 18:30:35 +00:00
vp - > SetVertex ( pt . X , base + pt . Z , pt . Y ) ;
2021-03-28 19:00:24 +00:00
vp - > SetTexCoord ( uv . X , canvas ? 1.f - uv . Y : uv . Y ) ;
2021-03-26 19:28:44 +00:00
vp + + ;
}
vertindex = ret . second ;
vertcount = mesh - > vertices . Size ( ) ;
}
else
{
vec2_t pos [ 4 ] ;
GetFlatSpritePosition ( sprite , sprite - > pos . vec2 , pos , true ) ;
auto ret = screen - > mVertexData - > AllocVertices ( 6 ) ;
auto vp = ret . first ;
float x = ! ( sprite - > cstat & CSTAT_SECTOR_XFLIP ) ? 0.f : 1.f ;
float y = ! ( sprite - > cstat & CSTAT_SECTOR_YFLIP ) ? 0.f : 1.f ;
for ( unsigned i = 0 ; i < 6 ; i + + )
{
const static unsigned indices [ ] = { 0 , 1 , 2 , 0 , 2 , 3 } ;
int j = indices [ i ] ;
vp - > SetVertex ( pos [ j ] . x * ( 1 / 16.f ) , z , pos [ j ] . y * ( 1 / - 16.f ) ) ;
2021-03-28 19:00:24 +00:00
if ( ! canvas ) vp - > SetTexCoord ( j = = 1 | | j = = 2 ? 1.f - x : x , j = = 2 | | j = = 3 ? 1.f - y : y ) ;
else vp - > SetTexCoord ( j = = 1 | | j = = 2 ? 1.f - x : x , j = = 2 | | j = = 3 ? y : 1.f - y ) ;
2021-03-26 19:28:44 +00:00
vp + + ;
}
vertindex = ret . second ;
vertcount = 6 ;
2021-03-18 20:50:02 +00:00
}
}
//==========================================================================
//
//
//
//==========================================================================
void HWFlat : : DrawFlat ( HWDrawInfo * di , FRenderState & state , bool translucent )
{
2021-03-30 17:58:42 +00:00
if ( screen - > BuffersArePersistent ( ) & & ! sprite )
2021-03-18 20:50:02 +00:00
{
MakeVertices ( ) ;
}
# ifdef _DEBUG
if ( sec - sector = = gl_breaksec )
{
int a = 0 ;
}
# endif
2021-03-26 19:28:44 +00:00
if ( ! sprite )
{
auto mesh = sectorGeometry . get ( sec - sector , plane ) ;
state . SetNormal ( mesh - > normal ) ;
}
else
{
if ( z < di - > Viewpoint . Pos . Z ) state . SetNormal ( { 0 , 1 , 0 } ) ;
else state . SetNormal ( { 0 , - 1 , 0 } ) ;
}
2021-03-18 20:50:02 +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 ;
// 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 ) ;
state . SetSoftLightLevel ( 255 ) ;
state . SetLightParms ( 128.f , 1 / 1000.f ) ;
}
else
{
state . EnableFog ( 0 ) ;
state . SetFog ( 0 , 0 ) ;
state . SetSoftLightLevel ( ShadeDiv > = 1 / 1000.f ? 255 - Scale ( shade , 255 , numshades ) : 255 ) ;
state . SetLightParms ( visibility , ShadeDiv / ( numshades - 2 ) ) ;
}
// The shade rgb from the tint is ignored here.
2021-03-27 22:12:41 +00:00
state . SetColorAlpha ( PalEntry ( 255 , globalr , globalg , globalb ) , alpha ) ;
2021-03-18 20:50:02 +00:00
if ( translucent )
{
2021-03-27 22:12:41 +00:00
if ( RenderStyle . BlendOp ! = STYLEOP_Add )
{
state . EnableBrightmap ( false ) ;
}
2021-03-26 19:28:44 +00:00
state . SetRenderStyle ( RenderStyle ) ;
2021-03-27 22:12:41 +00:00
state . SetTextureMode ( RenderStyle ) ;
2021-03-18 20:50:02 +00:00
if ( ! texture - > GetTranslucency ( ) ) state . AlphaFunc ( Alpha_GEqual , gl_mask_threshold ) ;
else state . AlphaFunc ( Alpha_GEqual , 0.f ) ;
}
2021-03-29 18:18:49 +00:00
state . SetMaterial ( texture , UF_Texture , 0 , sprite = = nullptr ? CLAMP_NONE : CLAMP_XY , TRANSLATION ( Translation_Remap + curbasepal , palette ) , - 1 ) ;
2021-03-18 20:50:02 +00:00
state . SetLightIndex ( dynlightindex ) ;
state . Draw ( DT_Triangles , vertindex , vertcount ) ;
vertexcount + = vertcount ;
2021-03-22 11:07:29 +00:00
if ( translucent ) state . SetRenderStyle ( LegacyRenderStyles [ STYLE_Translucent ] ) ;
2021-03-27 22:12:41 +00:00
state . EnableBrightmap ( true ) ;
2021-03-18 20:50:02 +00:00
//state.SetObjectColor(0xffffffff);
//state.SetAddColor(0);
//state.ApplyTextureManipulation(nullptr);
}
//==========================================================================
//
// HWFlat::PutFlat
//
// submit to the renderer
//
//==========================================================================
void HWFlat : : PutFlat ( HWDrawInfo * di , int whichplane )
{
2021-03-26 19:28:44 +00:00
vertcount = 0 ;
2021-03-19 22:11:23 +00:00
plane = whichplane ;
2021-03-30 17:58:42 +00:00
if ( ! screen - > BuffersArePersistent ( ) | | sprite ) // should be made static buffer content later (when the logic is working)
2021-03-18 20:50:02 +00:00
{
#if 0
if ( di - > Level - > HasDynamicLights & & texture ! = nullptr & & ! di - > isFullbrightScene ( ) & & ! ( hacktype & ( SSRF_PLANEHACK | SSRF_FLOODHACK ) ) )
{
SetupLights ( di , section - > lighthead , lightdata , sector - > PortalGroup ) ;
}
# endif
MakeVertices ( ) ;
}
di - > AddFlat ( this ) ;
rendered_flats + + ;
}
//==========================================================================
//
// Process a sector's flats for rendering
// This function is only called once per sector.
// Subsequent subsectors are just quickly added to the ss_renderflags array
//
//==========================================================================
void HWFlat : : ProcessSector ( HWDrawInfo * di , sectortype * frontsector , int which )
{
# ifdef _DEBUG
if ( frontsector - sector = = gl_breaksec )
{
int a = 0 ;
}
# endif
dynlightindex = - 1 ;
const auto & vp = di - > Viewpoint ;
float florz , ceilz ;
2021-03-18 22:22:51 +00:00
PlanesAtPoint ( frontsector , vp . Pos . X * 16.f , vp . Pos . Y * - 16.f , & ceilz , & florz ) ;
2021-03-18 20:50:02 +00:00
fade = lookups . getFade ( frontsector - > floorpal ) ; // fog is per sector.
visibility = sectorVisibility ( frontsector ) ;
sec = frontsector ;
2021-03-26 19:28:44 +00:00
sprite = nullptr ;
2021-03-18 20:50:02 +00:00
//
//
//
// do floors
//
//
//
if ( ( which & SSRF_RENDERFLOOR ) & & ! ( frontsector - > floorstat & CSTAT_SECTOR_SKY ) & & florz < = vp . Pos . Z )
{
// process the original floor first.
2021-03-28 20:29:13 +00:00
shade = clamp ( frontsector - > floorshade , 0 , numshades - 1 ) ;
2021-03-18 20:50:02 +00:00
palette = frontsector - > floorpal ;
2021-03-30 21:27:11 +00:00
stack = frontsector - > portalflags = = PORTAL_SECTOR_FLOOR | | frontsector - > portalflags = = PORTAL_SECTOR_FLOOR_REFLECT ;
2021-03-18 20:50:02 +00:00
2021-03-30 21:27:11 +00:00
if ( stack & & ( frontsector - > floorstat & CSTAT_SECTOR_METHOD ) )
2021-03-18 20:50:02 +00:00
{
2021-03-30 21:27:11 +00:00
RenderStyle = GetRenderStyle ( 0 , ! ! ( frontsector - > floorstat & CSTAT_SECTOR_TRANS_INVERT ) ) ;
alpha = GetAlphaFromBlend ( ( frontsector - > floorstat & CSTAT_SECTOR_TRANS_INVERT ) ? DAMETH_TRANS2 : DAMETH_TRANS1 , 0 ) ;
2021-03-18 20:50:02 +00:00
}
else
2021-03-30 21:27:11 +00:00
{
RenderStyle = STYLE_Translucent ;
alpha = 1.f ;
}
2021-03-18 20:50:02 +00:00
if ( alpha ! = 0.f )
{
int tilenum = frontsector - > floorpicnum ;
2021-03-20 15:46:06 +00:00
setgotpic ( tilenum ) ;
2021-03-18 20:50:02 +00:00
tileUpdatePicnum ( & tilenum , tilenum , 0 ) ;
texture = tileGetTexture ( tilenum ) ;
if ( texture & & texture - > isValid ( ) )
{
//iboindex = frontsector->iboindex[sector_t::floor];
PutFlat ( di , 0 ) ;
}
}
}
//
//
//
// do ceilings
//
//
//
if ( ( which & SSRF_RENDERCEILING ) & & ! ( frontsector - > ceilingstat & CSTAT_SECTOR_SKY ) & & ceilz > = vp . Pos . Z )
{
// process the original ceiling first.
2021-03-28 20:29:13 +00:00
shade = clamp ( frontsector - > ceilingshade , 0 , numshades - 1 ) ;
2021-03-18 20:50:02 +00:00
palette = frontsector - > ceilingpal ;
2021-03-30 21:27:11 +00:00
stack = frontsector - > portalflags = = PORTAL_SECTOR_CEILING | | frontsector - > portalflags = = PORTAL_SECTOR_CEILING_REFLECT ;
2021-03-18 20:50:02 +00:00
2021-03-30 21:27:11 +00:00
if ( stack & & ( frontsector - > ceilingstat & CSTAT_SECTOR_METHOD ) )
2021-03-18 20:50:02 +00:00
{
2021-03-30 21:27:11 +00:00
RenderStyle = GetRenderStyle ( 0 , ! ! ( frontsector - > ceilingstat & CSTAT_SECTOR_TRANS_INVERT ) ) ;
alpha = GetAlphaFromBlend ( ( frontsector - > ceilingstat & CSTAT_SECTOR_TRANS_INVERT ) ? DAMETH_TRANS2 : DAMETH_TRANS1 , 0 ) ;
2021-03-18 20:50:02 +00:00
}
2021-03-30 21:27:11 +00:00
else
{
RenderStyle = STYLE_Translucent ;
alpha = 1.f ;
}
2021-03-18 20:50:02 +00:00
if ( alpha ! = 0.f )
{
//iboindex = frontsector->iboindex[sector_t::ceiling];
int tilenum = frontsector - > ceilingpicnum ;
2021-03-20 15:46:06 +00:00
setgotpic ( tilenum ) ;
2021-03-18 20:50:02 +00:00
tileUpdatePicnum ( & tilenum , tilenum , 0 ) ;
texture = tileGetTexture ( tilenum ) ;
if ( texture & & texture - > isValid ( ) )
{
//iboindex = frontsector->iboindex[sector_t::floor];
PutFlat ( di , 1 ) ;
}
}
}
}
2021-03-26 19:28:44 +00:00
void HWFlat : : ProcessFlatSprite ( HWDrawInfo * di , spritetype * sprite , sectortype * sector )
{
int tilenum = sprite - > picnum ;
texture = tileGetTexture ( tilenum ) ;
z = sprite - > z * ( 1 / - 256.f ) ;
if ( z = = di - > Viewpoint . Pos . Z ) return ; // looking right at the edge.
visibility = sectorVisibility ( & sector [ sprite - > sectnum ] ) ; // *(4.f / 5.f); // The factor comes directly from Polymost. No idea why this uses a different visibility setting. Bad projection math?
// Weird Build logic that really makes no sense.
if ( ( sprite - > cstat & CSTAT_SPRITE_ONE_SIDED ) ! = 0 & & ( di - > Viewpoint . Pos . Z < z ) = = ( ( sprite - > cstat & CSTAT_SPRITE_YFLIP ) = = 0 ) )
return ;
if ( texture & & texture - > isValid ( ) )
{
this - > sprite = sprite ;
sec = sector ;
2021-03-28 20:29:13 +00:00
shade = clamp ( sprite - > shade , 0 , numshades - 1 ) ;
2021-03-26 19:28:44 +00:00
palette = sprite - > pal ;
fade = lookups . getFade ( sector [ sprite - > sectnum ] . floorpal ) ; // fog is per sector.
bool trans = ( sprite - > cstat & CSTAT_SPRITE_TRANSLUCENT ) ;
if ( trans )
{
RenderStyle = GetRenderStyle ( 0 , ! ! ( sprite - > cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT ) ) ;
alpha = GetAlphaFromBlend ( ( sprite - > cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT ) ? DAMETH_TRANS2 : DAMETH_TRANS1 , 0 ) ;
}
else
{
RenderStyle = LegacyRenderStyles [ STYLE_Translucent ] ;
alpha = 1.f ;
}
PutFlat ( di , 0 ) ;
}
}