This commit is contained in:
Rachael Alexanderson 2018-05-23 20:04:20 -04:00
commit e42a820b31
65 changed files with 1254 additions and 1012 deletions

View file

@ -120,9 +120,26 @@ Note: All <bool> fields default to false unless mentioned otherwise.
blockhitscan = <bool>; // Line blocks hitscan attacks
locknumber = <int>; // Line special is locked
arg0str = <string>; // Alternate string-based version of arg0
moreids = <string>; // Additional line IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
moreids = <string>; // Additional line IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
transparent = <bool>; // true = line is a Strife transparent line (alpha 0.25)
transparent = <bool>; // true = line is a Strife transparent line (alpha 0.25)
automapstyle = <integer>; // Explicit automap style. Possible values can be
// 0: Automap style is based on line properties (default).
// 1: One-sided wall.
// 2: Two-sided wall.
// 3: Floor levels of front and back sectors are different.
// 4: Ceiling levels of front and back sectors are different.
// 5: 3D floor border.
// 6: Wall with special non-door action.
// 7: Secret door.
// 8: Wall not seen yet.
// 9: Locked door.
// 10: Intra-level teleporter.
// 11: Inter-level or game-ending teleporter.
// 12: Unexplored secret wall.
// 13: Portal line.
revealed = <bool>; // true = line is initially visible on automap.
* Note about arg0str
@ -171,14 +188,14 @@ Note: All <bool> fields default to false unless mentioned otherwise.
yscaleceiling = <float>; // Y texture scale of ceiling texture, Default = 1.0.
rotationfloor = <float>; // Rotation of floor texture in degrees, Default = 0.0.
rotationceiling = <float>; // Rotation of ceiling texture in degrees, Default = 0.0.
ceilingplane_a = <float>; // Define the plane equation for the sector's ceiling. Default is a horizontal plane at 'heightceiling'.
ceilingplane_b = <float>; // 'heightceiling' will still be used to calculate texture alignment.
ceilingplane_c = <float>; // The plane equation will only be used if all 4 values are given.
ceilingplane_d = <float>;
floorplane_a = <float>; // Define the plane equation for the sector's floor. Default is a horizontal plane at 'heightfloor'.
floorplane_b = <float>; // 'heightfloor' will still be used to calculate texture alignment.
floorplane_c = <float>; // The plane equation will only be used if all 4 values are given.
floorplane_d = <float>;
ceilingplane_a = <float>; // Define the plane equation for the sector's ceiling. Default is a horizontal plane at 'heightceiling'.
ceilingplane_b = <float>; // 'heightceiling' will still be used to calculate texture alignment.
ceilingplane_c = <float>; // The plane equation will only be used if all 4 values are given.
ceilingplane_d = <float>;
floorplane_a = <float>; // Define the plane equation for the sector's floor. Default is a horizontal plane at 'heightfloor'.
floorplane_b = <float>; // 'heightfloor' will still be used to calculate texture alignment.
floorplane_c = <float>; // The plane equation will only be used if all 4 values are given.
floorplane_d = <float>;
lightfloor = <integer>; // The floor's light level. Default is 0.
lightceiling = <integer>; // The ceiling's light level. Default is 0.
lightfloorabsolute = <bool>; // true = 'lightfloor' is an absolute value. Default is
@ -196,8 +213,8 @@ Note: All <bool> fields default to false unless mentioned otherwise.
fadecolor = <integer>; // Sector's fog color as RRGGBB value, default = 0x000000.
desaturation = <float>; // Color desaturation factor. 0 = none, 1 = full, default = 0.
silent = <bool>; // Actors in this sector make no sound,
nofallingdamage = <bool>; // Falling damage is disabled in this sector
noattack = <bool>; // Blocks monster attacks in this sector.
nofallingdamage = <bool>; // Falling damage is disabled in this sector
noattack = <bool>; // Blocks monster attacks in this sector.
dropactors = <bool>; // Actors drop with instantly moving floors (*)
norespawn = <bool>; // Players can not respawn in this sector
soundsequence = <string>; // The sound sequence to play when this sector moves. Placing a
@ -215,21 +232,21 @@ Note: All <bool> fields default to false unless mentioned otherwise.
damagehazard = <bool>; // Changes damage model to Strife's delayed damage for the given sector. Default = false.
floorterrain = <string>; // Sets the terrain for the sector's floor. Default = 'use the flat texture's terrain definition.'
ceilingterrain = <string>; // Sets the terrain for the sector's ceiling. Default = 'use the flat texture's terrain definition.'
floor_reflect = <float>; // reflectiveness of floor (OpenGL only, not functional on sloped sectors)
ceiling_reflect = <float>; // reflectiveness of ceiling (OpenGL only, not functional on sloped sectors)
fogdensity = <integer>; // Sets an explicit fog density for the sector, overriding the default calculation from the light level. Value range is 0-510,
// 0 meaning that the default is to be used, 2 equalling the density of a light level of 250, and 255 equalling the density of
// a light level of 0. (OpenGL only)
floorglowcolor = <integer>; // Sector's floor glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing. (OpenGL 3.x and newer only)
floorglowheight = <float>; // Height of floor glow. This only has an effect for the sector's own glow color, but not for a texture based glow. (OpenGL 3.x and newer only)
ceilingglowcolor = <integer>; // Sector's ceiling glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing. (OpenGL 3.x and newer only)
ceilingglowheight = <float>; // Height of ceiling glow. This only has an effect for the sector's own glow color, but not for a texture based glow. (OpenGL 3.x and newer only)
color_floor = <int>; // Material color of sector's floor. Default is white (0xffffff)
color_ceiling = <int>; // Material color of sector's ceiling. Default is white (0xffffff)
color_walltop = <int>; // Material color of top of sector's sidedefs. In OpenGL 2.x and the software renderer this will define the entire wall's color) Default is white (0xffffff)
color_wallbottom = <int>; // Material color of bottom of sector's sidedefs (OpenGL 3.x and later only) Default is white (0xffffff)
color_sprites = <int>; // Material color of sprites in sector. Default is white (0xffffff)
floor_reflect = <float>; // reflectiveness of floor (OpenGL only, not functional on sloped sectors)
ceiling_reflect = <float>; // reflectiveness of ceiling (OpenGL only, not functional on sloped sectors)
fogdensity = <integer>; // Sets an explicit fog density for the sector, overriding the default calculation from the light level. Value range is 0-510,
// 0 meaning that the default is to be used, 2 equalling the density of a light level of 250, and 255 equalling the density of
// a light level of 0. (OpenGL only)
floorglowcolor = <integer>; // Sector's floor glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing. (OpenGL 3.x and newer only)
floorglowheight = <float>; // Height of floor glow. This only has an effect for the sector's own glow color, but not for a texture based glow. (OpenGL 3.x and newer only)
ceilingglowcolor = <integer>; // Sector's ceiling glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing. (OpenGL 3.x and newer only)
ceilingglowheight = <float>; // Height of ceiling glow. This only has an effect for the sector's own glow color, but not for a texture based glow. (OpenGL 3.x and newer only)
color_floor = <int>; // Material color of sector's floor. Default is white (0xffffff)
color_ceiling = <int>; // Material color of sector's ceiling. Default is white (0xffffff)
color_walltop = <int>; // Material color of top of sector's sidedefs. In OpenGL 2.x and the software renderer this will define the entire wall's color) Default is white (0xffffff)
color_wallbottom = <int>; // Material color of bottom of sector's sidedefs (OpenGL 3.x and later only) Default is white (0xffffff)
color_sprites = <int>; // Material color of sprites in sector. Default is white (0xffffff)
portal_ceil_blocksound = <bool> // ceiling portal blocks sound.
portal_ceil_disabled = <bool> // ceiling portal disabled.
@ -241,8 +258,8 @@ Note: All <bool> fields default to false unless mentioned otherwise.
portal_floor_nopass = <bool> // ceiling portal blocks movement if true.
portal_floor_norender = <bool> // ceiling portal not rendered.
portal_floor_overlaytype = <string> // defines translucency style, can either be "translucent" or "additive". Default is "translucent".
* Note about dropactors
The spec requires this to be false by default. Currently, however, ZDoom assumes this to be true
@ -253,37 +270,37 @@ Note: All <bool> fields default to false unless mentioned otherwise.
thing
{
skill# = <bool> // Unlike the base spec, # can range from 1-16.
class# = <bool> // Unlike the base spec, # can range from 1-16.
conversation = <int> // Assigns a conversation dialogue to this thing.
skill# = <bool> // Unlike the base spec, # can range from 1-16.
class# = <bool> // Unlike the base spec, # can range from 1-16.
conversation = <int> // Assigns a conversation dialogue to this thing.
// Parameter is the conversation ID, 0 meaning none.
countsecret = <bool>; // Picking up this actor counts as a secret.
arg0str = <string>; // Alternate string-based version of arg0
gravity = <float>; // Set per-actor gravity. Positive values are multiplied with the class's property,
// negative values are used as their absolute. Default = 1.0.
health = <float>; // Set per-actor health. Positive values are multiplied with the class's property,
// negative values are used as their absolute. Default = 1.
renderstyle = <string>; // Set per-actor render style, overriding the class default. Possible values can be "normal",
// "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil",
// "addstencil", "shaded", "addshaded", "translucent", "fuzzy", "optfuzzy", "soultrans" and "shadow".
// Default is an empty string for no change.
fillcolor = <integer>; // Fill color used by the "stencil", "addstencil" and "translucentstencil" rendestyles, as RRGGBB value, default = 0x000000.
alpha = <float>; // Translucency of this actor (if applicable to renderstyle), default is 1.0.
score = <int>; // Score value of this actor, overriding the class default if not null. Default = 0.
pitch = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
roll = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
scalex = <float>; // Vertical scaling on thing. Default = 0 (ignored).
scaley = <float>; // Horizontal scaling on thing. Default = 0 (ignored).
scale = <float>; // Vertical and horizontal scaling on thing. Default = 0 (ignored).
floatbobphase = <int>; // Sets the thing's floatbobphase. Valid phase values are 0-63. Default = -1 (use actor class default).
gravity = <float>; // Set per-actor gravity. Positive values are multiplied with the class's property,
// negative values are used as their absolute. Default = 1.0.
health = <float>; // Set per-actor health. Positive values are multiplied with the class's property,
// negative values are used as their absolute. Default = 1.
renderstyle = <string>; // Set per-actor render style, overriding the class default. Possible values can be "normal",
// "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil",
// "addstencil", "shaded", "addshaded", "translucent", "fuzzy", "optfuzzy", "soultrans" and "shadow".
// Default is an empty string for no change.
fillcolor = <integer>; // Fill color used by the "stencil", "addstencil" and "translucentstencil" rendestyles, as RRGGBB value, default = 0x000000.
alpha = <float>; // Translucency of this actor (if applicable to renderstyle), default is 1.0.
score = <int>; // Score value of this actor, overriding the class default if not null. Default = 0.
pitch = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
roll = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
scalex = <float>; // Vertical scaling on thing. Default = 0 (ignored).
scaley = <float>; // Horizontal scaling on thing. Default = 0 (ignored).
scale = <float>; // Vertical and horizontal scaling on thing. Default = 0 (ignored).
floatbobphase = <int>; // Sets the thing's floatbobphase. Valid phase values are 0-63. Default = -1 (use actor class default).
* Note about arg0str
For things with ACS specials (80-86 and 226), if arg0str is present and non-null, it
will be used as the name of the script to execute, and arg0 will be ignored.
On dynamic lights, arg0str can be used to set a color by name, this will supersede all args which are normally used to define a color.
On dynamic lights, arg0str can be used to set a color by name, this will supersede all args which are normally used to define a color.
}
@ -430,6 +447,10 @@ sector material colors.
1.29 04.02.2018
arg0str in dynamic lights.
1.30 20.05.2018
Added automapstyle and revealed linedef properties.
Replaced tabs with spaces.
===============================================================================
EOF
===============================================================================

View file

@ -809,7 +809,6 @@ set( FASTMATH_SOURCES
textures/hires/hqnx/hq4x.cpp
textures/hires/xbr/xbrz.cpp
textures/hires/xbr/xbrz_old.cpp
gl/scene/gl_bsp.cpp
gl/scene/gl_drawinfo.cpp
gl/scene/gl_flats.cpp
gl/scene/gl_sprite.cpp
@ -819,7 +818,10 @@ set( FASTMATH_SOURCES
gl/scene/gl_portal.cpp
gl/scene/gl_walls_draw.cpp
gl_load/gl_load.c
hwrenderer/postprocessing/hw_postprocess_cvars.cpp
hwrenderer/postprocessing/hw_postprocessshader.cpp
hwrenderer/dynlights/hw_dynlightdata.cpp
hwrenderer/scene/hw_bsp.cpp
hwrenderer/scene/hw_fakeflat.cpp
hwrenderer/scene/hw_decal.cpp
hwrenderer/scene/hw_drawlist.cpp

View file

@ -324,6 +324,30 @@ struct AMColorset
}
};
//=============================================================================
//
// automap colors forced by linedef
//
//=============================================================================
static const int AUTOMAP_LINE_COLORS[AMLS_COUNT] =
{
-1, // AMLS_Default (unused)
AMColorset::WallColor, // AMLS_OneSided,
AMColorset::TSWallColor, // AMLS_TwoSided
AMColorset::FDWallColor, // AMLS_FloorDiff
AMColorset::CDWallColor, // AMLS_CeilingDiff
AMColorset::EFWallColor, // AMLS_ExtraFloor
AMColorset::SpecialWallColor, // AMLS_Special
AMColorset::SecretWallColor, // AMLS_Secret
AMColorset::NotSeenColor, // AMLS_NotSeen
AMColorset::LockedColor, // AMLS_Locked
AMColorset::IntraTeleportColor, // AMLS_IntraTeleport
AMColorset::InterTeleportColor, // AMLS_InterTeleport
AMColorset::UnexploredSecretColor, // AMLS_UnexploredSecret
AMColorset::PortalColor, // AMLS_Portal
};
//=============================================================================
//
// predefined colorsets
@ -2583,6 +2607,13 @@ void AM_drawWalls (bool allmap)
}
}
if (line.automapstyle > AMLS_Default && line.automapstyle < AMLS_COUNT
&& (am_cheat == 0 || am_cheat >= 4))
{
AM_drawMline(&l, AUTOMAP_LINE_COLORS[line.automapstyle]);
continue;
}
if (portalmode)
{
AM_drawMline(&l, AMColors.PortalColor);
@ -2658,7 +2689,7 @@ void AM_drawWalls (bool allmap)
AM_drawMline(&l, AMColors.TSWallColor);
}
}
else if (allmap)
else if (allmap || (line.flags & ML_REVEALED))
{
if ((line.flags & ML_DONTDRAW) && (am_cheat == 0 || am_cheat >= 4))
{

View file

@ -170,6 +170,7 @@ enum ELineFlags : unsigned
ML_BLOCKSIGHT = 0x04000000, // blocks monster line of sight
ML_BLOCKHITSCAN = 0x08000000, // blocks hitscan attacks
ML_3DMIDTEX_IMPASS = 0x10000000, // [TP] if 3D midtex, behaves like a height-restricted ML_BLOCKING
ML_REVEALED = 0x20000000, // set if revealed in automap
ML_PORTALCONNECT = 0x80000000, // for internal use only: This line connects to a sector with a linked portal (used to speed up sight checks.)
};

View file

@ -586,8 +586,9 @@ bool FDrawInfo::PutFlatCompat(GLFlat *flat, bool fog)
int list = list_indices[masked][foggy];
auto newflat = gl_drawinfo->dldrawlists[list].NewFlat();
auto newflat = dldrawlists[list].NewFlat();
*newflat = *flat;
newflat->iboindex = -1; // don't use the vertex buffer with legacy lights to ensure all passes use the same render logic.
return true;
}
@ -720,7 +721,7 @@ void FDrawInfo::DrawLightsCompat(GLFlat *flat, int pass)
for (int i = 0; i<flat->sector->subsectorcount; i++)
{
subsector_t * sub = flat->sector->subsectors[i];
if (gl_drawinfo->ss_renderflags[sub->Index()] & flat->renderflags)
if (ss_renderflags[sub->Index()] & flat->renderflags)
{
DrawSubsectorLights(flat, sub, pass);
}
@ -730,8 +731,8 @@ void FDrawInfo::DrawLightsCompat(GLFlat *flat, int pass)
if (!(flat->renderflags&SSRF_RENDER3DPLANES))
{
gl_subsectorrendernode * node = (flat->renderflags&SSRF_RENDERFLOOR) ?
gl_drawinfo->GetOtherFloorPlanes(flat->sector->sectornum) :
gl_drawinfo->GetOtherCeilingPlanes(flat->sector->sectornum);
GetOtherFloorPlanes(flat->sector->sectornum) :
GetOtherCeilingPlanes(flat->sector->sectornum);
while (node)
{
@ -854,7 +855,7 @@ void FDrawInfo::RenderLightsCompat(GLWall *wall, int pass)
//
//==========================================================================
void GLSceneDrawer::RenderMultipassStuff()
void GLSceneDrawer::RenderMultipassStuff(FDrawInfo *di)
{
// First pass: empty background with sector light only
@ -864,8 +865,8 @@ void GLSceneDrawer::RenderMultipassStuff()
gl_RenderState.EnableTexture(false);
gl_RenderState.EnableBrightmap(false);
gl_RenderState.Apply();
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(gl_drawinfo, GLPASS_ALL);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(gl_drawinfo, GLPASS_ALL);
di->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(di, GLPASS_ALL);
di->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(di, GLPASS_ALL);
// Part 2: masked geometry. This is set up so that only pixels with alpha>0.5 will show
// This creates a blank surface that only fills the nontransparent parts of the texture
@ -873,18 +874,18 @@ void GLSceneDrawer::RenderMultipassStuff()
gl_RenderState.SetTextureMode(TM_MASK);
gl_RenderState.EnableBrightmap(true);
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(gl_drawinfo, GLPASS_ALL);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(gl_drawinfo, GLPASS_ALL);
di->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(di, GLPASS_ALL);
di->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(di, GLPASS_ALL);
// Part 3: The base of fogged surfaces, including the texture
gl_RenderState.EnableBrightmap(false);
gl_RenderState.SetTextureMode(TM_MODULATE);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(gl_drawinfo, GLPASS_ALL);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(gl_drawinfo, GLPASS_ALL);
di->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(di, GLPASS_ALL);
di->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(di, GLPASS_ALL);
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(gl_drawinfo, GLPASS_ALL);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(gl_drawinfo, GLPASS_ALL);
di->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(di, GLPASS_ALL);
di->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(di, GLPASS_ALL);
// second pass: draw lights
glDepthMask(false);
@ -895,10 +896,10 @@ void GLSceneDrawer::RenderMultipassStuff()
gl_RenderState.BlendFunc(GL_ONE, GL_ONE);
glDepthFunc(GL_EQUAL);
if (level.lightmode == 8) gl_RenderState.SetSoftLightLevel(255);
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX);
di->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(di, GLPASS_LIGHTTEX);
di->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(di, GLPASS_LIGHTTEX);
di->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(di, GLPASS_LIGHTTEX);
di->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(di, GLPASS_LIGHTTEX);
gl_RenderState.BlendEquation(GL_FUNC_ADD);
}
else gl_lights = false;
@ -910,11 +911,11 @@ void GLSceneDrawer::RenderMultipassStuff()
gl_RenderState.EnableFog(false);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0);
glDepthFunc(GL_LEQUAL);
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(gl_drawinfo, GLPASS_TEXONLY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(gl_drawinfo, GLPASS_TEXONLY);
di->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(di, GLPASS_TEXONLY);
di->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(di, GLPASS_TEXONLY);
gl_RenderState.AlphaFunc(GL_GREATER, gl_mask_threshold);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(gl_drawinfo, GLPASS_TEXONLY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(gl_drawinfo, GLPASS_TEXONLY);
di->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(di, GLPASS_TEXONLY);
di->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(di, GLPASS_TEXONLY);
// fourth pass: additive lights
gl_RenderState.EnableFog(true);
@ -922,14 +923,14 @@ void GLSceneDrawer::RenderMultipassStuff()
glDepthFunc(GL_EQUAL);
if (gl_SetupLightTexture())
{
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX_FOGGY);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX_FOGGY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX_FOGGY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX_FOGGY);
di->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(di, GLPASS_LIGHTTEX_ADDITIVE);
di->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(di, GLPASS_LIGHTTEX_ADDITIVE);
di->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(di, GLPASS_LIGHTTEX_ADDITIVE);
di->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(di, GLPASS_LIGHTTEX_ADDITIVE);
di->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(di, GLPASS_LIGHTTEX_FOGGY);
di->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(di, GLPASS_LIGHTTEX_FOGGY);
di->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(di, GLPASS_LIGHTTEX_FOGGY);
di->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(di, GLPASS_LIGHTTEX_FOGGY);
}
else gl_lights = false;

View file

@ -125,6 +125,8 @@ void FSimpleVertexBuffer::set(FSimpleVertex *verts, int count)
FFlatVertexBuffer::FFlatVertexBuffer(int width, int height)
: FVertexBuffer(!gl.legacyMode), FFlatVertexGenerator(width, height)
{
ibo_id = 0;
if (gl.buffermethod != BM_LEGACY) glGenBuffers(1, &ibo_id);
switch (gl.buffermethod)
{
case BM_PERSISTENT:
@ -157,6 +159,7 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height)
mIndex = mCurIndex = 0;
mNumReserved = NUM_RESERVED;
mMap = map;
Map();
memcpy(map, &vbo_shadowdata[0], mNumReserved * sizeof(FFlatVertex));
Unmap();
@ -170,6 +173,11 @@ FFlatVertexBuffer::~FFlatVertexBuffer()
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
if (ibo_id != 0)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &ibo_id);
}
if (gl.legacyMode)
{
delete[] map;
@ -188,6 +196,7 @@ void FFlatVertexBuffer::OutputResized(int width, int height)
void FFlatVertexBuffer::BindVBO()
{
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id);
if (!gl.legacyMode)
{
glVertexAttribPointer(VATTR_VERTEX, 3, GL_FLOAT, false, sizeof(FFlatVertex), &VTO->x);
@ -215,7 +224,7 @@ void FFlatVertexBuffer::Map()
unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
gl_RenderState.ResetVertexBuffer();
map = (FFlatVertex*)glMapBufferRange(GL_ARRAY_BUFFER, 0, bytesize, GL_MAP_WRITE_BIT|GL_MAP_UNSYNCHRONIZED_BIT);
mMap = map = (FFlatVertex*)glMapBufferRange(GL_ARRAY_BUFFER, 0, bytesize, GL_MAP_WRITE_BIT|GL_MAP_UNSYNCHRONIZED_BIT);
}
}
@ -227,7 +236,7 @@ void FFlatVertexBuffer::Unmap()
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
gl_RenderState.ResetVertexBuffer();
glUnmapBuffer(GL_ARRAY_BUFFER);
map = nullptr;
mMap = map = nullptr;
}
}
@ -240,9 +249,17 @@ void FFlatVertexBuffer::Unmap()
void FFlatVertexBuffer::CreateVBO()
{
vbo_shadowdata.Resize(mNumReserved);
FFlatVertexGenerator::CreateVertices();
if (!gl.legacyMode)
{
FFlatVertexGenerator::CreateVertices();
}
mCurIndex = mIndex = vbo_shadowdata.Size();
Map();
memcpy(map, &vbo_shadowdata[0], vbo_shadowdata.Size() * sizeof(FFlatVertex));
Unmap();
if (ibo_id > 0)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ibo_data.Size() * sizeof(uint32_t), &ibo_data[0], GL_STATIC_DRAW);
}
}

View file

@ -95,6 +95,7 @@ public:
class FFlatVertexBuffer : public FVertexBuffer, public FFlatVertexGenerator
{
unsigned int ibo_id;
FFlatVertex *map;
unsigned int mIndex;
std::atomic<unsigned int> mCurIndex;
@ -177,14 +178,9 @@ public:
#endif
void CheckPlanes(sector_t *sector)
uint32_t *GetIndexPointer() const
{
FFlatVertexGenerator::CheckPlanes(sector, map);
}
void CheckUpdate(sector_t *sector)
{
FFlatVertexGenerator::CheckUpdate(sector, map);
return ibo_id == 0 ? &ibo_data[0] : nullptr;
}
void Reset()

View file

@ -36,6 +36,7 @@ class FGLModelRenderer : public FModelRenderer
public:
FGLModelRenderer(int mli) : modellightindex(mli)
{}
ModelRendererType GetType() const override { return GLModelRendererType; }
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override;
void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override;
IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override;

View file

@ -85,7 +85,6 @@ extern bool NoInterpolateView;
FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
{
framebuffer = fb;
mClipPortal = nullptr;
mCurrentPortal = nullptr;
mMirrorCount = 0;
mPlaneMirrorCount = 0;
@ -121,9 +120,6 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mCustomPostProcessShaders = nullptr;
}
void gl_LoadModels();
void gl_FlushModels();
void FGLRenderer::Initialize(int width, int height)
{
mBuffers = new FGLRenderBuffers();
@ -175,7 +171,6 @@ void FGLRenderer::Initialize(int width, int height)
SetupLevel();
mShaderManager = new FShaderManager;
mSamplerManager = new FSamplerManager;
gl_LoadModels();
GLPortal::Initialize();
}
@ -184,7 +179,7 @@ FGLRenderer::~FGLRenderer()
{
GLPortal::Shutdown();
gl_FlushModels();
FlushModels();
AActor::DeleteAllAttachedLights();
FMaterial::FlushAll();
if (legacyShaders) delete legacyShaders;

View file

@ -87,7 +87,7 @@ class FGLRenderer
public:
OpenGLFrameBuffer *framebuffer;
GLPortal *mClipPortal;
//GLPortal *mClipPortal;
GLPortal *mCurrentPortal;
int mMirrorCount;
int mPlaneMirrorCount;

View file

@ -62,7 +62,7 @@ static void matrixToGL(const VSMatrix &mat, int loc)
void FRenderState::Reset()
{
mTextureEnabled = true;
mClipLineEnabled = mSplitEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
mClipLineShouldBeActive = mClipLineEnabled = mSplitEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
mColorMask[0] = mColorMask[1] = mColorMask[2] = mColorMask[3] = true;
currentColorMask[0] = currentColorMask[1] = currentColorMask[2] = currentColorMask[3] = true;
mFogColor.d = -1;

View file

@ -81,6 +81,7 @@ class FRenderState
bool mGlowEnabled;
bool mSplitEnabled;
bool mClipLineEnabled;
bool mClipLineShouldBeActive;
bool mBrightmapEnabled;
bool mColorMask[4];
bool currentColorMask[4];
@ -201,6 +202,11 @@ public:
return mClipLineEnabled;
}
bool GetClipLineShouldBeActive()
{
return mClipLineShouldBeActive;
}
void SetClipHeight(float height, float direction);
void SetNormal(FVector3 norm)
@ -326,6 +332,11 @@ public:
glDisable(GL_CLIP_DISTANCE0);
}
}
else
{
// this needs to be flagged because in this case per-sector plane rendering needs to be disabled if a clip plane is active.
mClipLineShouldBeActive = on;
}
}
void EnableBrightmap(bool on)

View file

@ -44,7 +44,7 @@
#include "gl/renderer/gl_quaddrawer.h"
#include "gl/dynlights/gl_lightbuffer.h"
FDrawInfo * gl_drawinfo;
static FDrawInfo * gl_drawinfo;
FDrawInfoList di_list;
//==========================================================================
@ -81,13 +81,13 @@ void FDrawInfo::DoDrawSorted(HWDrawList *dl, SortNode * head)
DoDrawSorted(dl, head->left);
gl_RenderState.SetClipSplit(clipsplit);
}
dl->DoDraw(gl_drawinfo, GLPASS_TRANSLUCENT, head->itemindex, true);
dl->DoDraw(this, GLPASS_TRANSLUCENT, head->itemindex, true);
if (head->equal)
{
SortNode * ehead=head->equal;
while (ehead)
{
dl->DoDraw(gl_drawinfo, GLPASS_TRANSLUCENT, ehead->itemindex, true);
dl->DoDraw(this, GLPASS_TRANSLUCENT, ehead->itemindex, true);
ehead=ehead->equal;
}
}
@ -191,26 +191,26 @@ FDrawInfo::~FDrawInfo()
// Sets up a new drawinfo struct
//
//==========================================================================
void FDrawInfo::StartDrawInfo(GLSceneDrawer *drawer)
// OpenGL has no use for multiple clippers so use the same one for all DrawInfos.
static Clipper staticClipper;
FDrawInfo *FDrawInfo::StartDrawInfo(GLSceneDrawer *drawer)
{
FDrawInfo *di=di_list.GetNew();
di->mDrawer = drawer;
di->mVBO = GLRenderer->mVBO;
di->mClipper = &staticClipper;
staticClipper.Clear();
di->FixedColormap = drawer->FixedColormap;
di->StartScene();
return di;
}
void FDrawInfo::StartScene()
{
ClearBuffers();
sectorrenderflags.Resize(level.sectors.Size());
ss_renderflags.Resize(level.subsectors.Size());
no_renderflags.Resize(level.subsectors.Size());
memset(&sectorrenderflags[0], 0, level.sectors.Size() * sizeof(sectorrenderflags[0]));
memset(&ss_renderflags[0], 0, level.subsectors.Size() * sizeof(ss_renderflags[0]));
memset(&no_renderflags[0], 0, level.nodes.Size() * sizeof(no_renderflags[0]));
next = gl_drawinfo;
gl_drawinfo = this;
for (int i = 0; i < GLDL_TYPES; i++) drawlists[i].Reset();
@ -392,8 +392,8 @@ void FDrawInfo::FloodUpperGap(seg_t * seg)
{
wallseg ws;
sector_t ffake, bfake;
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, &ffake, mDrawer->in_area, true);
sector_t * fakebsector = hw_FakeFlat(seg->backsector, &bfake, mDrawer->in_area, false);
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, &ffake, in_area, true);
sector_t * fakebsector = hw_FakeFlat(seg->backsector, &bfake, in_area, false);
vertex_t * v1, * v2;
@ -444,8 +444,8 @@ void FDrawInfo::FloodLowerGap(seg_t * seg)
{
wallseg ws;
sector_t ffake, bfake;
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, &ffake, mDrawer->in_area, true);
sector_t * fakebsector = hw_FakeFlat(seg->backsector, &bfake, mDrawer->in_area, false);
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, &ffake, in_area, true);
sector_t * fakebsector = hw_FakeFlat(seg->backsector, &bfake, in_area, false);
vertex_t * v1, * v2;
@ -505,12 +505,6 @@ void FDrawInfo::AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *su
portal->GetRenderState()->AddSubsector(sub);
}
int FDrawInfo::ClipPoint(const DVector3 &pos)
{
return GLRenderer->mClipPortal->ClipPoint(pos);
}
std::pair<FFlatVertex *, unsigned int> FDrawInfo::AllocVertices(unsigned int count)
{
unsigned int index = -1;

View file

@ -121,6 +121,7 @@ struct FDrawInfo : public HWDrawInfo
void ProcessLights(GLFlat *flat, bool istrans);
void DrawSubsector(GLFlat *flat, subsector_t * sub);
void SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub, int *dli);
void SetupSectorLights(GLFlat *flat, int pass, int *dli);
// Sprite drawer
void DrawSprite(GLSprite *sprite, int pass);
@ -133,9 +134,8 @@ struct FDrawInfo : public HWDrawInfo
// These two may be moved to the API independent part of the renderer later.
void ProcessLowerMinisegs(TArray<seg_t *> &lowersegs) override;
void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) override;
int ClipPoint(const DVector3 &pos) override;
static void StartDrawInfo(GLSceneDrawer *drawer);
static FDrawInfo *StartDrawInfo(GLSceneDrawer *drawer);
static void EndDrawInfo();
gl_subsectorrendernode * GetOtherFloorPlanes(unsigned int sector)
@ -162,8 +162,6 @@ public:
};
extern FDrawInfo * gl_drawinfo;
void gl_SetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblending);
#endif

View file

@ -82,6 +82,34 @@ void FDrawInfo::SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub,
//
//==========================================================================
void FDrawInfo::SetupSectorLights(GLFlat *flat, int pass, int *dli)
{
if (dli != NULL && *dli != -1)
{
gl_RenderState.ApplyLightIndex(GLRenderer->mLights->GetIndex(*dli));
(*dli)++;
return;
}
if (flat->SetupSectorLights(pass, flat->sector, lightdata))
{
int d = GLRenderer->mLights->UploadLights(lightdata);
if (pass == GLPASS_LIGHTSONLY)
{
GLRenderer->mLights->StoreIndex(d);
}
else
{
gl_RenderState.ApplyLightIndex(d);
}
}
}
//==========================================================================
//
//
//
//==========================================================================
void FDrawInfo::DrawSubsector(GLFlat *flat, subsector_t * sub)
{
if (gl.buffermethod != BM_DEFERRED)
@ -136,23 +164,30 @@ void FDrawInfo::DrawSubsector(GLFlat *flat, subsector_t * sub)
void FDrawInfo::ProcessLights(GLFlat *flat, bool istrans)
{
flat->dynlightindex = GLRenderer->mLights->GetIndexPtr();
// Draw the subsectors belonging to this sector
for (int i=0; i< flat->sector->subsectorcount; i++)
if (flat->sector->ibocount > 0 && !gl_RenderState.GetClipLineShouldBeActive())
{
subsector_t * sub = flat->sector->subsectors[i];
if (gl_drawinfo->ss_renderflags[sub->Index()]& flat->renderflags || istrans)
SetupSectorLights(flat, GLPASS_LIGHTSONLY, nullptr);
}
else
{
// Draw the subsectors belonging to this sector
for (int i = 0; i < flat->sector->subsectorcount; i++)
{
SetupSubsectorLights(flat, GLPASS_LIGHTSONLY, sub, nullptr);
subsector_t * sub = flat->sector->subsectors[i];
if (ss_renderflags[sub->Index()] & flat->renderflags || istrans)
{
SetupSubsectorLights(flat, GLPASS_LIGHTSONLY, sub, nullptr);
}
}
}
// Draw the subsectors assigned to it due to missing textures
if (!(flat->renderflags&SSRF_RENDER3DPLANES))
{
gl_subsectorrendernode * node = (flat->renderflags&SSRF_RENDERFLOOR)?
gl_drawinfo->GetOtherFloorPlanes(flat->sector->sectornum) :
gl_drawinfo->GetOtherCeilingPlanes(flat->sector->sectornum);
GetOtherFloorPlanes(flat->sector->sectornum) :
GetOtherCeilingPlanes(flat->sector->sectornum);
while (node)
{
@ -175,33 +210,44 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool
gl_RenderState.Apply();
if (gl.legacyMode) processlights = false;
if (flat->vboindex >= 0)
auto vcount = flat->sector->ibocount;
if (vcount > 0 && !gl_RenderState.GetClipLineShouldBeActive())
{
int index = flat->vboindex;
if (processlights) SetupSectorLights(flat, GLPASS_ALL, &dli);
drawcalls.Clock();
glDrawElements(GL_TRIANGLES, vcount, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + flat->iboindex);
drawcalls.Unclock();
flatvertices += vcount;
flatprimitives++;
}
else if (flat->iboindex >= 0)
{
int index = flat->iboindex;
for (int i=0; i<flat->sector->subsectorcount; i++)
{
subsector_t * sub = flat->sector->subsectors[i];
if (sub->numlines <= 2) continue;
if (gl_drawinfo->ss_renderflags[sub->Index()]& flat->renderflags || istrans)
if (ss_renderflags[sub->Index()]& flat->renderflags || istrans)
{
if (processlights) SetupSubsectorLights(flat, GLPASS_ALL, sub, &dli);
drawcalls.Clock();
glDrawArrays(GL_TRIANGLE_FAN, index, sub->numlines);
glDrawElements(GL_TRIANGLES, (sub->numlines - 2) * 3, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + index);
drawcalls.Unclock();
flatvertices += sub->numlines;
flatprimitives++;
}
index += sub->numlines;
index += (sub->numlines - 2) * 3;
}
}
else
{
// Draw the subsectors belonging to this sector
// (can this case even happen?)
for (int i=0; i<flat->sector->subsectorcount; i++)
{
subsector_t * sub = flat->sector->subsectors[i];
if (gl_drawinfo->ss_renderflags[sub->Index()]& flat->renderflags || istrans)
if (ss_renderflags[sub->Index()]& flat->renderflags || istrans)
{
if (processlights) SetupSubsectorLights(flat, GLPASS_ALL, sub, &dli);
DrawSubsector(flat, sub);
@ -213,8 +259,8 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool
if (!(flat->renderflags&SSRF_RENDER3DPLANES))
{
gl_subsectorrendernode * node = (flat->renderflags&SSRF_RENDERFLOOR)?
gl_drawinfo->GetOtherFloorPlanes(flat->sector->sectornum) :
gl_drawinfo->GetOtherCeilingPlanes(flat->sector->sectornum);
GetOtherFloorPlanes(flat->sector->sectornum) :
GetOtherCeilingPlanes(flat->sector->sectornum);
while (node)
{
@ -399,7 +445,7 @@ void FDrawInfo::AddFlat(GLFlat *flat, bool fog)
bool masked = flat->gltexture->isMasked() && ((flat->renderflags&SSRF_RENDER3DPLANES) || flat->stack);
list = masked ? GLDL_MASKEDFLATS : GLDL_PLAINFLATS;
}
auto newflat = gl_drawinfo->drawlists[list].NewFlat();
auto newflat = drawlists[list].NewFlat();
*newflat = *flat;
}

View file

@ -41,7 +41,6 @@
#include "gl/renderer/gl_renderstate.h"
#include "gl/data/gl_vertexbuffer.h"
#include "hwrenderer/scene/hw_clipper.h"
#include "gl/scene/gl_drawinfo.h"
#include "gl/scene/gl_portal.h"
#include "gl/scene/gl_scenedrawer.h"
#include "gl/stereo3d/scoped_color_mask.h"
@ -160,8 +159,9 @@ void GLPortal::DrawPortalStencil()
//
//-----------------------------------------------------------------------------
bool GLPortal::Start(bool usestencil, bool doquery)
bool GLPortal::Start(bool usestencil, bool doquery, FDrawInfo **pDi)
{
*pDi = nullptr;
rendered_portals++;
Clocker c(PortalAll);
if (usestencil)
@ -228,7 +228,7 @@ bool GLPortal::Start(bool usestencil, bool doquery)
return false;
}
}
FDrawInfo::StartDrawInfo(drawer);
*pDi = FDrawInfo::StartDrawInfo(drawer);
}
else
{
@ -256,7 +256,7 @@ bool GLPortal::Start(bool usestencil, bool doquery)
{
if (NeedDepthBuffer())
{
FDrawInfo::StartDrawInfo(drawer);
*pDi = FDrawInfo::StartDrawInfo(drawer);
}
else
{
@ -271,15 +271,12 @@ bool GLPortal::Start(bool usestencil, bool doquery)
savedshowviewer = r_viewpoint.showviewer;
savedAngles = r_viewpoint.Angles;
savedviewactor=GLRenderer->mViewActor;
savedviewarea=drawer->in_area;
savedviewpath[0] = r_viewpoint.Path[0];
savedviewpath[1] = r_viewpoint.Path[1];
savedvisibility = r_viewpoint.camera ? r_viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0);
PrevPortal = GLRenderer->mCurrentPortal;
PrevClipPortal = GLRenderer->mClipPortal;
GLRenderer->mClipPortal = NULL; // Portals which need this have to set it themselves
GLRenderer->mCurrentPortal = this;
if (PrevPortal != NULL) PrevPortal->PushState();
@ -287,14 +284,14 @@ bool GLPortal::Start(bool usestencil, bool doquery)
}
inline void GLPortal::ClearClipper()
inline void GLPortal::ClearClipper(FDrawInfo *di)
{
DAngle angleOffset = deltaangle(savedAngles.Yaw, r_viewpoint.Angles.Yaw);
drawer->clipper.Clear();
di->mClipper->Clear();
// Set the clipper to the minimal visible area
drawer->clipper.SafeAddClipRange(0,0xffffffff);
di->mClipper->SafeAddClipRange(0,0xffffffff);
for (unsigned int i = 0; i < lines.Size(); i++)
{
DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - savedViewPos).Angle() + angleOffset;
@ -302,16 +299,16 @@ inline void GLPortal::ClearClipper()
if (deltaangle(endAngle, startAngle) < 0)
{
drawer->clipper.SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs());
di->mClipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs());
}
}
// and finally clip it to the visible area
angle_t a1 = drawer->FrustumAngle();
if (a1 < ANGLE_180) drawer->clipper.SafeAddClipRangeRealAngles(r_viewpoint.Angles.Yaw.BAMs() + a1, r_viewpoint.Angles.Yaw.BAMs() - a1);
if (a1 < ANGLE_180) di->mClipper->SafeAddClipRangeRealAngles(r_viewpoint.Angles.Yaw.BAMs() + a1, r_viewpoint.Angles.Yaw.BAMs() - a1);
// lock the parts that have just been clipped out.
drawer->clipper.SetSilhouette();
di->mClipper->SetSilhouette();
}
//-----------------------------------------------------------------------------
@ -326,7 +323,6 @@ void GLPortal::End(bool usestencil)
Clocker c(PortalAll);
if (PrevPortal != NULL) PrevPortal->PopState();
GLRenderer->mCurrentPortal = PrevPortal;
GLRenderer->mClipPortal = PrevClipPortal;
if (usestencil)
{
@ -340,7 +336,6 @@ void GLPortal::End(bool usestencil)
r_viewpoint.ActorPos = savedViewActorPos;
r_viewpoint.Angles = savedAngles;
GLRenderer->mViewActor=savedviewactor;
drawer->in_area=savedviewarea;
if (r_viewpoint.camera != nullptr) r_viewpoint.camera->renderflags = (r_viewpoint.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility;
drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1));
@ -399,7 +394,6 @@ void GLPortal::End(bool usestencil)
r_viewpoint.Pos = savedViewPos;
r_viewpoint.Angles = savedAngles;
GLRenderer->mViewActor=savedviewactor;
drawer->in_area=savedviewarea;
if (r_viewpoint.camera != nullptr) r_viewpoint.camera->renderflags |= savedvisibility;
drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));
@ -432,11 +426,11 @@ void GLPortal::End(bool usestencil)
//-----------------------------------------------------------------------------
void GLPortal::StartFrame()
{
GLPortal * p=NULL;
GLPortal * p = nullptr;
portals.Push(p);
if (renderdepth==0)
if (renderdepth == 0)
{
inskybox=false;
inskybox = false;
screen->instack[sector_t::floor] = screen->instack[sector_t::ceiling] = 0;
}
renderdepth++;
@ -560,26 +554,6 @@ GLPortal * GLPortal::FindPortal(const void * src)
}
//-----------------------------------------------------------------------------
//
// Save/RestoreMapSection
//
// saves CurrentMapSection for a recursive call of SceneDrawer::DrawScene
//
//-----------------------------------------------------------------------------
void GLPortal::SaveMapSection()
{
SavedMapSection = std::move(drawer->CurrentMapSections);
drawer->CurrentMapSections.Resize(SavedMapSection.Size());
drawer->CurrentMapSections.Zero();
}
void GLPortal::RestoreMapSection()
{
drawer->CurrentMapSections = std::move(SavedMapSection);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
@ -596,7 +570,7 @@ void GLPortal::RestoreMapSection()
//
//-----------------------------------------------------------------------------
void GLSkyboxPortal::DrawContents()
void GLSkyboxPortal::DrawContents(FDrawInfo *di)
{
int old_pm = PlaneMirrorMode;
int saved_extralight = r_viewpoint.extralight;
@ -629,15 +603,15 @@ void GLSkyboxPortal::DrawContents()
inskybox = true;
drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1));
drawer->SetViewArea();
ClearClipper();
di->SetViewArea();
ClearClipper(di);
int mapsection = R_PointInSubsector(r_viewpoint.Pos)->mapsection;
SaveMapSection();
drawer->CurrentMapSections.Set(mapsection);
di->CurrentMapSections.Zero();
di->CurrentMapSections.Set(mapsection);
drawer->DrawScene(DM_SKYPORTAL);
drawer->DrawScene(di, DM_SKYPORTAL);
portal->mFlags &= ~PORTSF_INSKYBOX;
inskybox = false;
gl_RenderState.SetDepthClamp(oldclamp);
@ -645,8 +619,6 @@ void GLSkyboxPortal::DrawContents()
PlaneMirrorMode = old_pm;
r_viewpoint.extralight = saved_extralight;
RestoreMapSection();
}
//-----------------------------------------------------------------------------
@ -688,7 +660,7 @@ GLSectorStackPortal::~GLSectorStackPortal()
//
//-----------------------------------------------------------------------------
static uint8_t SetCoverage(void *node)
static uint8_t SetCoverage(FDrawInfo *di, void *node)
{
if (level.nodes.Size() == 0)
{
@ -697,18 +669,18 @@ static uint8_t SetCoverage(void *node)
if (!((size_t)node & 1)) // Keep going until found a subsector
{
node_t *bsp = (node_t *)node;
uint8_t coverage = SetCoverage(bsp->children[0]) | SetCoverage(bsp->children[1]);
gl_drawinfo->no_renderflags[bsp->Index()] = coverage;
uint8_t coverage = SetCoverage(di, bsp->children[0]) | SetCoverage(di, bsp->children[1]);
di->no_renderflags[bsp->Index()] = coverage;
return coverage;
}
else
{
subsector_t *sub = (subsector_t *)((uint8_t *)node - 1);
return gl_drawinfo->ss_renderflags[sub->Index()] & SSRF_SEEN;
return di->ss_renderflags[sub->Index()] & SSRF_SEEN;
}
}
void GLSectorStackPortal::SetupCoverage()
void GLSectorStackPortal::SetupCoverage(FDrawInfo *di)
{
for(unsigned i=0; i<subsectors.Size(); i++)
{
@ -717,11 +689,11 @@ void GLSectorStackPortal::SetupCoverage()
for(int j=0;j<sub->portalcoverage[plane].sscount; j++)
{
subsector_t *dsub = &::level.subsectors[sub->portalcoverage[plane].subsectors[j]];
drawer->CurrentMapSections.Set(dsub->mapsection);
gl_drawinfo->ss_renderflags[dsub->Index()] |= SSRF_SEEN;
di->CurrentMapSections.Set(dsub->mapsection);
di->ss_renderflags[dsub->Index()] |= SSRF_SEEN;
}
}
SetCoverage(::level.HeadNode());
SetCoverage(di, ::level.HeadNode());
}
//-----------------------------------------------------------------------------
@ -729,7 +701,7 @@ void GLSectorStackPortal::SetupCoverage()
// GLSectorStackPortal::DrawContents
//
//-----------------------------------------------------------------------------
void GLSectorStackPortal::DrawContents()
void GLSectorStackPortal::DrawContents(FDrawInfo *di)
{
FSectorPortalGroup *portal = origin;
@ -741,21 +713,19 @@ void GLSectorStackPortal::DrawContents()
if (origin->plane != -1) screen->instack[origin->plane]++;
drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));
SaveMapSection();
SetupCoverage();
ClearClipper();
SetupCoverage(di);
ClearClipper(di);
// If the viewpoint is not within the portal, we need to invalidate the entire clip area.
// The portal will re-validate the necessary parts when its subsectors get traversed.
subsector_t *sub = R_PointInSubsector(r_viewpoint.Pos);
if (!(gl_drawinfo->ss_renderflags[sub->Index()] & SSRF_SEEN))
if (!(di->ss_renderflags[sub->Index()] & SSRF_SEEN))
{
drawer->clipper.SafeAddClipRange(0, ANGLE_MAX);
drawer->clipper.SetBlocked(true);
di->mClipper->SafeAddClipRange(0, ANGLE_MAX);
di->mClipper->SetBlocked(true);
}
drawer->DrawScene(DM_PORTAL);
RestoreMapSection();
drawer->DrawScene(di, DM_PORTAL);
if (origin->plane != -1) screen->instack[origin->plane]--;
}
@ -776,7 +746,7 @@ void GLSectorStackPortal::DrawContents()
//
//-----------------------------------------------------------------------------
void GLPlaneMirrorPortal::DrawContents()
void GLPlaneMirrorPortal::DrawContents(FDrawInfo *di)
{
if (renderdepth > r_mirror_recursions)
{
@ -798,10 +768,10 @@ void GLPlaneMirrorPortal::DrawContents()
PlaneMirrorFlag++;
drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1));
ClearClipper();
ClearClipper(di);
gl_RenderState.SetClipHeight(planez, PlaneMirrorMode < 0 ? -1.f : 1.f);
drawer->DrawScene(DM_PORTAL);
drawer->DrawScene(di, DM_PORTAL);
gl_RenderState.SetClipHeight(0.f, 0.f);
PlaneMirrorFlag--;
PlaneMirrorMode = old_pm;
@ -897,7 +867,7 @@ int GLLinePortal::ClipPoint(const DVector2 &pos)
// R_EnterMirror
//
//-----------------------------------------------------------------------------
void GLMirrorPortal::DrawContents()
void GLMirrorPortal::DrawContents(FDrawInfo *di)
{
if (renderdepth>r_mirror_recursions)
{
@ -905,7 +875,7 @@ void GLMirrorPortal::DrawContents()
return;
}
GLRenderer->mClipPortal = this;
di->mClipPortal = this;
DAngle StartAngle = r_viewpoint.Angles.Yaw;
DVector3 StartPos = r_viewpoint.Pos;
@ -965,18 +935,18 @@ void GLMirrorPortal::DrawContents()
MirrorFlag++;
drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));
drawer->clipper.Clear();
di->mClipper->Clear();
angle_t af = drawer->FrustumAngle();
if (af<ANGLE_180) drawer->clipper.SafeAddClipRangeRealAngles(r_viewpoint.Angles.Yaw.BAMs()+af, r_viewpoint.Angles.Yaw.BAMs()-af);
if (af<ANGLE_180) di->mClipper->SafeAddClipRangeRealAngles(r_viewpoint.Angles.Yaw.BAMs()+af, r_viewpoint.Angles.Yaw.BAMs()-af);
angle_t a2 = linedef->v1->GetClipAngle();
angle_t a1 = linedef->v2->GetClipAngle();
drawer->clipper.SafeAddClipRange(a1,a2);
di->mClipper->SafeAddClipRange(a1,a2);
gl_RenderState.SetClipLine(linedef);
gl_RenderState.EnableClipLine(true);
drawer->DrawScene(DM_PORTAL);
drawer->DrawScene(di, DM_PORTAL);
gl_RenderState.EnableClipLine(false);
MirrorFlag--;
@ -997,7 +967,7 @@ void GLMirrorPortal::DrawContents()
//
//
//-----------------------------------------------------------------------------
void GLLineToLinePortal::DrawContents()
void GLLineToLinePortal::DrawContents(FDrawInfo *di)
{
// TODO: Handle recursion more intelligently
if (renderdepth>r_mirror_recursions)
@ -1006,7 +976,7 @@ void GLLineToLinePortal::DrawContents()
return;
}
GLRenderer->mClipPortal = this;
di->mClipPortal = this;
line_t *origin = glport->lines[0]->mOrigin;
P_TranslatePortalXY(origin, r_viewpoint.Pos.X, r_viewpoint.Pos.Y);
@ -1031,8 +1001,6 @@ void GLLineToLinePortal::DrawContents()
}
SaveMapSection();
for (unsigned i = 0; i < lines.Size(); i++)
{
line_t *line = lines[i].seg->linedef->getPortalDestination();
@ -1040,23 +1008,22 @@ void GLLineToLinePortal::DrawContents()
if (line->sidedef[0]->Flags & WALLF_POLYOBJ)
sub = R_PointInSubsector(line->v1->fixX(), line->v1->fixY());
else sub = line->frontsector->subsectors[0];
drawer->CurrentMapSections.Set(sub->mapsection);
di->CurrentMapSections.Set(sub->mapsection);
}
GLRenderer->mViewActor = nullptr;
drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));
ClearClipper();
ClearClipper(di);
gl_RenderState.SetClipLine(glport->lines[0]->mDestination);
gl_RenderState.EnableClipLine(true);
drawer->DrawScene(DM_PORTAL);
drawer->DrawScene(di, DM_PORTAL);
gl_RenderState.EnableClipLine(false);
RestoreMapSection();
}
void GLLineToLinePortal::RenderAttached()
void GLLineToLinePortal::RenderAttached(FDrawInfo *di)
{
gl_drawinfo->ProcessActorsInPortal(glport, gl_drawinfo->mDrawer->in_area);
di->ProcessActorsInPortal(glport, di->in_area);
}
//-----------------------------------------------------------------------------
@ -1145,7 +1112,7 @@ GLHorizonPortal::GLHorizonPortal(GLHorizonInfo * pt, bool local)
// GLHorizonPortal::DrawContents
//
//-----------------------------------------------------------------------------
void GLHorizonPortal::DrawContents()
void GLHorizonPortal::DrawContents(FDrawInfo *di)
{
Clocker c(PortalAll);
@ -1216,7 +1183,7 @@ void GLHorizonPortal::DrawContents()
//
//-----------------------------------------------------------------------------
void GLEEHorizonPortal::DrawContents()
void GLEEHorizonPortal::DrawContents(FDrawInfo *di)
{
sector_t *sector = portal->mOrigin;
if (sector->GetTexture(sector_t::floor) == skyflatnum ||
@ -1225,7 +1192,7 @@ void GLEEHorizonPortal::DrawContents()
GLSkyInfo skyinfo;
skyinfo.init(sector->sky, 0);
GLSkyPortal sky(&skyinfo, true);
sky.DrawContents();
sky.DrawContents(di);
}
if (sector->GetTexture(sector_t::ceiling) != skyflatnum)
{
@ -1239,7 +1206,7 @@ void GLEEHorizonPortal::DrawContents()
horz.plane.Texheight = r_viewpoint.Pos.Z + fabs(horz.plane.Texheight);
}
GLHorizonPortal ceil(&horz, true);
ceil.DrawContents();
ceil.DrawContents(di);
}
if (sector->GetTexture(sector_t::floor) != skyflatnum)
{
@ -1253,7 +1220,7 @@ void GLEEHorizonPortal::DrawContents()
horz.plane.Texheight = r_viewpoint.Pos.Z - fabs(horz.plane.Texheight);
}
GLHorizonPortal floor(&horz, true);
floor.DrawContents();
floor.DrawContents(di);
}
}
@ -1281,3 +1248,9 @@ const char *GLLineToLinePortal::GetName() { return "LineToLine"; }
const char *GLHorizonPortal::GetName() { return "Horizon"; }
const char *GLEEHorizonPortal::GetName() { return "EEHorizon"; }
// This needs to remain on the renderer side until the portal interface can be abstracted.
void FSectorPortalGroup::AddSubsector(subsector_t *sub)
{
GLSectorStackPortal *glportal = GetRenderState();
glportal->AddSubsector(sub);
}

View file

@ -49,7 +49,7 @@ extern UniqueList<secplane_t> UniquePlaneMirrors;
struct GLEEHorizonPortal;
class GLSceneDrawer;
class GLPortal
class GLPortal : public IPortal
{
static TArray<GLPortal *> portals;
static int recursion;
@ -75,11 +75,8 @@ private:
DRotator savedAngles;
bool savedshowviewer;
AActor * savedviewactor;
area_t savedviewarea;
ActorRenderFlags savedvisibility;
GLPortal *PrevPortal;
GLPortal *PrevClipPortal;
BitArray SavedMapSection;
TArray<unsigned int> mPrimIndices;
protected:
@ -89,18 +86,16 @@ protected:
GLPortal(bool local = false) { if (!local) portals.Push(this); }
virtual ~GLPortal() { }
bool Start(bool usestencil, bool doquery);
bool Start(bool usestencil, bool doquery, FDrawInfo **pDi);
void End(bool usestencil);
virtual void DrawContents()=0;
virtual void DrawContents(FDrawInfo *di)=0;
virtual void * GetSource() const =0; // GetSource MUST be implemented!
void ClearClipper();
void ClearClipper(FDrawInfo *di);
virtual bool IsSky() { return false; }
virtual bool NeedCap() { return true; }
virtual bool NeedDepthBuffer() { return true; }
void ClearScreen();
virtual const char *GetName() = 0;
void SaveMapSection();
void RestoreMapSection();
virtual void PushState() {}
virtual void PopState() {}
@ -111,9 +106,10 @@ public:
// Start may perform an occlusion query. If that returns 0 there
// is no need to draw the stencil's contents and there's also no
// need to restore the affected area becasue there is none!
if (Start(usestencil, doquery))
FDrawInfo *di;
if (Start(usestencil, doquery, &di))
{
DrawContents();
DrawContents(di);
End(usestencil);
}
}
@ -130,11 +126,7 @@ public:
static bool isMirrored() { return !!((MirrorFlag ^ PlaneMirrorFlag) & 1); }
virtual int ClipSeg(seg_t *seg) { return PClip_Inside; }
virtual int ClipSubsector(subsector_t *sub) { return PClip_Inside; }
virtual int ClipPoint(const DVector2 &pos) { return PClip_Inside; }
virtual line_t *ClipLine() { return NULL; }
virtual void RenderAttached() {}
virtual void RenderAttached(FDrawInfo *di) {}
static void BeginScene();
static void StartFrame();
@ -205,7 +197,7 @@ struct GLMirrorPortal : public GLLinePortal
line_t * linedef;
protected:
virtual void DrawContents();
virtual void DrawContents(FDrawInfo *di);
virtual void * GetSource() const { return linedef; }
virtual const char *GetName();
@ -223,11 +215,11 @@ struct GLLineToLinePortal : public GLLinePortal
{
FLinePortalSpan *glport;
protected:
virtual void DrawContents();
virtual void DrawContents(FDrawInfo *di);
virtual void * GetSource() const { return glport; }
virtual const char *GetName();
virtual line_t *ClipLine() { return line(); }
virtual void RenderAttached();
virtual void RenderAttached(FDrawInfo *di);
public:
@ -244,7 +236,7 @@ struct GLSkyboxPortal : public GLPortal
FSectorPortal * portal;
protected:
virtual void DrawContents();
virtual void DrawContents(FDrawInfo *di);
virtual void * GetSource() const { return portal; }
virtual bool IsSky() { return true; }
virtual const char *GetName();
@ -266,7 +258,7 @@ struct GLSkyPortal : public GLPortal
friend struct GLEEHorizonPortal;
protected:
virtual void DrawContents();
virtual void DrawContents(FDrawInfo *di);
virtual void * GetSource() const { return origin; }
virtual bool IsSky() { return true; }
virtual bool NeedDepthBuffer() { return false; }
@ -290,7 +282,7 @@ struct GLSectorStackPortal : public GLPortal
TArray<subsector_t *> subsectors;
protected:
virtual ~GLSectorStackPortal();
virtual void DrawContents();
virtual void DrawContents(FDrawInfo *di);
virtual void * GetSource() const { return origin; }
virtual bool IsSky() { return true; } // although this isn't a real sky it can be handled as one.
virtual const char *GetName();
@ -302,7 +294,7 @@ public:
{
origin=pt;
}
void SetupCoverage();
void SetupCoverage(FDrawInfo *di);
void AddSubsector(subsector_t *sub)
{
subsectors.Push(sub);
@ -313,7 +305,7 @@ public:
struct GLPlaneMirrorPortal : public GLPortal
{
protected:
virtual void DrawContents();
virtual void DrawContents(FDrawInfo *di);
virtual void * GetSource() const { return origin; }
virtual const char *GetName();
virtual void PushState();
@ -338,7 +330,7 @@ struct GLHorizonPortal : public GLPortal
friend struct GLEEHorizonPortal;
protected:
virtual void DrawContents();
virtual void DrawContents(FDrawInfo *di);
virtual void * GetSource() const { return origin; }
virtual bool NeedDepthBuffer() { return false; }
virtual bool NeedCap() { return false; }
@ -354,7 +346,7 @@ struct GLEEHorizonPortal : public GLPortal
FSectorPortal * portal;
protected:
virtual void DrawContents();
virtual void DrawContents(FDrawInfo *di);
virtual void * GetSource() const { return portal; }
virtual bool NeedDepthBuffer() { return false; }
virtual bool NeedCap() { return false; }

View file

@ -92,29 +92,6 @@ angle_t GLSceneDrawer::FrustumAngle()
return a1;
}
//-----------------------------------------------------------------------------
//
// Sets the area the camera is in
//
//-----------------------------------------------------------------------------
void GLSceneDrawer::SetViewArea()
{
// The render_sector is better suited to represent the current position in GL
r_viewpoint.sector = R_PointInSubsector(r_viewpoint.Pos)->render_sector;
// Get the heightsec state from the render sector, not the current one!
if (r_viewpoint.sector->GetHeightSec())
{
in_area = r_viewpoint.Pos.Z <= r_viewpoint.sector->heightsec->floorplane.ZatPoint(r_viewpoint.Pos) ? area_below :
(r_viewpoint.Pos.Z > r_viewpoint.sector->heightsec->ceilingplane.ZatPoint(r_viewpoint.Pos) &&
!(r_viewpoint.sector->heightsec->MoreFlags&SECMF_FAKEFLOORONLY)) ? area_above : area_normal;
}
else
{
in_area = level.HasHeightSecs? area_default : area_normal; // depends on exposed lower sectors, if map contains heightsecs.
}
}
//-----------------------------------------------------------------------------
//
// resets the 3D viewport
@ -234,10 +211,10 @@ void GLSceneDrawer::SetupView(float vx, float vy, float vz, DAngle va, bool mirr
//
//-----------------------------------------------------------------------------
void GLSceneDrawer::CreateScene()
void GLSceneDrawer::CreateScene(FDrawInfo *di)
{
angle_t a1 = FrustumAngle();
InitClipper(r_viewpoint.Angles.Yaw.BAMs() + a1, r_viewpoint.Angles.Yaw.BAMs() - a1);
di->mClipper->SafeAddClipRangeRealAngles(r_viewpoint.Angles.Yaw.BAMs() + a1, r_viewpoint.Angles.Yaw.BAMs() - a1);
// reset the portal manager
GLPortal::StartFrame();
@ -251,29 +228,31 @@ void GLSceneDrawer::CreateScene()
GLRenderer->mVBO->Map();
GLRenderer->mLights->Begin();
SetView();
// Give the DrawInfo the viewpoint in fixed point because that's what the nodes are.
di->viewx = FLOAT2FIXED(r_viewpoint.Pos.X);
di->viewy = FLOAT2FIXED(r_viewpoint.Pos.Y);
validcount++; // used for processing sidedefs only once by the renderer.
di->mAngles = GLRenderer->mAngles;
di->mViewVector = GLRenderer->mViewVector;
di->mViewActor = GLRenderer->mViewActor;
di->mShadowMap = &GLRenderer->mShadowMap;
gl_drawinfo->clipPortal = !!GLRenderer->mClipPortal;
gl_drawinfo->mAngles = GLRenderer->mAngles;
gl_drawinfo->mViewVector = GLRenderer->mViewVector;
gl_drawinfo->mViewActor = GLRenderer->mViewActor;
gl_drawinfo->mShadowMap = &GLRenderer->mShadowMap;
RenderBSPNode (level.HeadNode());
gl_drawinfo->PreparePlayerSprites(r_viewpoint.sector, in_area);
di->RenderBSPNode (level.HeadNode());
di->PreparePlayerSprites(r_viewpoint.sector, di->in_area);
// Process all the sprites on the current portal's back side which touch the portal.
if (GLRenderer->mCurrentPortal != NULL) GLRenderer->mCurrentPortal->RenderAttached();
if (GLRenderer->mCurrentPortal != NULL) GLRenderer->mCurrentPortal->RenderAttached(di);
Bsp.Unclock();
// And now the crappy hacks that have to be done to avoid rendering anomalies.
// These cannot be multithreaded when the time comes because all these depend
// on the global 'validcount' variable.
gl_drawinfo->HandleMissingTextures(in_area); // Missing upper/lower textures
gl_drawinfo->HandleHackedSubsectors(); // open sector hacks for deep water
gl_drawinfo->ProcessSectorStacks(in_area); // merge visplanes of sector stacks
di->HandleMissingTextures(di->in_area); // Missing upper/lower textures
di->HandleHackedSubsectors(); // open sector hacks for deep water
di->ProcessSectorStacks(di->in_area); // merge visplanes of sector stacks
GLRenderer->mLights->Finish();
GLRenderer->mVBO->Unmap();
@ -289,7 +268,7 @@ void GLSceneDrawer::CreateScene()
//
//-----------------------------------------------------------------------------
void GLSceneDrawer::RenderScene(int recursion)
void GLSceneDrawer::RenderScene(FDrawInfo *di, int recursion)
{
RenderAll.Clock();
@ -303,11 +282,11 @@ void GLSceneDrawer::RenderScene(int recursion)
if (gl_sort_textures)
{
gl_drawinfo->drawlists[GLDL_PLAINWALLS].SortWalls();
gl_drawinfo->drawlists[GLDL_PLAINFLATS].SortFlats();
gl_drawinfo->drawlists[GLDL_MASKEDWALLS].SortWalls();
gl_drawinfo->drawlists[GLDL_MASKEDFLATS].SortFlats();
gl_drawinfo->drawlists[GLDL_MASKEDWALLSOFS].SortWalls();
di->drawlists[GLDL_PLAINWALLS].SortWalls();
di->drawlists[GLDL_PLAINFLATS].SortFlats();
di->drawlists[GLDL_MASKEDWALLS].SortWalls();
di->drawlists[GLDL_MASKEDFLATS].SortFlats();
di->drawlists[GLDL_MASKEDWALLSOFS].SortWalls();
}
// if we don't have a persistently mapped buffer, we have to process all the dynamic lights up front,
@ -315,10 +294,10 @@ void GLSceneDrawer::RenderScene(int recursion)
if (gl.lightmethod == LM_DEFERRED && level.HasDynamicLights && FixedColormap == CM_DEFAULT)
{
GLRenderer->mLights->Begin();
gl_drawinfo->drawlists[GLDL_PLAINFLATS].DrawFlats(gl_drawinfo, GLPASS_LIGHTSONLY);
gl_drawinfo->drawlists[GLDL_MASKEDFLATS].DrawFlats(gl_drawinfo, GLPASS_LIGHTSONLY);
gl_drawinfo->drawlists[GLDL_TRANSLUCENTBORDER].Draw(gl_drawinfo, GLPASS_LIGHTSONLY);
gl_drawinfo->drawlists[GLDL_TRANSLUCENT].Draw(gl_drawinfo, GLPASS_LIGHTSONLY, true);
di->drawlists[GLDL_PLAINFLATS].DrawFlats(di, GLPASS_LIGHTSONLY);
di->drawlists[GLDL_MASKEDFLATS].DrawFlats(di, GLPASS_LIGHTSONLY);
di->drawlists[GLDL_TRANSLUCENTBORDER].Draw(di, GLPASS_LIGHTSONLY);
di->drawlists[GLDL_TRANSLUCENT].Draw(di, GLPASS_LIGHTSONLY, true);
GLRenderer->mLights->Finish();
}
@ -336,7 +315,7 @@ void GLSceneDrawer::RenderScene(int recursion)
else // GL 2.x legacy mode
{
// process everything that needs to handle textured dynamic lights.
if (level.HasDynamicLights) RenderMultipassStuff();
if (level.HasDynamicLights) RenderMultipassStuff(di);
// The remaining lists which are unaffected by dynamic lights are just processed as normal.
pass = GLPASS_ALL;
@ -344,8 +323,8 @@ void GLSceneDrawer::RenderScene(int recursion)
gl_RenderState.EnableTexture(gl_texture);
gl_RenderState.EnableBrightmap(true);
gl_drawinfo->drawlists[GLDL_PLAINWALLS].DrawWalls(gl_drawinfo, pass);
gl_drawinfo->drawlists[GLDL_PLAINFLATS].DrawFlats(gl_drawinfo, pass);
di->drawlists[GLDL_PLAINWALLS].DrawWalls(di, pass);
di->drawlists[GLDL_PLAINFLATS].DrawFlats(di, pass);
// Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show
@ -355,20 +334,20 @@ void GLSceneDrawer::RenderScene(int recursion)
gl_RenderState.SetTextureMode(TM_MASK);
}
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
gl_drawinfo->drawlists[GLDL_MASKEDWALLS].DrawWalls(gl_drawinfo, pass);
gl_drawinfo->drawlists[GLDL_MASKEDFLATS].DrawFlats(gl_drawinfo, pass);
di->drawlists[GLDL_MASKEDWALLS].DrawWalls(di, pass);
di->drawlists[GLDL_MASKEDFLATS].DrawFlats(di, pass);
// Part 3: masked geometry with polygon offset. This list is empty most of the time so only waste time on it when in use.
if (gl_drawinfo->drawlists[GLDL_MASKEDWALLSOFS].Size() > 0)
if (di->drawlists[GLDL_MASKEDWALLSOFS].Size() > 0)
{
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -128.0f);
gl_drawinfo->drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(gl_drawinfo, pass);
di->drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(di, pass);
glDisable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0, 0);
}
gl_drawinfo->drawlists[GLDL_MODELS].Draw(gl_drawinfo, pass);
di->drawlists[GLDL_MODELS].Draw(di, pass);
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@ -377,7 +356,7 @@ void GLSceneDrawer::RenderScene(int recursion)
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -128.0f);
glDepthMask(false);
gl_drawinfo->DrawDecals();
di->DrawDecals();
gl_RenderState.SetTextureMode(TM_MODULATE);
@ -395,7 +374,7 @@ void GLSceneDrawer::RenderScene(int recursion)
gl_RenderState.EnableFog(true);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
gl_RenderState.BlendFunc(GL_ONE,GL_ZERO);
gl_drawinfo->DrawUnhandledMissingTextures();
di->DrawUnhandledMissingTextures();
glDepthMask(true);
glPolygonOffset(0.0f, 0.0f);
@ -412,7 +391,7 @@ void GLSceneDrawer::RenderScene(int recursion)
//
//-----------------------------------------------------------------------------
void GLSceneDrawer::RenderTranslucent()
void GLSceneDrawer::RenderTranslucent(FDrawInfo *di)
{
RenderAll.Clock();
@ -424,8 +403,8 @@ void GLSceneDrawer::RenderTranslucent()
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gl_RenderState.EnableBrightmap(true);
gl_drawinfo->drawlists[GLDL_TRANSLUCENTBORDER].Draw(gl_drawinfo, GLPASS_TRANSLUCENT);
gl_drawinfo->DrawSorted(GLDL_TRANSLUCENT);
di->drawlists[GLDL_TRANSLUCENTBORDER].Draw(di, GLPASS_TRANSLUCENT);
di->DrawSorted(GLDL_TRANSLUCENT);
gl_RenderState.EnableBrightmap(false);
@ -445,7 +424,7 @@ void GLSceneDrawer::RenderTranslucent()
//
//-----------------------------------------------------------------------------
void GLSceneDrawer::DrawScene(int drawmode)
void GLSceneDrawer::DrawScene(FDrawInfo *di, int drawmode)
{
static int recursion=0;
static int ssao_portals_available = 0;
@ -469,16 +448,15 @@ void GLSceneDrawer::DrawScene(int drawmode)
if (r_viewpoint.camera != nullptr)
{
ActorRenderFlags savedflags = r_viewpoint.camera->renderflags;
CreateScene();
CreateScene(di);
r_viewpoint.camera->renderflags = savedflags;
}
else
{
CreateScene();
CreateScene(di);
}
GLRenderer->mClipPortal = NULL; // this must be reset before any portal recursion takes place.
RenderScene(recursion);
RenderScene(di, recursion);
if (applySSAO && gl_RenderState.GetPassType() == GBUFFER_PASS)
{
@ -495,7 +473,7 @@ void GLSceneDrawer::DrawScene(int drawmode)
recursion++;
GLPortal::EndFrame();
recursion--;
RenderTranslucent();
RenderTranslucent(di);
}
//-----------------------------------------------------------------------------
@ -505,17 +483,17 @@ void GLSceneDrawer::DrawScene(int drawmode)
//-----------------------------------------------------------------------------
void GLSceneDrawer::EndDrawScene(sector_t * viewsector)
void GLSceneDrawer::EndDrawScene(FDrawInfo *di, sector_t * viewsector)
{
gl_RenderState.EnableFog(false);
// [BB] HUD models need to be rendered here.
const bool renderHUDModel = gl_IsHUDModelForPlayerAvailable( players[consoleplayer].camera->player );
const bool renderHUDModel = IsHUDModelForPlayerAvailable( players[consoleplayer].camera->player );
if ( renderHUDModel )
{
// [BB] The HUD model should be drawn over everything else already drawn.
glClear(GL_DEPTH_BUFFER_BIT);
gl_drawinfo->DrawPlayerSprites(true);
di->DrawPlayerSprites(true);
}
glDisable(GL_STENCIL_TEST);
@ -525,7 +503,7 @@ void GLSceneDrawer::EndDrawScene(sector_t * viewsector)
// Delay drawing psprites until after bloom has been applied, if enabled.
if (!FGLRenderBuffers::IsEnabled() || !gl_bloom || FixedColormap != CM_DEFAULT)
{
DrawEndScene2D(viewsector);
DrawEndScene2D(di, viewsector);
}
else
{
@ -537,9 +515,9 @@ void GLSceneDrawer::EndDrawScene(sector_t * viewsector)
}
}
void GLSceneDrawer::DrawEndScene2D(sector_t * viewsector)
void GLSceneDrawer::DrawEndScene2D(FDrawInfo *di, sector_t * viewsector)
{
const bool renderHUDModel = gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
const bool renderHUDModel = IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
// This should be removed once all 2D stuff is really done through the 2D interface.
gl_RenderState.mViewMatrix.loadIdentity();
@ -549,7 +527,7 @@ void GLSceneDrawer::DrawEndScene2D(sector_t * viewsector)
glDisable(GL_MULTISAMPLE);
gl_drawinfo->DrawPlayerSprites(false);
di->DrawPlayerSprites(false);
if (gl.legacyMode)
{
@ -572,16 +550,15 @@ void GLSceneDrawer::DrawEndScene2D(sector_t * viewsector)
//
//-----------------------------------------------------------------------------
void GLSceneDrawer::ProcessScene(bool toscreen)
void GLSceneDrawer::ProcessScene(FDrawInfo *di, bool toscreen)
{
iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0;
GLPortal::BeginScene();
int mapsection = R_PointInSubsector(r_viewpoint.Pos)->mapsection;
CurrentMapSections.Resize(level.NumMapSections);
CurrentMapSections.Zero();
CurrentMapSections.Set(mapsection);
DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN);
di->CurrentMapSections.Set(mapsection);
GLRenderer->mCurrentPortal = nullptr;
DrawScene(di, toscreen ? DM_MAINVIEW : DM_OFFSCREEN);
}
@ -644,7 +621,6 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, IntRect * bounds, fl
GLRenderer->mSceneClearColor[1] = 0.0f;
GLRenderer->mSceneClearColor[2] = 0.0f;
R_SetupFrame (r_viewpoint, r_viewwindow, camera);
SetViewArea();
GLRenderer->mGlobVis = R_GetGlobVis(r_viewwindow, r_visibility);
@ -684,6 +660,10 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, IntRect * bounds, fl
Set3DViewport(mainview);
GLRenderer->mDrawingScene2D = true;
GLRenderer->mCurrentFoV = fov;
FDrawInfo *di = FDrawInfo::StartDrawInfo(this);
di->SetViewArea();
// Stereo mode specific perspective projection
SetProjection( eye->GetProjection(fov, ratio, fovratio) );
// SetProjection(fov, ratio, fovratio); // switch to perspective mode and set up clipper
@ -694,13 +674,12 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, IntRect * bounds, fl
SetViewMatrix(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, false, false);
gl_RenderState.ApplyMatrices();
FDrawInfo::StartDrawInfo(this);
ProcessScene(toscreen);
if (mainview && toscreen) EndDrawScene(lviewsector); // do not call this for camera textures.
ProcessScene(di, toscreen);
if (mainview && toscreen) EndDrawScene(di, lviewsector); // do not call this for camera textures.
if (mainview && FGLRenderBuffers::IsEnabled())
{
GLRenderer->PostProcessScene(FixedColormap, [&]() { if (gl_bloom && FixedColormap == CM_DEFAULT) DrawEndScene2D(lviewsector); });
GLRenderer->PostProcessScene(FixedColormap, [&]() { if (gl_bloom && FixedColormap == CM_DEFAULT) DrawEndScene2D(di, lviewsector); });
// This should be done after postprocessing, not before.
GLRenderer->mBuffers->BindCurrentFB();

View file

@ -13,30 +13,14 @@ struct HUDSprite;
class GLSceneDrawer
{
fixed_t viewx, viewy; // since the nodes are still fixed point, keeping the view position also fixed point for node traversal is faster.
subsector_t *currentsubsector; // used by the line processing code.
sector_t *currentsector;
TMap<DPSprite*, int> weapondynlightindex;
void RenderMultipassStuff();
void RenderMultipassStuff(FDrawInfo *di);
void UnclipSubsector(subsector_t *sub);
void AddLine (seg_t *seg, bool portalclip);
void PolySubsector(subsector_t * sub);
void RenderPolyBSPNode (void *node);
void AddPolyobjs(subsector_t *sub);
void AddLines(subsector_t * sub, sector_t * sector);
void AddSpecialPortalLines(subsector_t * sub, sector_t * sector, line_t *line);
void RenderThings(subsector_t * sub, sector_t * sector);
void DoSubsector(subsector_t * sub);
void RenderBSPNode(void *node);
void RenderScene(FDrawInfo *di, int recursion);
void RenderTranslucent(FDrawInfo *di);
void RenderScene(int recursion);
void RenderTranslucent();
void CreateScene();
void CreateScene(FDrawInfo *di);
public:
GLSceneDrawer()
@ -44,10 +28,7 @@ public:
GLPortal::drawer = this;
}
Clipper clipper;
int FixedColormap;
area_t in_area;
BitArray CurrentMapSections; // this cannot be a single number, because a group of portals with the same displacement may link different sections.
angle_t FrustumAngle();
void SetViewMatrix(float vx, float vy, float vz, bool mirror, bool planemirror);
@ -58,27 +39,15 @@ public:
void Set3DViewport(bool mainview);
void Reset3DViewport();
void SetFixedColormap(player_t *player);
void DrawScene(int drawmode);
void ProcessScene(bool toscreen = false);
void EndDrawScene(sector_t * viewsector);
void DrawEndScene2D(sector_t * viewsector);
void DrawScene(FDrawInfo *di, int drawmode);
void ProcessScene(FDrawInfo *di, bool toscreen = false);
void EndDrawScene(FDrawInfo *di, sector_t * viewsector);
void DrawEndScene2D(FDrawInfo *di, sector_t * viewsector);
sector_t *RenderViewpoint(AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen);
sector_t *RenderView(player_t *player);
void WriteSavePic(player_t *player, FileWriter *file, int width, int height);
void InitClipper(angle_t a1, angle_t a2)
{
clipper.Clear();
clipper.SafeAddClipRangeRealAngles(a1, a2);
}
void SetView()
{
viewx = FLOAT2FIXED(r_viewpoint.Pos.X);
viewy = FLOAT2FIXED(r_viewpoint.Pos.Y);
}
void SetColor(int light, int rellight, const FColormap &cm, float alpha, bool weapon = false)
{
gl_SetColor(light, rellight, FixedColormap != CM_DEFAULT, cm, alpha, weapon);

View file

@ -271,7 +271,7 @@ static void RenderBox(FTextureID texno, FMaterial * gltex, float x_offset, bool
//
//
//-----------------------------------------------------------------------------
void GLSkyPortal::DrawContents()
void GLSkyPortal::DrawContents(FDrawInfo *di)
{
bool drawBoth = false;

View file

@ -327,7 +327,7 @@ void FDrawInfo::AddSprite(GLSprite *sprite, bool translucent)
list = GLDL_MODELS;
}
auto newsprt = gl_drawinfo->drawlists[list].NewSprite();
auto newsprt = drawlists[list].NewSprite();
*newsprt = *sprite;
}

View file

@ -142,7 +142,7 @@ void FDrawInfo::RenderMirrorSurface(GLWall *wall)
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -128.0f);
glDepthMask(false);
gl_drawinfo->DrawDecalsForMirror(wall);
DrawDecalsForMirror(wall);
glDepthMask(true);
glPolygonOffset(0.0f, 0.0f);
glDisable(GL_POLYGON_OFFSET_FILL);
@ -293,7 +293,7 @@ void FDrawInfo::DrawWall(GLWall *wall, int pass)
case GLPASS_LIGHTTEX:
case GLPASS_LIGHTTEX_ADDITIVE:
case GLPASS_LIGHTTEX_FOGGY:
gl_drawinfo->RenderLightsCompat(wall, pass);
RenderLightsCompat(wall, pass);
break;
case GLPASS_TEXONLY:
@ -426,7 +426,7 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype)
line_t *otherside = wall->lineportal->lines[0]->mDestination;
if (otherside != NULL && otherside->portalindex < level.linePortals.Size())
{
ProcessActorsInPortal(otherside->getPortal()->mGroup, mDrawer->in_area);
ProcessActorsInPortal(otherside->getPortal()->mGroup, in_area);
}
portal = new GLLineToLinePortal(wall->lineportal);
}

View file

@ -33,8 +33,6 @@
#include "gl/stereo3d/gl_interleaved3d.h"
#include "version.h"
EXTERN_CVAR(Bool, vr_enable_quadbuffered)
// Set up 3D-specific console variables:
CVAR(Int, vr_mode, 0, CVAR_GLOBALCONFIG)

View file

@ -470,16 +470,16 @@ void OpenGLFrameBuffer::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch,
int sx = u * viewport.width;
int sy = v * viewport.height;
int sindex = (sx + sy * viewport.width) * 3;
int dindex = (x + y * w) * 3;
int dindex = (x + (h - y - 1) * w) * 3;
ScreenshotBuffer[dindex] = pixels[sindex];
ScreenshotBuffer[dindex + 1] = pixels[sindex + 1];
ScreenshotBuffer[dindex + 2] = pixels[sindex + 2];
}
}
pitch = -w*3;
pitch = w * 3;
color_type = SS_RGB;
buffer = ScreenshotBuffer + w * 3 * (h - 1);
buffer = ScreenshotBuffer;
// Screenshot should not use gamma correction if it was already applied to rendered image
EXTERN_CVAR(Bool, fullscreen);

View file

@ -64,7 +64,6 @@ public:
bool HWGammaActive = false; // Are we using hardware or software gamma?
std::shared_ptr<FGLDebug> mDebug; // Debug API
private:
uint8_t *ScreenshotBuffer; // What the name says. This must be maintained because the software renderer can return a locked canvas surface which the caller cannot release.
int camtexcount = 0;
class Wiper

View file

@ -238,7 +238,12 @@ void gl_LoadExtensions()
// Intel's GLSL compiler is a bit broken with extensions, so unlock the feature only if not on Intel or having GL 4.3.
if (strstr(gl.vendorstring, "Intel") == NULL || gl_version >= 4.3f)
{
gl.flags |= RFL_SHADER_STORAGE_BUFFER;
// Mesa implements shader storage only for fragment shaders.
// Just disable the feature there. The light buffer may just use a uniform buffer without any adverse effects.
int v;
glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &v);
if (v > 0)
gl.flags |= RFL_SHADER_STORAGE_BUFFER;
}
}
gl.flags |= RFL_BUFFER_STORAGE;

View file

@ -118,13 +118,22 @@ static F3DFloor *Find3DFloor(sector_t *target, sector_t *model)
//
//==========================================================================
int FFlatVertexGenerator::CreateSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor)
int FFlatVertexGenerator::CreateIndexedSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor, int vi, FFlatVertexGenerator::FIndexGenerationInfo &gen)
{
int idx = vbo_shadowdata.Reserve(sub->numlines);
for(unsigned int k=0; k<sub->numlines; k++, idx++)
if (sub->numlines < 3) return -1;
int idx = ibo_data.Reserve((sub->numlines - 2) * 3);
int idxc = idx;
int firstndx = gen.GetIndex(sub->firstline[0].v1);
int secondndx = gen.GetIndex(sub->firstline[1].v1);
for (unsigned int k = 2; k<sub->numlines; k++)
{
vbo_shadowdata[idx].SetFlatVertex(sub->firstline[k].v1, plane);
if (sub->sector->transdoor && floor) vbo_shadowdata[idx].z -= 1.f;
auto ndx = gen.GetIndex(sub->firstline[k].v1);
ibo_data[idx++] = vi + firstndx;
ibo_data[idx++] = vi + secondndx;
ibo_data[idx++] = vi + ndx;
secondndx = ndx;
}
return idx;
}
@ -135,15 +144,28 @@ int FFlatVertexGenerator::CreateSubsectorVertices(subsector_t *sub, const secpla
//
//==========================================================================
int FFlatVertexGenerator::CreateSectorVertices(sector_t *sec, const secplane_t &plane, int floor)
int FFlatVertexGenerator::CreateIndexedSectorVertices(sector_t *sec, const secplane_t &plane, int floor, FFlatVertexGenerator::FIndexGenerationInfo &gen)
{
int rt = vbo_shadowdata.Size();
// First calculate the vertices for the sector itself
for(int j=0; j<sec->subsectorcount; j++)
int rt = ibo_data.Size();
int vi = vbo_shadowdata.Reserve(gen.vertices.Size());
float diff;
// Create the actual vertices.
if (sec->transdoor && floor) diff = -1.f;
else diff = 0.f;
for (unsigned i = 0; i < gen.vertices.Size(); i++)
{
vbo_shadowdata[vi + i].SetFlatVertex(gen.vertices[i], plane);
vbo_shadowdata[vi + i].z += diff;
}
// Create the indices for the subsectors
for (int j = 0; j<sec->subsectorcount; j++)
{
subsector_t *sub = sec->subsectors[j];
CreateSubsectorVertices(sub, plane, floor);
CreateIndexedSubsectorVertices(sub, plane, floor, vi, gen);
}
sec->ibocount = ibo_data.Size() - rt;
return rt;
}
@ -153,23 +175,24 @@ int FFlatVertexGenerator::CreateSectorVertices(sector_t *sec, const secplane_t &
//
//==========================================================================
int FFlatVertexGenerator::CreateVertices(int h, sector_t *sec, const secplane_t &plane, int floor)
int FFlatVertexGenerator::CreateIndexedVertices(int h, sector_t *sec, const secplane_t &plane, int floor, TArray<FFlatVertexGenerator::FIndexGenerationInfo> &gen)
{
sec->vboindex[h] = vbo_shadowdata.Size();
// First calculate the vertices for the sector itself
sec->vboheight[h] = sec->GetPlaneTexZ(h);
sec->vboindex[h] = CreateSectorVertices(sec, plane, floor);
sec->iboindex[h] = CreateIndexedSectorVertices(sec, plane, floor, gen[sec->Index()]);
// Next are all sectors using this one as heightsec
TArray<sector_t *> &fakes = sec->e->FakeFloor.Sectors;
for (unsigned g=0; g<fakes.Size(); g++)
for (unsigned g = 0; g < fakes.Size(); g++)
{
sector_t *fsec = fakes[g];
fsec->vboindex[2+h] = CreateSectorVertices(fsec, plane, false);
fsec->iboindex[2 + h] = CreateIndexedSectorVertices(fsec, plane, false, gen[fsec->Index()]);
}
// and finally all attached 3D floors
TArray<sector_t *> &xf = sec->e->XFloor.attached;
for (unsigned g=0; g<xf.Size(); g++)
for (unsigned g = 0; g < xf.Size(); g++)
{
sector_t *fsec = xf[g];
F3DFloor *ffloor = Find3DFloor(fsec, sec);
@ -181,15 +204,14 @@ int FFlatVertexGenerator::CreateVertices(int h, sector_t *sec, const secplane_t
if (dotop || dobottom)
{
if (dotop) ffloor->top.vindex = vbo_shadowdata.Size();
if (dobottom) ffloor->bottom.vindex = vbo_shadowdata.Size();
CreateSectorVertices(fsec, plane, false);
auto ndx = CreateIndexedSectorVertices(fsec, plane, false, gen[fsec->Index()]);
if (dotop) ffloor->top.vindex = ndx;
if (dobottom) ffloor->bottom.vindex = ndx;
}
}
}
sec->vbocount[h] = vbo_shadowdata.Size() - sec->vboindex[h];
return sec->vboindex[h];
return sec->iboindex[h];
}
@ -199,13 +221,28 @@ int FFlatVertexGenerator::CreateVertices(int h, sector_t *sec, const secplane_t
//
//==========================================================================
void FFlatVertexGenerator::CreateFlatVertices()
void FFlatVertexGenerator::CreateIndexedFlatVertices()
{
TArray<FIndexGenerationInfo> gen;
gen.Resize(level.sectors.Size());
// This must be generated up front so that the following code knows how many vertices a sector contains.
for (unsigned i = 0; i < level.sectors.Size(); i++)
{
for (int j = 0; j < level.sectors[i].subsectorcount; j++)
{
auto sub = level.sectors[i].subsectors[j];
for (unsigned k = 0; k < sub->numlines; k++)
{
auto vert = sub->firstline[k].v1;
gen[i].AddVertex(vert);
}
}
}
for (int h = sector_t::floor; h <= sector_t::ceiling; h++)
{
for(auto &sec : level.sectors)
for (auto &sec : level.sectors)
{
CreateVertices(h, &sec, sec.GetSecPlane(h), h == sector_t::floor);
CreateIndexedVertices(h, &sec, sec.GetSecPlane(h), h == sector_t::floor, gen);
}
}
@ -213,15 +250,15 @@ void FFlatVertexGenerator::CreateFlatVertices()
// No new vertices are needed here. The planes come from the actual sector
for (auto &sec : level.sectors)
{
for(auto ff : sec.e->XFloor.ffloors)
for (auto ff : sec.e->XFloor.ffloors)
{
if (ff->top.model == &sec)
{
ff->top.vindex = sec.vboindex[ff->top.isceiling];
ff->top.vindex = sec.iboindex[ff->top.isceiling];
}
if (ff->bottom.model == &sec)
{
ff->bottom.vindex = sec.vboindex[ff->top.isceiling];
ff->bottom.vindex = sec.iboindex[ff->top.isceiling];
}
}
}
@ -233,13 +270,13 @@ void FFlatVertexGenerator::CreateFlatVertices()
//
//==========================================================================
void FFlatVertexGenerator::UpdatePlaneVertices(sector_t *sec, int plane, FFlatVertex *map)
void FFlatVertexGenerator::UpdatePlaneVertices(sector_t *sec, int plane)
{
int startvt = sec->vboindex[plane];
int countvt = sec->vbocount[plane];
secplane_t &splane = sec->GetSecPlane(plane);
FFlatVertex *vt = &vbo_shadowdata[startvt];
FFlatVertex *mapvt = &map[startvt];
FFlatVertex *mapvt = &mMap[startvt];
for(int i=0; i<countvt; i++, vt++, mapvt++)
{
vt->z = (float)splane.ZatPoint(vt->x, vt->y);
@ -257,7 +294,7 @@ void FFlatVertexGenerator::UpdatePlaneVertices(sector_t *sec, int plane, FFlatVe
void FFlatVertexGenerator::CreateVertices()
{
vbo_shadowdata.Resize(NUM_RESERVED);
CreateFlatVertices();
CreateIndexedFlatVertices();
}
//==========================================================================
@ -266,16 +303,16 @@ void FFlatVertexGenerator::CreateVertices()
//
//==========================================================================
void FFlatVertexGenerator::CheckPlanes(sector_t *sector, FFlatVertex *map)
void FFlatVertexGenerator::CheckPlanes(sector_t *sector)
{
if (sector->GetPlaneTexZ(sector_t::ceiling) != sector->vboheight[sector_t::ceiling])
{
UpdatePlaneVertices(sector, sector_t::ceiling, map);
UpdatePlaneVertices(sector, sector_t::ceiling);
sector->vboheight[sector_t::ceiling] = sector->GetPlaneTexZ(sector_t::ceiling);
}
if (sector->GetPlaneTexZ(sector_t::floor) != sector->vboheight[sector_t::floor])
{
UpdatePlaneVertices(sector, sector_t::floor, map);
UpdatePlaneVertices(sector, sector_t::floor);
sector->vboheight[sector_t::floor] = sector->GetPlaneTexZ(sector_t::floor);
}
}
@ -287,11 +324,11 @@ void FFlatVertexGenerator::CheckPlanes(sector_t *sector, FFlatVertex *map)
//
//==========================================================================
void FFlatVertexGenerator::CheckUpdate(sector_t *sector, FFlatVertex *map)
void FFlatVertexGenerator::CheckUpdate(sector_t *sector)
{
CheckPlanes(sector, map);
CheckPlanes(sector);
sector_t *hs = sector->GetHeightSec();
if (hs != NULL) CheckPlanes(hs, map);
if (hs != NULL) CheckPlanes(hs);
for (unsigned i = 0; i < sector->e->XFloor.ffloors.Size(); i++)
CheckPlanes(sector->e->XFloor.ffloors[i]->model, map);
CheckPlanes(sector->e->XFloor.ffloors[i]->model);
}

View file

@ -45,9 +45,32 @@ class FFlatVertexGenerator
{
protected:
TArray<FFlatVertex> vbo_shadowdata;
TArray<uint32_t> ibo_data;
FFlatVertex *mMap;
// Temporary data for creating an indexed buffer
struct FIndexGenerationInfo
{
TArray<vertex_t *> vertices;
TMap<vertex_t*, uint32_t> vertexmap;
uint32_t AddVertex(vertex_t *vert)
{
auto check = vertexmap.CheckKey(vert);
if (check != nullptr) return *check;
auto index = vertices.Push(vert);
vertexmap[vert] = index;
return index;
}
uint32_t GetIndex(vertex_t *vert)
{
auto check = vertexmap.CheckKey(vert);
if (check != nullptr) return *check;
return ~0;
}
};
void CheckPlanes(sector_t *sector);
public:
enum
@ -66,16 +89,17 @@ public:
void OutputResized(int width, int height);
private:
int CreateSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor);
int CreateSectorVertices(sector_t *sec, const secplane_t &plane, int floor);
int CreateVertices(int h, sector_t *sec, const secplane_t &plane, int floor);
void CreateFlatVertices();
void UpdatePlaneVertices(sector_t *sec, int plane, FFlatVertex *map);
int CreateIndexedSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor, int vi, FIndexGenerationInfo &gen);
int CreateIndexedSectorVertices(sector_t *sec, const secplane_t &plane, int floor, FIndexGenerationInfo &gen);
int CreateIndexedVertices(int h, sector_t *sec, const secplane_t &plane, int floor, TArray<FIndexGenerationInfo> &gen);
void CreateIndexedFlatVertices();
void UpdatePlaneVertices(sector_t *sec, int plane);
protected:
void CreateVertices();
void CheckPlanes(sector_t *sector, FFlatVertex *map);
void CheckUpdate(sector_t *sector, FFlatVertex *map);
void CheckPlanes(sector_t *sector);
public:
void CheckUpdate(sector_t *sector);
};
#endif

View file

@ -31,10 +31,14 @@
#include "g_levellocals.h"
#include "p_effect.h"
#include "po_man.h"
#include "hwrenderer/scene/hw_fakeflat.h"
#include "hwrenderer/scene/hw_clipper.h"
#include "hwrenderer/scene/hw_drawstructs.h"
#include "hwrenderer/scene/hw_drawinfo.h"
#include "hwrenderer/scene/hw_portal.h"
#include "hwrenderer/utility/hw_clock.h"
#include "hwrenderer/data/flatvertices.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/data/gl_vertexbuffer.h"
#include "gl/scene/gl_scenedrawer.h"
EXTERN_CVAR(Bool, gl_render_segs)
@ -42,10 +46,11 @@ CVAR(Bool, gl_render_things, true, 0)
CVAR(Bool, gl_render_walls, true, 0)
CVAR(Bool, gl_render_flats, true, 0)
void GLSceneDrawer::UnclipSubsector(subsector_t *sub)
void HWDrawInfo::UnclipSubsector(subsector_t *sub)
{
int count = sub->numlines;
seg_t * seg = sub->firstline;
auto &clipper = *mClipper;
while (count--)
{
@ -70,7 +75,7 @@ void GLSceneDrawer::UnclipSubsector(subsector_t *sub)
//
//==========================================================================
void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip)
void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
{
#ifdef _DEBUG
if (seg->linedef->Index() == 38)
@ -79,15 +84,16 @@ void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip)
}
#endif
sector_t * backsector = NULL;
sector_t * backsector = nullptr;
sector_t bs;
if (portalclip)
{
int clipres = GLRenderer->mClipPortal->ClipSeg(seg);
int clipres = mClipPortal->ClipSeg(seg);
if (clipres == PClip_InFront) return;
}
auto &clipper = *mClipper;
angle_t startAngle = clipper.GetClipAngle(seg->v2);
angle_t endAngle = clipper.GetClipAngle(seg->v1);
@ -97,7 +103,7 @@ void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip)
return;
}
if (seg->sidedef == NULL)
if (seg->sidedef == nullptr)
{
if (!(currentsubsector->flags & SSECMF_DRAWN))
{
@ -168,7 +174,7 @@ void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip)
GLWall wall;
wall.sub = currentsubsector;
wall.Process(gl_drawinfo, seg, currentsector, backsector);
wall.Process(this, seg, currentsector, backsector);
rendered_lines++;
SetupWall.Unclock();
@ -185,7 +191,7 @@ void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip)
//
//==========================================================================
void GLSceneDrawer::PolySubsector(subsector_t * sub)
void HWDrawInfo::PolySubsector(subsector_t * sub)
{
int count = sub->numlines;
seg_t * line = sub->firstline;
@ -194,7 +200,7 @@ void GLSceneDrawer::PolySubsector(subsector_t * sub)
{
if (line->linedef)
{
AddLine (line, GLRenderer->mClipPortal != NULL);
AddLine (line, mClipPortal != nullptr);
}
line++;
}
@ -209,7 +215,7 @@ void GLSceneDrawer::PolySubsector(subsector_t * sub)
//
//==========================================================================
void GLSceneDrawer::RenderPolyBSPNode (void *node)
void HWDrawInfo::RenderPolyBSPNode (void *node)
{
while (!((size_t)node & 1)) // Keep going until found a subsector
{
@ -225,7 +231,7 @@ void GLSceneDrawer::RenderPolyBSPNode (void *node)
side ^= 1;
// It is not necessary to use the slower precise version here
if (!clipper.CheckBox(bsp->bbox[side]))
if (!mClipper->CheckBox(bsp->bbox[side]))
{
return;
}
@ -242,15 +248,15 @@ void GLSceneDrawer::RenderPolyBSPNode (void *node)
//
//==========================================================================
void GLSceneDrawer::AddPolyobjs(subsector_t *sub)
void HWDrawInfo::AddPolyobjs(subsector_t *sub)
{
if (sub->BSP == NULL || sub->BSP->bDirty)
if (sub->BSP == nullptr || sub->BSP->bDirty)
{
sub->BuildPolyBSP();
for (unsigned i = 0; i < sub->BSP->Segs.Size(); i++)
{
sub->BSP->Segs[i].Subsector = sub;
sub->BSP->Segs[i].PartnerSeg = NULL;
sub->BSP->Segs[i].PartnerSeg = nullptr;
}
}
if (sub->BSP->Nodes.Size() == 0)
@ -270,13 +276,13 @@ void GLSceneDrawer::AddPolyobjs(subsector_t *sub)
//
//==========================================================================
void GLSceneDrawer::AddLines(subsector_t * sub, sector_t * sector)
void HWDrawInfo::AddLines(subsector_t * sub, sector_t * sector)
{
currentsector = sector;
currentsubsector = sub;
ClipWall.Clock();
if (sub->polys != NULL)
if (sub->polys != nullptr)
{
AddPolyobjs(sub);
}
@ -287,13 +293,13 @@ void GLSceneDrawer::AddLines(subsector_t * sub, sector_t * sector)
while (count--)
{
if (seg->linedef == NULL)
if (seg->linedef == nullptr)
{
if (!(sub->flags & SSECMF_DRAWN)) AddLine (seg, GLRenderer->mClipPortal != NULL);
if (!(sub->flags & SSECMF_DRAWN)) AddLine (seg, mClipPortal != nullptr);
}
else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
{
AddLine (seg, GLRenderer->mClipPortal != NULL);
AddLine (seg, mClipPortal != nullptr);
}
seg++;
}
@ -314,7 +320,7 @@ inline bool PointOnLine(const DVector2 &pos, const line_t *line)
return fabs(v) <= EQUAL_EPSILON;
}
void GLSceneDrawer::AddSpecialPortalLines(subsector_t * sub, sector_t * sector, line_t *line)
void HWDrawInfo::AddSpecialPortalLines(subsector_t * sub, sector_t * sector, line_t *line)
{
currentsector = sector;
currentsubsector = sub;
@ -325,7 +331,7 @@ void GLSceneDrawer::AddSpecialPortalLines(subsector_t * sub, sector_t * sector,
while (count--)
{
if (seg->linedef != NULL && seg->PartnerSeg != NULL)
if (seg->linedef != nullptr && seg->PartnerSeg != nullptr)
{
if (PointOnLine(seg->v1->fPos(), line) && PointOnLine(seg->v2->fPos(), line))
AddLine(seg, false);
@ -342,7 +348,7 @@ void GLSceneDrawer::AddSpecialPortalLines(subsector_t * sub, sector_t * sector,
//
//==========================================================================
void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector)
void HWDrawInfo::RenderThings(subsector_t * sub, sector_t * sector)
{
SetupSprite.Clock();
sector_t * sec=sub->sector;
@ -354,7 +360,7 @@ void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector)
thing->validcount = validcount;
FIntCVar *cvar = thing->GetInfo()->distancecheck;
if (cvar != NULL && *cvar >= 0)
if (cvar != nullptr && *cvar >= 0)
{
double dist = (thing->Pos() - r_viewpoint.Pos).LengthSquared();
double check = (double)**cvar;
@ -367,7 +373,7 @@ void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector)
if (CurrentMapSections[thing->subsector->mapsection])
{
GLSprite sprite;
sprite.Process(gl_drawinfo, thing, sector, in_area, false);
sprite.Process(this, thing, sector, in_area, false);
}
}
@ -375,7 +381,7 @@ void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector)
{
AActor *thing = node->m_thing;
FIntCVar *cvar = thing->GetInfo()->distancecheck;
if (cvar != NULL && *cvar >= 0)
if (cvar != nullptr && *cvar >= 0)
{
double dist = (thing->Pos() - r_viewpoint.Pos).LengthSquared();
double check = (double)**cvar;
@ -386,7 +392,7 @@ void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector)
}
GLSprite sprite;
sprite.Process(gl_drawinfo, thing, sector, gl_drawinfo->mDrawer->in_area, true);
sprite.Process(this, thing, sector, in_area, true);
}
SetupSprite.Unclock();
}
@ -401,7 +407,7 @@ void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector)
//
//==========================================================================
void GLSceneDrawer::DoSubsector(subsector_t * sub)
void HWDrawInfo::DoSubsector(subsector_t * sub)
{
unsigned int i;
sector_t * sector;
@ -422,23 +428,23 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
if (!CurrentMapSections[sub->mapsection]) return;
if (sub->flags & SSECF_POLYORG) return; // never render polyobject origin subsectors because their vertices no longer are where one may expect.
if (gl_drawinfo->ss_renderflags[sub->Index()] & SSRF_SEEN)
if (ss_renderflags[sub->Index()] & SSRF_SEEN)
{
// This means that we have reached a subsector in a portal that has been marked 'seen'
// from the other side of the portal. This means we must clear the clipper for the
// range this subsector spans before going on.
UnclipSubsector(sub);
}
if (clipper.IsBlocked()) return; // if we are inside a stacked sector portal which hasn't unclipped anything yet.
if (mClipper->IsBlocked()) return; // if we are inside a stacked sector portal which hasn't unclipped anything yet.
fakesector=hw_FakeFlat(sector, &fake, in_area, false);
if (GLRenderer->mClipPortal)
if (mClipPortal)
{
int clipres = GLRenderer->mClipPortal->ClipSubsector(sub);
int clipres = mClipPortal->ClipSubsector(sub);
if (clipres == PClip_InFront)
{
line_t *line = GLRenderer->mClipPortal->ClipLine();
line_t *line = mClipPortal->ClipLine();
// The subsector is out of range, but we still have to check lines that lie directly on the boundary and may expose their upper or lower parts.
if (line) AddSpecialPortalLines(sub, fakesector, line);
return;
@ -447,7 +453,11 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
if (sector->validcount != validcount)
{
GLRenderer->mVBO->CheckUpdate(sector);
if (sector->Index() == 62)
{
int a = 0;
}
mVBO->CheckUpdate(sector);
}
// [RH] Add particles
@ -458,14 +468,14 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
for (i = ParticlesInSubsec[sub->Index()]; i != NO_PARTICLE; i = Particles[i].snext)
{
if (GLRenderer->mClipPortal)
if (mClipPortal)
{
int clipres = GLRenderer->mClipPortal->ClipPoint(Particles[i].Pos);
int clipres = mClipPortal->ClipPoint(Particles[i].Pos);
if (clipres == PClip_InFront) continue;
}
GLSprite sprite;
sprite.ProcessParticle(gl_drawinfo, &Particles[i], fakesector);
sprite.ProcessParticle(this, &Particles[i], fakesector);
}
SetupSprite.Unclock();
}
@ -507,35 +517,33 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
fakesector = hw_FakeFlat(sector, &fake, in_area, false);
}
uint8_t &srf = gl_drawinfo->sectorrenderflags[sub->render_sector->sectornum];
uint8_t &srf = sectorrenderflags[sub->render_sector->sectornum];
if (!(srf & SSRF_PROCESSED))
{
srf |= SSRF_PROCESSED;
SetupFlat.Clock();
GLFlat flat;
flat.ProcessSector(gl_drawinfo, fakesector);
flat.ProcessSector(this, fakesector);
SetupFlat.Unclock();
}
// mark subsector as processed - but mark for rendering only if it has an actual area.
gl_drawinfo->ss_renderflags[sub->Index()] =
ss_renderflags[sub->Index()] =
(sub->numlines > 2) ? SSRF_PROCESSED|SSRF_RENDERALL : SSRF_PROCESSED;
if (sub->hacked & 1) gl_drawinfo->AddHackedSubsector(sub);
if (sub->hacked & 1) AddHackedSubsector(sub);
FSectorPortalGroup *portal;
portal = fakesector->GetPortalGroup(sector_t::ceiling);
if (portal != NULL)
if (portal != nullptr)
{
GLSectorStackPortal *glportal = portal->GetRenderState();
glportal->AddSubsector(sub);
portal->AddSubsector(sub);
}
portal = fakesector->GetPortalGroup(sector_t::floor);
if (portal != NULL)
if (portal != nullptr)
{
GLSectorStackPortal *glportal = portal->GetRenderState();
glportal->AddSubsector(sub);
portal->AddSubsector(sub);
}
}
}
@ -554,7 +562,7 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
//
//==========================================================================
void GLSceneDrawer::RenderBSPNode (void *node)
void HWDrawInfo::RenderBSPNode (void *node)
{
if (level.nodes.Size() == 0)
{
@ -575,9 +583,9 @@ void GLSceneDrawer::RenderBSPNode (void *node)
side ^= 1;
// It is not necessary to use the slower precise version here
if (!clipper.CheckBox(bsp->bbox[side]))
if (!mClipper->CheckBox(bsp->bbox[side]))
{
if (!(gl_drawinfo->no_renderflags[bsp->Index()] & SSRF_SEEN))
if (!(no_renderflags[bsp->Index()] & SSRF_SEEN))
return;
}

View file

@ -3,6 +3,7 @@
#include <atomic>
#include "r_defs.h"
struct FSectorPortalGroup;
struct FLinePortalSpan;
struct FFlatVertex;
@ -14,6 +15,9 @@ class IShadowMap;
struct particle_t;
struct FDynLightData;
struct HUDSprite;
class Clipper;
class IPortal;
class FFlatVertexGenerator;
//==========================================================================
//
@ -78,11 +82,12 @@ struct HWDrawInfo
int FixedColormap;
std::atomic<int> spriteindex;
bool clipPortal;
IPortal *mClipPortal;
FRotator mAngles;
FVector2 mViewVector;
AActor *mViewActor;
IShadowMap *mShadowMap;
Clipper *mClipper;
TArray<MissingTextureInfo> MissingUpperTextures;
TArray<MissingTextureInfo> MissingLowerTextures;
@ -104,16 +109,38 @@ struct HWDrawInfo
TArray<uint8_t> ss_renderflags;
TArray<uint8_t> no_renderflags;
// This is needed by the BSP traverser.
BitArray CurrentMapSections; // this cannot be a single number, because a group of portals with the same displacement may link different sections.
area_t in_area;
fixed_t viewx, viewy; // since the nodes are still fixed point, keeping the view position also fixed point for node traversal is faster.
FFlatVertexGenerator *mVBO; // this class needs access because the sector vertex updating is part of BSP traversal.
private:
// For ProcessLowerMiniseg
bool inview;
subsector_t * viewsubsector;
TArray<seg_t *> lowersegs;
subsector_t *currentsubsector; // used by the line processing code.
sector_t *currentsector;
sector_t fakesec; // this is a struct member because it gets used in recursively called functions so it cannot be put on the stack.
void UnclipSubsector(subsector_t *sub);
void AddLine(seg_t *seg, bool portalclip);
void PolySubsector(subsector_t * sub);
void RenderPolyBSPNode(void *node);
void AddPolyobjs(subsector_t *sub);
void AddLines(subsector_t * sub, sector_t * sector);
void AddSpecialPortalLines(subsector_t * sub, sector_t * sector, line_t *line);
void RenderThings(subsector_t * sub, sector_t * sector);
void DoSubsector(subsector_t * sub);
public:
void RenderBSPNode(void *node);
void ClearBuffers();
void SetViewArea();
bool DoOneSectorUpper(subsector_t * subsec, float planez, area_t in_area);
bool DoOneSectorLower(subsector_t * subsec, float planez, area_t in_area);
@ -169,8 +196,5 @@ public:
virtual GLDecal *AddDecal(bool onmirror) = 0;
virtual std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) = 0;
virtual int ClipPoint(const DVector3 &pos) = 0;
};

View file

@ -306,12 +306,14 @@ public:
bool stack;
bool ceiling;
uint8_t renderflags;
int vboindex;
int iboindex;
//int vboheight;
int dynlightindex;
bool SetupLights(int pass, FLightNode *head, FDynLightData &lightdata, int portalgroup);
bool SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata);
bool SetupSectorLights(int pass, sector_t * sec, FDynLightData &lightdata);
void PutFlat(HWDrawInfo *di, bool fog = false);
void Process(HWDrawInfo *di, sector_t * model, int whichplane, bool notexture);

View file

@ -31,6 +31,8 @@
#include "a_sharedglobal.h"
#include "r_sky.h"
#include "hw_fakeflat.h"
#include "hw_drawinfo.h"
#include "r_utility.h"
//==========================================================================
@ -232,7 +234,7 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
{
dest->SetTexture(sector_t::floor, s->GetTexture(sector_t::floor), false);
dest->SetPlaneTexZQuick(sector_t::floor, s->GetPlaneTexZ(sector_t::floor));
dest->vboindex[sector_t::floor] = sec->vboindex[sector_t::vbo_fakefloor];
dest->iboindex[sector_t::floor] = sec->iboindex[sector_t::vbo_fakefloor];
dest->vboheight[sector_t::floor] = s->vboheight[sector_t::floor];
}
else if (s->MoreFlags & SECMF_FAKEFLOORONLY)
@ -258,7 +260,7 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
dest->SetPlaneTexZQuick(sector_t::floor, s->GetPlaneTexZ(sector_t::floor));
dest->floorplane = s->floorplane;
dest->vboindex[sector_t::floor] = sec->vboindex[sector_t::vbo_fakefloor];
dest->iboindex[sector_t::floor] = sec->iboindex[sector_t::vbo_fakefloor];
dest->vboheight[sector_t::floor] = s->vboheight[sector_t::floor];
}
@ -270,7 +272,7 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
{
dest->SetTexture(sector_t::ceiling, s->GetTexture(sector_t::ceiling), false);
dest->SetPlaneTexZQuick(sector_t::ceiling, s->GetPlaneTexZ(sector_t::ceiling));
dest->vboindex[sector_t::ceiling] = sec->vboindex[sector_t::vbo_fakeceiling];
dest->iboindex[sector_t::ceiling] = sec->iboindex[sector_t::vbo_fakeceiling];
dest->vboheight[sector_t::ceiling] = s->vboheight[sector_t::ceiling];
}
}
@ -278,7 +280,7 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
{
dest->ceilingplane = s->ceilingplane;
dest->SetPlaneTexZQuick(sector_t::ceiling, s->GetPlaneTexZ(sector_t::ceiling));
dest->vboindex[sector_t::ceiling] = sec->vboindex[sector_t::vbo_fakeceiling];
dest->iboindex[sector_t::ceiling] = sec->iboindex[sector_t::vbo_fakeceiling];
dest->vboheight[sector_t::ceiling] = s->vboheight[sector_t::ceiling];
}
}
@ -292,10 +294,10 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
dest->ceilingplane=s->floorplane;
dest->ceilingplane.FlipVert();
dest->vboindex[sector_t::floor] = sec->vboindex[sector_t::floor];
dest->iboindex[sector_t::floor] = sec->iboindex[sector_t::floor];
dest->vboheight[sector_t::floor] = sec->vboheight[sector_t::floor];
dest->vboindex[sector_t::ceiling] = sec->vboindex[sector_t::vbo_fakefloor];
dest->iboindex[sector_t::ceiling] = sec->iboindex[sector_t::vbo_fakefloor];
dest->vboheight[sector_t::ceiling] = s->vboheight[sector_t::floor];
dest->ClearPortal(sector_t::ceiling);
@ -345,10 +347,10 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
dest->floorplane = s->ceilingplane;
dest->floorplane.FlipVert();
dest->vboindex[sector_t::floor] = sec->vboindex[sector_t::vbo_fakeceiling];
dest->iboindex[sector_t::floor] = sec->iboindex[sector_t::vbo_fakeceiling];
dest->vboheight[sector_t::floor] = s->vboheight[sector_t::ceiling];
dest->vboindex[sector_t::ceiling] = sec->vboindex[sector_t::ceiling];
dest->iboindex[sector_t::ceiling] = sec->iboindex[sector_t::ceiling];
dest->vboheight[sector_t::ceiling] = sec->vboheight[sector_t::ceiling];
dest->ClearPortal(sector_t::floor);
@ -383,4 +385,26 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
return dest;
}
//-----------------------------------------------------------------------------
//
// Sets the area the camera is in
//
//-----------------------------------------------------------------------------
void HWDrawInfo::SetViewArea()
{
// The render_sector is better suited to represent the current position in GL
r_viewpoint.sector = R_PointInSubsector(r_viewpoint.Pos)->render_sector;
// Get the heightsec state from the render sector, not the current one!
if (r_viewpoint.sector->GetHeightSec())
{
in_area = r_viewpoint.Pos.Z <= r_viewpoint.sector->heightsec->floorplane.ZatPoint(r_viewpoint.Pos) ? area_below :
(r_viewpoint.Pos.Z > r_viewpoint.sector->heightsec->ceilingplane.ZatPoint(r_viewpoint.Pos) &&
!(r_viewpoint.sector->heightsec->MoreFlags&SECMF_FAKEFLOORONLY)) ? area_above : area_normal;
}
else
{
in_area = level.HasHeightSecs ? area_default : area_normal; // depends on exposed lower sectors, if map contains heightsecs.
}
}

View file

@ -92,14 +92,13 @@ bool hw_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * glte
//
//==========================================================================
bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata)
bool GLFlat::SetupLights(int pass, FLightNode * node, FDynLightData &lightdata, int portalgroup)
{
Plane p;
if (renderstyle == STYLE_Add && !level.lightadditivesurfaces) return false; // no lights on additively blended surfaces.
lightdata.Clear();
FLightNode * node = sub->lighthead;
while (node)
{
ADynamicLight * light = node->lightsource;
@ -121,13 +120,23 @@ bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &li
}
p.Set(plane.plane.Normal(), plane.plane.fD());
lightdata.GetLight(sub->sector->PortalGroup, p, light, false);
lightdata.GetLight(portalgroup, p, light, false);
node = node->nextLight;
}
return true;
}
bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata)
{
return SetupLights(pass, sub->lighthead, lightdata, sub->sector->PortalGroup);
}
bool GLFlat::SetupSectorLights(int pass, sector_t * sec, FDynLightData &lightdata)
{
return SetupLights(pass, sec->lighthead, lightdata, sec->PortalGroup);
}
//==========================================================================
//
// GLFlat::PutFlat
@ -220,11 +229,11 @@ void GLFlat::SetFrom3DFloor(F3DFloor *rover, bool top, bool underside)
renderstyle = rover->flags&FF_ADDITIVETRANS? STYLE_Add : STYLE_Translucent;
if (plane.model->VBOHeightcheck(plane.isceiling))
{
vboindex = plane.vindex;
iboindex = plane.vindex;
}
else
{
vboindex = -1;
iboindex = -1;
}
}
@ -289,11 +298,11 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector)
{
if (frontsector->VBOHeightcheck(sector_t::floor))
{
vboindex = frontsector->vboindex[sector_t::floor];
iboindex = frontsector->iboindex[sector_t::floor];
}
else
{
vboindex = -1;
iboindex = -1;
}
ceiling = false;
@ -349,11 +358,11 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector)
{
if (frontsector->VBOHeightcheck(sector_t::ceiling))
{
vboindex = frontsector->vboindex[sector_t::ceiling];
iboindex = frontsector->iboindex[sector_t::ceiling];
}
else
{
vboindex = -1;
iboindex = -1;
}
ceiling = true;

View file

@ -1,5 +1,6 @@
#pragma once
#include "hw_drawinfo.h"
#include "hwrenderer/textures/hw_material.h"
struct GLSkyInfo
@ -32,3 +33,12 @@ struct GLHorizonInfo
PalEntry specialcolor;
};
class IPortal
{
public:
virtual ~IPortal() {}
virtual int ClipSeg(seg_t *seg) { return PClip_Inside; }
virtual int ClipSubsector(subsector_t *sub) { return PClip_Inside; }
virtual int ClipPoint(const DVector2 &pos) { return PClip_Inside; }
virtual line_t *ClipLine() { return nullptr; }
};

View file

@ -72,7 +72,20 @@ void HWDrawInfo::ClearBuffers()
HandledSubsectors.Clear();
spriteindex = 0;
CurrentMapSections.Resize(level.NumMapSections);
CurrentMapSections.Zero();
sectorrenderflags.Resize(level.sectors.Size());
ss_renderflags.Resize(level.subsectors.Size());
no_renderflags.Resize(level.subsectors.Size());
memset(&sectorrenderflags[0], 0, level.sectors.Size() * sizeof(sectorrenderflags[0]));
memset(&ss_renderflags[0], 0, level.subsectors.Size() * sizeof(ss_renderflags[0]));
memset(&no_renderflags[0], 0, level.nodes.Size() * sizeof(no_renderflags[0]));
mClipPortal = nullptr;
}
//==========================================================================
//
// Adds a subsector plane to a sector's render list
@ -1077,6 +1090,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area)
{
subsector_t *sub = HandledSubsectors[j];
ss_renderflags[sub->Index()] &= ~SSRF_RENDERCEILING;
sub->sector->ibocount = -1; // cannot render this sector in one go.
if (sub->portalcoverage[sector_t::ceiling].subsectors == NULL)
{
@ -1122,6 +1136,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area)
{
subsector_t *sub = HandledSubsectors[j];
ss_renderflags[sub->Index()] &= ~SSRF_RENDERFLOOR;
sub->sector->ibocount = -1; // cannot render this sector in one go.
if (sub->portalcoverage[sector_t::floor].subsectors == NULL)
{

View file

@ -45,6 +45,7 @@
#include "hwrenderer/scene/hw_drawstructs.h"
#include "hwrenderer/scene/hw_drawinfo.h"
#include "hwrenderer/scene/hw_fakeflat.h"
#include "hwrenderer/scene/hw_portal.h"
#include "hwrenderer/utility/hw_cvars.h"
#include "hwrenderer/utility/hw_clock.h"
#include "hwrenderer/utility/hw_lighting.h"
@ -448,7 +449,7 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
// exclude vertically moving objects from this check.
if (!thing->Vel.isZero())
{
if (!gl_FindModelFrame(thing->GetClass(), spritenum, thing->frame, false))
if (!FindModelFrame(thing->GetClass(), spritenum, thing->frame, false))
{
return;
}
@ -471,9 +472,9 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
thing->flags7 |= MF7_FLYCHEAT; // do this only once for the very first frame, but not if it gets into range again.
}
if (thruportal != 2 && di->clipPortal)
if (thruportal != 2 && di->mClipPortal != nullptr)
{
int clipres = di->ClipPoint(thingpos);
int clipres = di->mClipPortal->ClipPoint(thingpos);
if (clipres == PClip_InFront) return;
}
// disabled because almost none of the actual game code is even remotely prepared for this. If desired, use the INTERPOLATE flag.
@ -509,7 +510,7 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
z += fz;
}
modelframe = isPicnumOverride ? nullptr : gl_FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
if (!modelframe)
{
bool mirror;

View file

@ -252,14 +252,13 @@ bool HUDSprite::GetWeaponRenderStyle(DPSprite *psp, AActor *playermo, sector_t *
auto rs = psp->GetRenderStyle(playermo->RenderStyle, playermo->Alpha);
visstyle_t vis;
float trans = 0.f;
vis.RenderStyle = STYLE_Count;
vis.Alpha = rs.second;
vis.Invert = false;
playermo->AlterWeaponSprite(&vis);
if (!(psp->Flags & PSPF_FORCEALPHA)) trans = vis.Alpha;
alpha = (psp->Flags & PSPF_FORCEALPHA) ? 0.f : vis.Alpha;
if (vis.RenderStyle != STYLE_Count && !(psp->Flags & PSPF_FORCESTYLE))
{
@ -303,14 +302,10 @@ bool HUDSprite::GetWeaponRenderStyle(DPSprite *psp, AActor *playermo, sector_t *
{
alpha = 1.f;
}
else if (trans == 0.f)
else if (alpha == 0.f)
{
alpha = vis.Alpha;
}
else
{
alpha = trans;
}
if (!RenderStyle.IsVisible(alpha)) return false; // if it isn't visible skip the rest.
PalEntry ThingColor = (playermo->RenderStyle.Flags & STYLEF_ColorIsFixed) ? playermo->fillcolor : 0xffffff;
@ -430,7 +425,7 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area)
bool brightflash = false;
AActor * playermo = players[consoleplayer].camera;
player_t * player = playermo->player;
const bool hudModelStep = gl_IsHUDModelForPlayerAvailable(player);
const bool hudModelStep = IsHUDModelForPlayerAvailable(player);
AActor *camera = r_viewpoint.camera;
@ -453,7 +448,7 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area)
for (DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext())
{
if (!psp->GetState()) continue;
FSpriteModelFrame *smf = playermo->player->ReadyWeapon ? gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false) : nullptr;
FSpriteModelFrame *smf = playermo->player->ReadyWeapon ? FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false) : nullptr;
// This is an 'either-or' proposition. This maybe needs some work to allow overlays with weapon models but as originally implemented this just won't work.
if (smf && !hudModelStep) continue;
if (!smf && hudModelStep) continue;

View file

@ -119,7 +119,7 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap<PClassActor*, bool> &actorhitl
{
auto &state = cls->GetStates()[i];
spritelist[state.sprite].Insert(gltrans, true);
FSpriteModelFrame * smf = gl_FindModelFrame(cls, state.sprite, state.Frame, false);
FSpriteModelFrame * smf = FindModelFrame(cls, state.sprite, state.Frame, false);
if (smf != NULL)
{
for (int i = 0; i < MAX_MODELS_PER_FRAME; i++)

View file

@ -537,6 +537,8 @@ xx(Repeatspecial)
xx(Conversation)
xx(Locknumber)
xx(Midtex3dimpassible)
xx(Revealed)
xx(AutomapStyle)
xx(Playercross)
xx(Playeruse)

View file

@ -120,6 +120,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
ffloor->top.copied = ffloor->bottom.copied = false;
ffloor->top.model = ffloor->bottom.model = ffloor->model = sec2;
ffloor->target = sec;
ffloor->top.vindex = ffloor->bottom.vindex = -1;
if (!(flags&FF_THINFLOOR))
{

View file

@ -1510,6 +1510,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex)
ss->friction = ORIG_FRICTION;
ss->movefactor = ORIG_FRICTION_FACTOR;
ss->sectornum = i;
ss->ibocount = -1;
}
delete[] msp;
}

View file

@ -1107,6 +1107,14 @@ public:
Flag(ld->flags, ML_3DMIDTEX_IMPASS, key);
continue;
case NAME_Revealed:
Flag(ld->flags, ML_REVEALED, key);
continue;
case NAME_AutomapStyle:
ld->automapstyle = AutomapLineStyle(CheckInt(key));
continue;
case NAME_MoreIds:
// delay parsing of the tag string until parsing of the sector is complete
// This ensures that the ID is always the first tag in the list.
@ -1375,6 +1383,7 @@ public:
sec->sectornum = index;
sec->damageinterval = 32;
sec->terrainnum[sector_t::ceiling] = sec->terrainnum[sector_t::floor] = -1;
sec->ibocount = -1;
memset(sec->SpecialColors, -1, sizeof(sec->SpecialColors));
if (floordrop) sec->Flags = SECF_FLOORDROP;
// killough 3/7/98: end changes

View file

@ -79,6 +79,11 @@ void PolyTriangleDrawer::SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw
queue->Push<PolySetCullCCWCommand>(ccw);
}
void PolyTriangleDrawer::SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided)
{
queue->Push<PolySetTwoSidedCommand>(twosided);
}
void PolyTriangleDrawer::SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable)
{
queue->Push<PolySetWeaponSceneCommand>(enable);
@ -348,6 +353,14 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *vert, boo
}
}
if (twosided && numclipvert > 2)
{
args->v1 = &clippedvert[0];
args->v2 = &clippedvert[1];
args->v3 = &clippedvert[2];
ccw = !IsFrontfacing(args);
}
// Draw screen triangles
if (ccw)
{
@ -588,6 +601,17 @@ void PolySetCullCCWCommand::Execute(DrawerThread *thread)
/////////////////////////////////////////////////////////////////////////////
PolySetTwoSidedCommand::PolySetTwoSidedCommand(bool twosided) : twosided(twosided)
{
}
void PolySetTwoSidedCommand::Execute(DrawerThread *thread)
{
PolyTriangleThreadData::Get(thread)->SetTwoSided(twosided);
}
/////////////////////////////////////////////////////////////////////////////
PolySetWeaponSceneCommand::PolySetWeaponSceneCommand(bool value) : value(value)
{
}

View file

@ -35,6 +35,7 @@ public:
static void ClearBuffers(DCanvas *canvas);
static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas, bool span_drawers);
static void SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw);
static void SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided);
static void SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable);
static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip);
};
@ -47,6 +48,7 @@ public:
void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, bool span_drawers);
void SetTransform(const Mat4f *objectToClip);
void SetCullCCW(bool value) { ccw = value; }
void SetTwoSided(bool value) { twosided = value; }
void SetWeaponScene(bool value) { weaponScene = value; }
void DrawElements(const PolyDrawArgs &args);
@ -81,6 +83,7 @@ private:
bool dest_bgra = false;
uint8_t *dest = nullptr;
bool ccw = true;
bool twosided = false;
bool weaponScene = false;
const Mat4f *objectToClip = nullptr;
bool span_drawers = false;
@ -112,6 +115,18 @@ private:
bool ccw;
};
class PolySetTwoSidedCommand : public DrawerCommand
{
public:
PolySetTwoSidedCommand(bool twosided);
void Execute(DrawerThread *thread) override;
FString DebugInfo() override { return "PolySetCullCCWCommand"; }
private:
bool twosided;
};
class PolySetWeaponSceneCommand : public DrawerCommand
{
public:

View file

@ -33,9 +33,6 @@
#include "actorinlines.h"
#include "i_time.h"
void gl_FlushModels();
bool polymodelsInUse;
void PolyRenderModel(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor)
{
PolyModelRenderer renderer(thread, worldToClip, stencilValue);
@ -52,11 +49,6 @@ void PolyRenderHUDModel(PolyRenderThread *thread, const Mat4f &worldToClip, uint
PolyModelRenderer::PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue) : Thread(thread), WorldToClip(worldToClip), StencilValue(stencilValue)
{
if (!polymodelsInUse)
{
gl_FlushModels();
polymodelsInUse = true;
}
}
void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix)
@ -64,10 +56,12 @@ void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, co
ModelActor = actor;
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.Matrix);
SetTransform();
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true);
}
void PolyModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf)
{
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false);
ModelActor = nullptr;
}
@ -106,12 +100,14 @@ void PolyModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectT
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.Matrix);
SetTransform();
PolyTriangleDrawer::SetWeaponScene(Thread->DrawQueue, true);
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true);
}
void PolyModelRenderer::EndDrawHUDModel(AActor *actor)
{
ModelActor = nullptr;
PolyTriangleDrawer::SetWeaponScene(Thread->DrawQueue, false);
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false);
}
void PolyModelRenderer::SetInterpolation(double interpolation)

View file

@ -34,6 +34,8 @@ class PolyModelRenderer : public FModelRenderer
public:
PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue);
ModelRendererType GetType() const override { return PolyModelRendererType; }
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override;
void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override;
IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override;

View file

@ -60,7 +60,7 @@ void RenderPolyPlayerSprites::Render(PolyRenderThread *thread)
(r_deathcamera && viewpoint.camera->health <= 0))
return;
renderHUDModel = r_models && gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
renderHUDModel = r_models && IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
PolyTransferHeights fakeflat(viewpoint.camera->subsector);

View file

@ -78,7 +78,7 @@ void RenderPolySprite::Render(PolyRenderThread *thread, AActor *thing, subsector
{
int spritenum = thing->sprite;
bool isPicnumOverride = thing->picnum.isValid();
FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : gl_FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
if (modelframe)
{
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;

View file

@ -7,6 +7,7 @@
struct FPortalGroupArray;
struct portnode_t;
struct subsector_t;
//============================================================================
//
// This table holds the offsets for the different parts of a map
@ -256,6 +257,8 @@ struct FSectorPortalGroup
GLSectorStackPortal *glportal; // for quick access to the render data. This is only valid during BSP traversal!
GLSectorStackPortal *GetRenderState();
void AddSubsector(subsector_t *sub);
};

View file

@ -94,8 +94,8 @@ void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *s
if (smf->flags & MDL_ROTATING)
{
const double time = smf->rotationSpeed*GetTimeFloat() / 200.;
rotateOffset = double((time - xs_FloorToInt(time)) *360.);
double turns = (I_GetTime() % 200 + I_GetTimeFrac()) / 200.0;
rotateOffset = turns * 360.0;
}
// Added MDL_USEACTORPITCH and MDL_USEACTORROLL flags processing.
@ -164,14 +164,14 @@ void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *s
objectToWorldMatrix.scale(1, stretch, 1);
BeginDrawModel(actor, smf, objectToWorldMatrix);
RenderFrameModels(smf, actor->state, actor->tics, actor->GetClass(), nullptr, translation);
RenderFrameModels(smf, actor->state, actor->tics, actor->GetClass(), translation);
EndDrawModel(actor, smf);
}
void FModelRenderer::RenderHUDModel(DPSprite *psp, float ofsX, float ofsY)
{
AActor * playermo = players[consoleplayer].camera;
FSpriteModelFrame *smf = gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false);
FSpriteModelFrame *smf = FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false);
// [BB] No model found for this sprite, so we can't render anything.
if (smf == nullptr)
@ -200,16 +200,11 @@ void FModelRenderer::RenderHUDModel(DPSprite *psp, float ofsX, float ofsY)
objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0);
BeginDrawHUDModel(playermo, objectToWorldMatrix);
RenderFrameModels(smf, psp->GetState(), psp->GetTics(), playermo->player->ReadyWeapon->GetClass(), nullptr, 0);
RenderFrameModels(smf, psp->GetState(), psp->GetTics(), playermo->player->ReadyWeapon->GetClass(), 0);
EndDrawHUDModel(playermo);
}
void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf,
const FState *curState,
const int curTics,
const PClass *ti,
Matrix3x4 *normaltransform,
int translation)
void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, int translation)
{
// [BB] Frame interpolation: Find the FSpriteModelFrame smfNext which follows after smf in the animation
// and the scalar value inter ( element of [0,1) ), both necessary to determine the interpolated frame.
@ -225,14 +220,13 @@ void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf,
// [BB] In case the tic counter is frozen we have to leave ticFraction at zero.
if (ConsoleState == c_up && menuactive != MENU_On && !(level.flags2 & LEVEL2_FROZEN))
{
double time = GetTimeFloat();
ticFraction = (time - static_cast<int>(time));
ticFraction = I_GetTimeFrac();
}
inter = static_cast<double>(curState->Tics - curTics - ticFraction) / static_cast<double>(curState->Tics);
inter = static_cast<double>(curState->Tics - curTics + ticFraction) / static_cast<double>(curState->Tics);
// [BB] For some actors (e.g. ZPoisonShroom) spr->actor->tics can be bigger than curState->Tics.
// In this case inter is negative and we need to set it to zero.
if (inter < 0.)
if (curState->Tics < curTics)
inter = 0.;
else
{
@ -253,7 +247,7 @@ void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf,
}
}
if (inter != 0.0)
smfNext = gl_FindModelFrame(ti, nextState->sprite, nextState->Frame, false);
smfNext = FindModelFrame(ti, nextState->sprite, nextState->Frame, false);
}
}
}
@ -265,7 +259,7 @@ void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf,
FModel * mdl = Models[smf->modelIDs[i]];
FTexture *tex = smf->skinIDs[i].isValid() ? TexMan(smf->skinIDs[i]) : nullptr;
mdl->BuildVertexBuffer(this);
SetVertexBuffer(mdl->mVBuf);
SetVertexBuffer(mdl->GetVertexBuffer(this));
mdl->PushSpriteMDLFrame(smf, i);
@ -279,24 +273,9 @@ void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf,
}
}
double FModelRenderer::GetTimeFloat()
{
return (double)I_msTime() * (double)TICRATE / 1000.;
}
/////////////////////////////////////////////////////////////////////////////
void gl_LoadModels()
{
/*
for (int i = Models.Size() - 1; i >= 0; i--)
{
Models[i]->BuildVertexBuffer();
}
*/
}
void gl_FlushModels()
void FlushModels()
{
for (int i = Models.Size() - 1; i >= 0; i--)
{
@ -306,9 +285,24 @@ void gl_FlushModels()
/////////////////////////////////////////////////////////////////////////////
FModel::FModel()
{
for (int i = 0; i < NumModelRendererTypes; i++)
mVBuf[i] = nullptr;
}
FModel::~FModel()
{
if (mVBuf != nullptr) delete mVBuf;
DestroyVertexBuffer();
}
void FModel::DestroyVertexBuffer()
{
for (int i = 0; i < NumModelRendererTypes; i++)
{
delete mVBuf[i];
mVBuf[i] = nullptr;
}
}
static TArray<FSpriteModelFrame> SpriteModelFrames;
@ -415,7 +409,7 @@ static unsigned FindModel(const char * path, const char * modelfile)
FMemLump lumpd = Wads.ReadLump(lump);
char * buffer = (char*)lumpd.GetMem();
if ( fullname.IndexOf("_d.3d") == fullname.Len()-5 )
if ( (size_t)fullname.IndexOf("_d.3d") == fullname.Len()-5 )
{
FString anivfile = fullname.GetChars();
anivfile.Substitute("_d.3d","_a.3d");
@ -424,7 +418,7 @@ static unsigned FindModel(const char * path, const char * modelfile)
model = new FUE1Model;
}
}
else if ( fullname.IndexOf("_a.3d") == fullname.Len()-5 )
else if ( (size_t)fullname.IndexOf("_a.3d") == fullname.Len()-5 )
{
FString datafile = fullname.GetChars();
datafile.Substitute("_a.3d","_d.3d");
@ -475,22 +469,15 @@ static unsigned FindModel(const char * path, const char * modelfile)
//===========================================================================
//
// gl_InitModels
// InitModels
//
//===========================================================================
void gl_InitModels()
static void ParseModelDefLump(int Lump);
void InitModels()
{
int Lump, lastLump;
FString path;
int index, surface;
int i;
FSpriteModelFrame smf;
lastLump = 0;
for(unsigned i=0;i<Models.Size();i++)
for (unsigned i = 0; i < Models.Size(); i++)
{
delete Models[i];
}
@ -508,6 +495,7 @@ void gl_InitModels()
for (unsigned i = 0; i < VoxelDefs.Size(); i++)
{
FVoxelModel *md = (FVoxelModel*)Models[VoxelDefs[i]->Voxel->VoxelIndex];
FSpriteModelFrame smf;
memset(&smf, 0, sizeof(smf));
smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
smf.modelIDs[0] = VoxelDefs[i]->Voxel->VoxelIndex;
@ -539,302 +527,11 @@ void gl_InitModels()
}
}
memset(&smf, 0, sizeof(smf));
smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
int Lump;
int lastLump = 0;
while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1)
{
FScanner sc(Lump);
while (sc.GetString())
{
if (sc.Compare("model"))
{
path = "";
sc.MustGetString();
memset(&smf, 0, sizeof(smf));
smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
smf.xscale=smf.yscale=smf.zscale=1.f;
smf.type = PClass::FindClass(sc.String);
if (!smf.type || smf.type->Defaults == nullptr)
{
sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String);
}
sc.MustGetStringName("{");
while (!sc.CheckString("}"))
{
sc.MustGetString();
if (sc.Compare("path"))
{
sc.MustGetString();
FixPathSeperator(sc.String);
path = sc.String;
if (path[(int)path.Len()-1]!='/') path+='/';
}
else if (sc.Compare("model"))
{
sc.MustGetNumber();
index = sc.Number;
if (index < 0 || index >= MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
sc.MustGetString();
FixPathSeperator(sc.String);
smf.modelIDs[index] = FindModel(path.GetChars(), sc.String);
if (smf.modelIDs[index] == -1)
{
Printf("%s: model not found in %s\n", sc.String, path.GetChars());
}
}
else if (sc.Compare("scale"))
{
sc.MustGetFloat();
smf.xscale = sc.Float;
sc.MustGetFloat();
smf.yscale = sc.Float;
sc.MustGetFloat();
smf.zscale = sc.Float;
}
// [BB] Added zoffset reading.
// Now it must be considered deprecated.
else if (sc.Compare("zoffset"))
{
sc.MustGetFloat();
smf.zoffset=sc.Float;
}
// Offset reading.
else if (sc.Compare("offset"))
{
sc.MustGetFloat();
smf.xoffset = sc.Float;
sc.MustGetFloat();
smf.yoffset = sc.Float;
sc.MustGetFloat();
smf.zoffset = sc.Float;
}
// angleoffset, pitchoffset and rolloffset reading.
else if (sc.Compare("angleoffset"))
{
sc.MustGetFloat();
smf.angleoffset = sc.Float;
}
else if (sc.Compare("pitchoffset"))
{
sc.MustGetFloat();
smf.pitchoffset = sc.Float;
}
else if (sc.Compare("rolloffset"))
{
sc.MustGetFloat();
smf.rolloffset = sc.Float;
}
// [BB] Added model flags reading.
else if (sc.Compare("ignoretranslation"))
{
smf.flags |= MDL_IGNORETRANSLATION;
}
else if (sc.Compare("pitchfrommomentum"))
{
smf.flags |= MDL_PITCHFROMMOMENTUM;
}
else if (sc.Compare("inheritactorpitch"))
{
smf.flags |= MDL_USEACTORPITCH | MDL_BADROTATION;
}
else if (sc.Compare("inheritactorroll"))
{
smf.flags |= MDL_USEACTORROLL;
}
else if (sc.Compare("useactorpitch"))
{
smf.flags |= MDL_USEACTORPITCH;
}
else if (sc.Compare("useactorroll"))
{
smf.flags |= MDL_USEACTORROLL;
}
else if (sc.Compare("rotating"))
{
smf.flags |= MDL_ROTATING;
smf.xrotate = 0.;
smf.yrotate = 1.;
smf.zrotate = 0.;
smf.rotationCenterX = 0.;
smf.rotationCenterY = 0.;
smf.rotationCenterZ = 0.;
smf.rotationSpeed = 1.;
}
else if (sc.Compare("rotation-speed"))
{
sc.MustGetFloat();
smf.rotationSpeed = sc.Float;
}
else if (sc.Compare("rotation-vector"))
{
sc.MustGetFloat();
smf.xrotate = sc.Float;
sc.MustGetFloat();
smf.yrotate = sc.Float;
sc.MustGetFloat();
smf.zrotate = sc.Float;
}
else if (sc.Compare("rotation-center"))
{
sc.MustGetFloat();
smf.rotationCenterX = sc.Float;
sc.MustGetFloat();
smf.rotationCenterY = sc.Float;
sc.MustGetFloat();
smf.rotationCenterZ = sc.Float;
}
else if (sc.Compare("interpolatedoubledframes"))
{
smf.flags |= MDL_INTERPOLATEDOUBLEDFRAMES;
}
else if (sc.Compare("nointerpolation"))
{
smf.flags |= MDL_NOINTERPOLATION;
}
else if (sc.Compare("skin"))
{
sc.MustGetNumber();
index=sc.Number;
if (index<0 || index>=MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
sc.MustGetString();
FixPathSeperator(sc.String);
if (sc.Compare(""))
{
smf.skinIDs[index]=FNullTextureID();
}
else
{
smf.skinIDs[index] = LoadSkin(path.GetChars(), sc.String);
if (!smf.skinIDs[index].isValid())
{
Printf("Skin '%s' not found in '%s'\n",
sc.String, smf.type->TypeName.GetChars());
}
}
}
else if (sc.Compare("surfaceskin"))
{
sc.MustGetNumber();
index = sc.Number;
sc.MustGetNumber();
surface = sc.Number;
if (index<0 || index >= MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
if (surface<0 || surface >= MD3_MAX_SURFACES)
{
sc.ScriptError("Invalid MD3 Surface %d in %s", MD3_MAX_SURFACES, smf.type->TypeName.GetChars());
}
sc.MustGetString();
FixPathSeperator(sc.String);
if (sc.Compare(""))
{
smf.surfaceskinIDs[index][surface] = FNullTextureID();
}
else
{
smf.surfaceskinIDs[index][surface] = LoadSkin(path.GetChars(), sc.String);
if (!smf.surfaceskinIDs[index][surface].isValid())
{
Printf("Surface Skin '%s' not found in '%s'\n",
sc.String, smf.type->TypeName.GetChars());
}
}
}
else if (sc.Compare("frameindex") || sc.Compare("frame"))
{
bool isframe=!!sc.Compare("frame");
sc.MustGetString();
smf.sprite = -1;
for (i = 0; i < (int)sprites.Size (); ++i)
{
if (strnicmp (sprites[i].name, sc.String, 4) == 0)
{
if (sprites[i].numframes==0)
{
//sc.ScriptError("Sprite %s has no frames", sc.String);
}
smf.sprite = i;
break;
}
}
if (smf.sprite==-1)
{
sc.ScriptError("Unknown sprite %s in model definition for %s", sc.String, smf.type->TypeName.GetChars());
}
sc.MustGetString();
FString framechars = sc.String;
sc.MustGetNumber();
index=sc.Number;
if (index<0 || index>=MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
if (isframe)
{
sc.MustGetString();
if (smf.modelIDs[index] != -1)
{
FModel *model = Models[smf.modelIDs[index]];
smf.modelframes[index] = model->FindFrame(sc.String);
if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, smf.type->TypeName.GetChars());
}
else smf.modelframes[index] = -1;
}
else
{
sc.MustGetNumber();
smf.modelframes[index] = sc.Number;
}
for(i=0; framechars[i]>0; i++)
{
char map[29]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int c = toupper(framechars[i])-'A';
if (c<0 || c>=29)
{
sc.ScriptError("Invalid frame character %c found", c+'A');
}
if (map[c]) continue;
smf.frame=c;
SpriteModelFrames.Push(smf);
GetDefaultByType(smf.type)->hasmodel = true;
map[c]=1;
}
}
else if (sc.Compare("dontcullbackfaces"))
{
smf.flags |= MDL_DONTCULLBACKFACES;
}
else if (sc.Compare("userotationcenter"))
{
smf.flags |= MDL_USEROTATIONCENTER;
smf.rotationCenterX = 0.;
smf.rotationCenterY = 0.;
smf.rotationCenterZ = 0.;
}
else
{
sc.ScriptMessage("Unrecognized string \"%s\"", sc.String);
}
}
}
}
ParseModelDefLump(Lump);
}
// create a hash table for quick access
@ -842,7 +539,7 @@ void gl_InitModels()
atterm(DeleteModelHash);
memset(SpriteModelHash, 0xff, SpriteModelFrames.Size () * sizeof(int));
for (i = 0; i < (int)SpriteModelFrames.Size (); i++)
for (unsigned int i = 0; i < SpriteModelFrames.Size (); i++)
{
int j = ModelFrameHash(&SpriteModelFrames[i]) % SpriteModelFrames.Size ();
@ -851,13 +548,327 @@ void gl_InitModels()
}
}
static void ParseModelDefLump(int Lump)
{
FScanner sc(Lump);
while (sc.GetString())
{
if (sc.Compare("model"))
{
int index, surface;
FString path = "";
sc.MustGetString();
FSpriteModelFrame smf;
memset(&smf, 0, sizeof(smf));
smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
smf.xscale=smf.yscale=smf.zscale=1.f;
smf.type = PClass::FindClass(sc.String);
if (!smf.type || smf.type->Defaults == nullptr)
{
sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String);
}
sc.MustGetStringName("{");
while (!sc.CheckString("}"))
{
sc.MustGetString();
if (sc.Compare("path"))
{
sc.MustGetString();
FixPathSeperator(sc.String);
path = sc.String;
if (path[(int)path.Len()-1]!='/') path+='/';
}
else if (sc.Compare("model"))
{
sc.MustGetNumber();
index = sc.Number;
if (index < 0 || index >= MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
sc.MustGetString();
FixPathSeperator(sc.String);
smf.modelIDs[index] = FindModel(path.GetChars(), sc.String);
if (smf.modelIDs[index] == -1)
{
Printf("%s: model not found in %s\n", sc.String, path.GetChars());
}
}
else if (sc.Compare("scale"))
{
sc.MustGetFloat();
smf.xscale = sc.Float;
sc.MustGetFloat();
smf.yscale = sc.Float;
sc.MustGetFloat();
smf.zscale = sc.Float;
}
// [BB] Added zoffset reading.
// Now it must be considered deprecated.
else if (sc.Compare("zoffset"))
{
sc.MustGetFloat();
smf.zoffset=sc.Float;
}
// Offset reading.
else if (sc.Compare("offset"))
{
sc.MustGetFloat();
smf.xoffset = sc.Float;
sc.MustGetFloat();
smf.yoffset = sc.Float;
sc.MustGetFloat();
smf.zoffset = sc.Float;
}
// angleoffset, pitchoffset and rolloffset reading.
else if (sc.Compare("angleoffset"))
{
sc.MustGetFloat();
smf.angleoffset = sc.Float;
}
else if (sc.Compare("pitchoffset"))
{
sc.MustGetFloat();
smf.pitchoffset = sc.Float;
}
else if (sc.Compare("rolloffset"))
{
sc.MustGetFloat();
smf.rolloffset = sc.Float;
}
// [BB] Added model flags reading.
else if (sc.Compare("ignoretranslation"))
{
smf.flags |= MDL_IGNORETRANSLATION;
}
else if (sc.Compare("pitchfrommomentum"))
{
smf.flags |= MDL_PITCHFROMMOMENTUM;
}
else if (sc.Compare("inheritactorpitch"))
{
smf.flags |= MDL_USEACTORPITCH | MDL_BADROTATION;
}
else if (sc.Compare("inheritactorroll"))
{
smf.flags |= MDL_USEACTORROLL;
}
else if (sc.Compare("useactorpitch"))
{
smf.flags |= MDL_USEACTORPITCH;
}
else if (sc.Compare("useactorroll"))
{
smf.flags |= MDL_USEACTORROLL;
}
else if (sc.Compare("rotating"))
{
smf.flags |= MDL_ROTATING;
smf.xrotate = 0.;
smf.yrotate = 1.;
smf.zrotate = 0.;
smf.rotationCenterX = 0.;
smf.rotationCenterY = 0.;
smf.rotationCenterZ = 0.;
smf.rotationSpeed = 1.;
}
else if (sc.Compare("rotation-speed"))
{
sc.MustGetFloat();
smf.rotationSpeed = sc.Float;
}
else if (sc.Compare("rotation-vector"))
{
sc.MustGetFloat();
smf.xrotate = sc.Float;
sc.MustGetFloat();
smf.yrotate = sc.Float;
sc.MustGetFloat();
smf.zrotate = sc.Float;
}
else if (sc.Compare("rotation-center"))
{
sc.MustGetFloat();
smf.rotationCenterX = sc.Float;
sc.MustGetFloat();
smf.rotationCenterY = sc.Float;
sc.MustGetFloat();
smf.rotationCenterZ = sc.Float;
}
else if (sc.Compare("interpolatedoubledframes"))
{
smf.flags |= MDL_INTERPOLATEDOUBLEDFRAMES;
}
else if (sc.Compare("nointerpolation"))
{
smf.flags |= MDL_NOINTERPOLATION;
}
else if (sc.Compare("skin"))
{
sc.MustGetNumber();
index=sc.Number;
if (index<0 || index>=MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
sc.MustGetString();
FixPathSeperator(sc.String);
if (sc.Compare(""))
{
smf.skinIDs[index]=FNullTextureID();
}
else
{
smf.skinIDs[index] = LoadSkin(path.GetChars(), sc.String);
if (!smf.skinIDs[index].isValid())
{
Printf("Skin '%s' not found in '%s'\n",
sc.String, smf.type->TypeName.GetChars());
}
}
}
else if (sc.Compare("surfaceskin"))
{
sc.MustGetNumber();
index = sc.Number;
sc.MustGetNumber();
surface = sc.Number;
if (index<0 || index >= MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
if (surface<0 || surface >= MD3_MAX_SURFACES)
{
sc.ScriptError("Invalid MD3 Surface %d in %s", MD3_MAX_SURFACES, smf.type->TypeName.GetChars());
}
sc.MustGetString();
FixPathSeperator(sc.String);
if (sc.Compare(""))
{
smf.surfaceskinIDs[index][surface] = FNullTextureID();
}
else
{
smf.surfaceskinIDs[index][surface] = LoadSkin(path.GetChars(), sc.String);
if (!smf.surfaceskinIDs[index][surface].isValid())
{
Printf("Surface Skin '%s' not found in '%s'\n",
sc.String, smf.type->TypeName.GetChars());
}
}
}
else if (sc.Compare("frameindex") || sc.Compare("frame"))
{
bool isframe=!!sc.Compare("frame");
sc.MustGetString();
smf.sprite = -1;
for (int i = 0; i < (int)sprites.Size (); ++i)
{
if (strnicmp (sprites[i].name, sc.String, 4) == 0)
{
if (sprites[i].numframes==0)
{
//sc.ScriptError("Sprite %s has no frames", sc.String);
}
smf.sprite = i;
break;
}
}
if (smf.sprite==-1)
{
sc.ScriptError("Unknown sprite %s in model definition for %s", sc.String, smf.type->TypeName.GetChars());
}
sc.MustGetString();
FString framechars = sc.String;
sc.MustGetNumber();
index=sc.Number;
if (index<0 || index>=MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
if (isframe)
{
sc.MustGetString();
if (smf.modelIDs[index] != -1)
{
FModel *model = Models[smf.modelIDs[index]];
smf.modelframes[index] = model->FindFrame(sc.String);
if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, smf.type->TypeName.GetChars());
}
else smf.modelframes[index] = -1;
}
else
{
sc.MustGetNumber();
smf.modelframes[index] = sc.Number;
}
for(int i=0; framechars[i]>0; i++)
{
char map[29]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int c = toupper(framechars[i])-'A';
if (c<0 || c>=29)
{
sc.ScriptError("Invalid frame character %c found", c+'A');
}
if (map[c]) continue;
smf.frame=c;
SpriteModelFrames.Push(smf);
GetDefaultByType(smf.type)->hasmodel = true;
map[c]=1;
}
}
else if (sc.Compare("dontcullbackfaces"))
{
smf.flags |= MDL_DONTCULLBACKFACES;
}
else if (sc.Compare("userotationcenter"))
{
smf.flags |= MDL_USEROTATIONCENTER;
smf.rotationCenterX = 0.;
smf.rotationCenterY = 0.;
smf.rotationCenterZ = 0.;
}
else
{
sc.ScriptMessage("Unrecognized string \"%s\"", sc.String);
}
}
}
else if (sc.Compare("#include"))
{
sc.MustGetString();
// This is not using sc.Open because it can print a more useful error message when done here
int includelump = Wads.CheckNumForFullName(sc.String, true);
if (includelump == -1)
{
if (strcmp(sc.String, "sentinel.modl") != 0) // Gene Tech mod has a broken #include statement
sc.ScriptError("Lump '%s' not found", sc.String);
}
else
{
ParseModelDefLump(includelump);
}
}
}
}
//===========================================================================
//
// gl_FindModelFrame
// FindModelFrame
//
//===========================================================================
FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped)
FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped)
{
if (GetDefaultByType(ti)->hasmodel)
{
@ -898,11 +909,11 @@ FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame,
//===========================================================================
//
// gl_IsHUDModelForPlayerAvailable
// IsHUDModelForPlayerAvailable
//
//===========================================================================
bool gl_IsHUDModelForPlayerAvailable (player_t * player)
bool IsHUDModelForPlayerAvailable (player_t * player)
{
if (player == nullptr || player->ReadyWeapon == nullptr)
return false;
@ -913,7 +924,7 @@ bool gl_IsHUDModelForPlayerAvailable (player_t * player)
return false;
FState* state = psp->GetState();
FSpriteModelFrame *smf = gl_FindModelFrame(player->ReadyWeapon->GetClass(), state->sprite, state->GetFrame(), false);
FSpriteModelFrame *smf = FindModelFrame(player->ReadyWeapon->GetClass(), state->sprite, state->GetFrame(), false);
return ( smf != nullptr );
}

View file

@ -46,6 +46,14 @@ FTextureID LoadSkin(const char * path, const char * fn);
struct FSpriteModelFrame;
class IModelVertexBuffer;
enum ModelRendererType
{
GLModelRendererType,
SWModelRendererType,
PolyModelRendererType,
NumModelRendererTypes
};
class FModelRenderer
{
public:
@ -54,6 +62,8 @@ public:
void RenderModel(float x, float y, float z, FSpriteModelFrame *modelframe, AActor *actor);
void RenderHUDModel(DPSprite *psp, float ofsx, float ofsy);
virtual ModelRendererType GetType() const = 0;
virtual void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) = 0;
virtual void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) = 0;
@ -73,8 +83,7 @@ public:
virtual void DrawElements(int numIndices, size_t offset) = 0;
private:
void RenderFrameModels(const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, Matrix3x4 *normaltransform, int translation);
static double GetTimeFloat();
void RenderFrameModels(const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, int translation);
};
struct FModelVertex
@ -123,11 +132,7 @@ public:
class FModel
{
public:
FModel()
{
mVBuf = NULL;
}
FModel();
virtual ~FModel();
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) = 0;
@ -135,19 +140,20 @@ public:
virtual void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0) = 0;
virtual void BuildVertexBuffer(FModelRenderer *renderer) = 0;
virtual void AddSkins(uint8_t *hitlist) = 0;
void DestroyVertexBuffer()
{
delete mVBuf;
mVBuf = NULL;
}
virtual float getAspectFactor() { return 1.f; }
void SetVertexBuffer(FModelRenderer *renderer, IModelVertexBuffer *buffer) { mVBuf[renderer->GetType()] = buffer; }
IModelVertexBuffer *GetVertexBuffer(FModelRenderer *renderer) const { return mVBuf[renderer->GetType()]; }
void DestroyVertexBuffer();
const FSpriteModelFrame *curSpriteMDLFrame;
int curMDLIndex;
void PushSpriteMDLFrame(const FSpriteModelFrame *smf, int index) { curSpriteMDLFrame = smf; curMDLIndex = index; };
IModelVertexBuffer *mVBuf;
FString mFileName;
private:
IModelVertexBuffer *mVBuf[NumModelRendererTypes];
};
class FDMDModel : public FModel
@ -473,9 +479,9 @@ struct FSpriteModelFrame
float pitchoffset, rolloffset; // I don't want to bother with type transformations, so I made this variables float.
};
FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped);
bool gl_IsHUDModelForPlayerAvailable (player_t * player);
FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped);
bool IsHUDModelForPlayerAvailable(player_t * player);
void FlushModels();
class DeletingModelArray : public TArray<FModel *>
{

View file

@ -279,15 +279,17 @@ FDMDModel::~FDMDModel()
void FDMDModel::BuildVertexBuffer(FModelRenderer *renderer)
{
if (mVBuf == NULL)
if (!GetVertexBuffer(renderer))
{
LoadGeometry();
int VertexBufferSize = info.numFrames * lodInfo[0].numTriangles * 3;
unsigned int vindex = 0;
mVBuf = renderer->CreateVertexBuffer(false, info.numFrames == 1);
FModelVertex *vertptr = mVBuf->LockVertexBuffer(VertexBufferSize);
auto vbuf = renderer->CreateVertexBuffer(false, info.numFrames == 1);
SetVertexBuffer(renderer, vbuf);
FModelVertex *vertptr = vbuf->LockVertexBuffer(VertexBufferSize);
for (int i = 0; i < info.numFrames; i++)
{
@ -313,7 +315,7 @@ void FDMDModel::BuildVertexBuffer(FModelRenderer *renderer)
tri++;
}
}
mVBuf->UnlockVertexBuffer();
vbuf->UnlockVertexBuffer();
UnloadGeometry();
}
}
@ -368,7 +370,7 @@ void FDMDModel::RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame
renderer->SetInterpolation(inter);
renderer->SetMaterial(skin, false, translation);
mVBuf->SetupFrame(renderer, frames[frameno].vindex, frames[frameno2].vindex, lodInfo[0].numTriangles * 3);
GetVertexBuffer(renderer)->SetupFrame(renderer, frames[frameno].vindex, frames[frameno2].vindex, lodInfo[0].numTriangles * 3);
renderer->DrawArrays(0, lodInfo[0].numTriangles * 3);
renderer->SetInterpolation(0.f);
}

View file

@ -237,7 +237,7 @@ void FMD3Model::LoadGeometry()
void FMD3Model::BuildVertexBuffer(FModelRenderer *renderer)
{
if (mVBuf == nullptr)
if (!GetVertexBuffer(renderer))
{
LoadGeometry();
@ -251,9 +251,11 @@ void FMD3Model::BuildVertexBuffer(FModelRenderer *renderer)
ibufsize += 3 * surf->numTriangles;
}
mVBuf = renderer->CreateVertexBuffer(true, numFrames == 1);
FModelVertex *vertptr = mVBuf->LockVertexBuffer(vbufsize);
unsigned int *indxptr = mVBuf->LockIndexBuffer(ibufsize);
auto vbuf = renderer->CreateVertexBuffer(true, numFrames == 1);
SetVertexBuffer(renderer, vbuf);
FModelVertex *vertptr = vbuf->LockVertexBuffer(vbufsize);
unsigned int *indxptr = vbuf->LockIndexBuffer(ibufsize);
assert(vertptr != nullptr && indxptr != nullptr);
@ -285,8 +287,8 @@ void FMD3Model::BuildVertexBuffer(FModelRenderer *renderer)
}
surf->UnloadGeometry();
}
mVBuf->UnlockVertexBuffer();
mVBuf->UnlockIndexBuffer();
vbuf->UnlockVertexBuffer();
vbuf->UnlockIndexBuffer();
}
}
@ -365,7 +367,7 @@ void FMD3Model::RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame
}
renderer->SetMaterial(surfaceSkin, false, translation);
mVBuf->SetupFrame(renderer, surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices, surf->numVertices);
GetVertexBuffer(renderer)->SetupFrame(renderer, surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices, surf->numVertices);
renderer->DrawElements(surf->numTriangles * 3, surf->iindex * sizeof(unsigned int));
}
renderer->SetInterpolation(0.f);

View file

@ -46,7 +46,7 @@ bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int
FMemLump lump2;
const char *buffer2;
FString realfilename = Wads.GetLumpFullName(lumpnum);
if ( realfilename.IndexOf("_d.3d") == realfilename.Len()-5 )
if ( (size_t)realfilename.IndexOf("_d.3d") == realfilename.Len()-5 )
{
realfilename.Substitute("_d.3d","_a.3d");
lumpnum2 = Wads.CheckNumForFullName(realfilename);
@ -98,9 +98,9 @@ void FUE1Model::LoadGeometry()
{
UE1Vertex Vert;
// unpack position
Vert.Pos.X = unpackuvert(averts[j+i*numVerts],0);
Vert.Pos.Y = unpackuvert(averts[j+i*numVerts],1);
Vert.Pos.Z = unpackuvert(averts[j+i*numVerts],2);
Vert.Pos = FVector3(unpackuvert(averts[j+i*numVerts],0),
unpackuvert(averts[j+i*numVerts],1),
unpackuvert(averts[j+i*numVerts],2));
// push vertex (without normals, will be calculated later)
verts.Push(Vert);
}
@ -114,10 +114,7 @@ void FUE1Model::LoadGeometry()
Poly.V[j] = dpolys[i].vertices[j];
// unpack coords
for ( int j=0; j<3; j++ )
{
Poly.C[j].S = dpolys[i].uv[j][0]/255.f;
Poly.C[j].T = dpolys[i].uv[j][1]/255.f;
}
Poly.C[j] = FVector2(dpolys[i].uv[j][0]/255.f,dpolys[i].uv[j][1]/255.f);
Poly.texNum = dpolys[i].texnum;
// push
polys.Push(Poly);
@ -129,39 +126,22 @@ void FUE1Model::LoadGeometry()
{
for ( int j=0; j<numVerts; j++ )
{
UE1Vector nsum = {0,0,0};
float total = 0.;
FVector3 nsum = FVector3(0,0,0);
for ( int k=0; k<numPolys; k++ )
{
if ( (polys[k].V[0] != j) && (polys[k].V[1] != j) && (polys[k].V[2] != j) ) continue;
UE1Vector vert[3], dir[2], norm;
FVector3 vert[3], dir[2], norm;
// compute facet normal
for ( int l=0; l<3; l++ )
vert[l] = verts[polys[k].V[l]+numVerts*i].Pos;
dir[0].X = vert[1].X-vert[0].X;
dir[0].Y = vert[1].Y-vert[0].Y;
dir[0].Z = vert[1].Z-vert[0].Z;
dir[1].X = vert[2].X-vert[0].X;
dir[1].Y = vert[2].Y-vert[0].Y;
dir[1].Z = vert[2].Z-vert[0].Z;
norm.X = dir[0].Y*dir[1].Z-dir[0].Z*dir[1].Y;
norm.Y = dir[0].Z*dir[1].X-dir[0].X*dir[1].Z;
norm.Z = dir[0].X*dir[1].Y-dir[0].Y*dir[1].X;
float s = (float)sqrt(norm.X*norm.X+norm.Y*norm.Y+norm.Z*norm.Z);
if ( s != 0.f )
{
norm.X /= s;
norm.Y /= s;
norm.Z /= s;
}
nsum.X += norm.X;
nsum.Y += norm.Y;
nsum.Z += norm.Z;
total+=1.f;
dir[0] = vert[1]-vert[0];
dir[1] = vert[2]-vert[0];
dir[0].MakeUnit();
dir[1].MakeUnit();
norm = dir[0]^dir[1];
nsum += norm.Unit();
}
verts[j+numVerts*i].Normal.X = nsum.X/total;
verts[j+numVerts*i].Normal.Y = nsum.Y/total;
verts[j+numVerts*i].Normal.Z = nsum.Z/total;
verts[j+numVerts*i].Normal = nsum.Unit();
}
}
// populate skin groups
@ -218,7 +198,7 @@ void FUE1Model::RenderFrame( FModelRenderer *renderer, FTexture *skin, int frame
}
}
renderer->SetMaterial(sskin,false,translation);
mVBuf->SetupFrame(renderer,vofs+frame*fsize,vofs+frame2*fsize,vsize);
GetVertexBuffer(renderer)->SetupFrame(renderer,vofs+frame*fsize,vofs+frame2*fsize,vsize);
renderer->DrawArrays(0,vsize);
vofs += vsize;
}
@ -227,14 +207,15 @@ void FUE1Model::RenderFrame( FModelRenderer *renderer, FTexture *skin, int frame
void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer )
{
if ( mVBuf != NULL )
if (GetVertexBuffer(renderer))
return;
int vsize = 0;
for ( int i=0; i<numGroups; i++ )
vsize += groups[i].numPolys*3;
vsize *= numFrames;
mVBuf = renderer->CreateVertexBuffer(false,numFrames==1);
FModelVertex *vptr = mVBuf->LockVertexBuffer(vsize);
auto vbuf = renderer->CreateVertexBuffer(false,numFrames==1);
SetVertexBuffer(renderer, vbuf);
FModelVertex *vptr = vbuf->LockVertexBuffer(vsize);
int vidx = 0;
for ( int i=0; i<numFrames; i++ )
{
@ -242,18 +223,18 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer )
{
for ( int k=0; k<groups[j].numPolys; k++ )
{
for ( int l=0; l<3; l++ )
for ( int l=2; l>=0; l-- )
{
UE1Vertex V = verts[polys[groups[j].P[k]].V[l]+i*numVerts];
UE1Coord C = polys[groups[j].P[k]].C[l];
FVector2 C = polys[groups[j].P[k]].C[l];
FModelVertex *vert = &vptr[vidx++];
vert->Set(V.Pos.X,V.Pos.Y,V.Pos.Z,C.S,C.T);
vert->Set(V.Pos.X,V.Pos.Y,V.Pos.Z,C.X,C.Y);
vert->SetNormal(V.Normal.X,V.Normal.Y,V.Normal.Z);
}
}
}
}
mVBuf->UnlockVertexBuffer();
vbuf->UnlockVertexBuffer();
}
void FUE1Model::AddSkins( uint8_t *hitlist )

View file

@ -56,22 +56,14 @@ private:
uint32_t * averts;
// converted data structures
struct UE1Coord
{
float S, T;
};
struct UE1Vector
{
float X, Y, Z;
};
struct UE1Vertex
{
UE1Vector Pos, Normal;
FVector3 Pos, Normal;
};
struct UE1Poly
{
int V[3];
UE1Coord C[3];
FVector2 C[3];
int texNum;
};
struct UE1Group

View file

@ -321,19 +321,21 @@ void FVoxelModel::Initialize()
void FVoxelModel::BuildVertexBuffer(FModelRenderer *renderer)
{
if (mVBuf == NULL)
if (!GetVertexBuffer(renderer))
{
Initialize();
mVBuf = renderer->CreateVertexBuffer(true, true);
FModelVertex *vertptr = mVBuf->LockVertexBuffer(mVertices.Size());
unsigned int *indxptr = mVBuf->LockIndexBuffer(mIndices.Size());
auto vbuf = renderer->CreateVertexBuffer(true, true);
SetVertexBuffer(renderer, vbuf);
FModelVertex *vertptr = vbuf->LockVertexBuffer(mVertices.Size());
unsigned int *indxptr = vbuf->LockIndexBuffer(mIndices.Size());
memcpy(vertptr, &mVertices[0], sizeof(FModelVertex)* mVertices.Size());
memcpy(indxptr, &mIndices[0], sizeof(unsigned int)* mIndices.Size());
mVBuf->UnlockVertexBuffer();
mVBuf->UnlockIndexBuffer();
vbuf->UnlockVertexBuffer();
vbuf->UnlockIndexBuffer();
mNumIndices = mIndices.Size();
// delete our temporary buffers
@ -398,7 +400,7 @@ float FVoxelModel::getAspectFactor()
void FVoxelModel::RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation)
{
renderer->SetMaterial(skin, true, translation);
mVBuf->SetupFrame(renderer, 0, 0, 0);
GetVertexBuffer(renderer)->SetupFrame(renderer, 0, 0, 0);
renderer->DrawElements(mNumIndices, 0);
}

View file

@ -34,7 +34,7 @@
#include "r_data/voxels.h"
#include "vm.h"
void gl_InitModels();
void InitModels();
// variables used to look up
// and range check thing_t sprites patches
@ -1048,7 +1048,7 @@ void R_InitSprites ()
// [RH] Sort the skins, but leave base as skin 0
//qsort (&skins[PlayerClasses.Size ()], numskins-PlayerClasses.Size (), sizeof(FPlayerSkin), skinsorter);
gl_InitModels();
InitModels();
}

View file

@ -979,6 +979,12 @@ public:
double CenterFloor() const { return floorplane.ZatPoint(centerspot); }
double CenterCeiling() const { return ceilingplane.ZatPoint(centerspot); }
void CopyColors(sector_t *other)
{
memcpy(SpecialColors, other->SpecialColors, sizeof(SpecialColors));
Colormap = other->Colormap;
}
// [RH] store floor and ceiling planes instead of heights
secplane_t floorplane, ceilingplane;
@ -986,26 +992,6 @@ public:
PalEntry SpecialColors[5];
FColormap Colormap;
private:
FDynamicColormap *_ColorMap; // [RH] Per-sector colormap
public:
// just a helper for refactoring
FDynamicColormap *GetColorMap()
{
return _ColorMap;
}
void CopyColors(sector_t *other)
{
memcpy(SpecialColors, other->SpecialColors, sizeof(SpecialColors));
Colormap = other->Colormap;
_ColorMap = other->_ColorMap;
}
TObjPtr<AActor*> SoundTarget;
short special;
@ -1101,9 +1087,11 @@ public:
vbo_fakeceiling = ceiling+2,
};
int vboindex[4]; // VBO indices of the 4 planes this sector uses during rendering
int vboindex[4]; // VBO indices of the 4 planes this sector uses during rendering. This is only needed for updating plane heights.
int iboindex[4]; // IBO indices of the 4 planes this sector uses during rendering
double vboheight[2]; // Last calculated height for the 2 planes of this actual sector
int vbocount[2]; // Total count of vertices belonging to this sector's planes
int vbocount[2]; // Total count of vertices belonging to this sector's planes. This is used when a sector height changes and also contains all attached planes.
int ibocount; // number of indices per plane (identical for all planes.) If this is -1 the index buffer is not in use.
float GetReflect(int pos) { return gl_plane_reflection_i? reflect[pos] : 0; }
bool VBOHeightcheck(int pos) const { return vboheight[pos] == GetPlaneTexZ(pos); }
@ -1295,6 +1283,26 @@ struct side_t
};
enum AutomapLineStyle : int
{
AMLS_Default,
AMLS_OneSided,
AMLS_TwoSided,
AMLS_FloorDiff,
AMLS_CeilingDiff,
AMLS_ExtraFloor,
AMLS_Special,
AMLS_Secret,
AMLS_NotSeen,
AMLS_Locked,
AMLS_IntraTeleport,
AMLS_InterTeleport,
AMLS_UnexploredSecret,
AMLS_Portal,
AMLS_COUNT
};
struct line_t
{
vertex_t *v1, *v2; // vertices, from v1 to v2
@ -1311,6 +1319,7 @@ struct line_t
int locknumber; // [Dusk] lock number for special
unsigned portalindex;
unsigned portaltransferred;
AutomapLineStyle automapstyle;
DVector2 Delta() const
{

View file

@ -962,7 +962,7 @@ namespace swrenderer
{
int spritenum = thing->sprite;
bool isPicnumOverride = thing->picnum.isValid();
FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : gl_FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
if (modelframe && (thing->Pos() - Thread->Viewport->viewpoint.Pos).LengthSquared() < model_distance_cull)
{
DVector3 pos = thing->InterpolatedPosition(Thread->Viewport->viewpoint.TicFrac);

View file

@ -34,9 +34,6 @@
#include "swrenderer/viewport/r_viewport.h"
#include "swrenderer/scene/r_light.h"
void gl_FlushModels();
extern bool polymodelsInUse;
namespace swrenderer
{
void RenderModel::Project(RenderThread *thread, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor)
@ -83,11 +80,6 @@ namespace swrenderer
SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor) : Thread(thread), Clip3DFloor(clip3DFloor)
{
if (polymodelsInUse)
{
gl_FlushModels();
polymodelsInUse = false;
}
}
void SWModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix)
@ -128,11 +120,13 @@ namespace swrenderer
}
SetTransform();
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true);
}
void SWModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf)
{
ModelActor = nullptr;
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false);
}
IModelVertexBuffer *SWModelRenderer::CreateVertexBuffer(bool needindex, bool singleframe)
@ -191,12 +185,14 @@ namespace swrenderer
ClipBottom = {};
SetTransform();
PolyTriangleDrawer::SetWeaponScene(Thread->DrawQueue, true);
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true);
}
void SWModelRenderer::EndDrawHUDModel(AActor *actor)
{
ModelActor = nullptr;
PolyTriangleDrawer::SetWeaponScene(Thread->DrawQueue, false);
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false);
}
void SWModelRenderer::SetInterpolation(double interpolation)

View file

@ -54,6 +54,8 @@ namespace swrenderer
public:
SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor);
ModelRendererType GetType() const override { return SWModelRendererType; }
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override;
void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override;
IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override;

View file

@ -94,7 +94,7 @@ namespace swrenderer
(r_deathcamera && Thread->Viewport->viewpoint.camera->health <= 0))
return;
renderHUDModel = r_models && gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
renderHUDModel = r_models && IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
FDynamicColormap *basecolormap;
CameraLight *cameraLight = CameraLight::Instance();

View file

@ -81,7 +81,6 @@ CUSTOM_CVAR(Bool, gl_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINI
CUSTOM_CVAR(Bool, vr_enable_quadbuffered, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
Printf("You must restart " GAMENAME " to switch quad stereo mode\n");
screen->enable_quadbuffered = self;
}
EXTERN_CVAR(Int, vid_refreshrate)
@ -1082,6 +1081,7 @@ SystemFrameBuffer::SystemFrameBuffer(void *hMonitor, int width, int height, int
m_supportsGamma = !!GetDeviceGammaRamp(hDC, (void *)m_origGamma);
ReleaseDC(Window, hDC);
enable_quadbuffered = vr_enable_quadbuffered;
}
//==========================================================================
@ -1159,10 +1159,15 @@ bool SystemFrameBuffer::IsFullscreen()
//
//
//==========================================================================
EXTERN_CVAR(Bool, vid_vsync);
CUSTOM_CVAR(Bool, gl_control_tear, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
vid_vsync.Callback();
}
void SystemFrameBuffer::SetVSync (bool vsync)
{
if (myWglSwapIntervalExtProc != NULL) myWglSwapIntervalExtProc(vsync ? SwapInterval : 0);
if (myWglSwapIntervalExtProc != NULL) myWglSwapIntervalExtProc(vsync ? (gl_control_tear? SwapInterval : 1) : 0);
}
void SystemFrameBuffer::SwapBuffers()

View file

@ -9,6 +9,10 @@ vec3 lightContribution(int i, vec3 normal)
float lightdistance = distance(lightpos.xyz, pixelpos.xyz);
if (lightpos.w < lightdistance)
return vec3(0.0); // Early out lights touching surface but not this fragment
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
float dotprod = dot(normal, lightdir);
if (dotprod < 0.0) return vec3(0.0); // light hits from the backside. This can happen with full sector light lists and must be rejected for all cases.
float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0);
@ -17,8 +21,7 @@ vec3 lightContribution(int i, vec3 normal)
if (lightcolor.a < 0.0) // Sign bit is the attenuated light flag
{
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
attenuation *= clamp(dot(normal, lightdir), 0.0, 1.0);
attenuation *= clamp(dotprod, 0.0, 1.0);
}
if (attenuation > 0.0) // Skip shadow map test if possible

View file

@ -12,7 +12,7 @@ struct SBarInfo native ui
}
// The sole purpose of this wrapper is to elimintate the native dependencies of the status bar object
// The sole purpose of this wrapper is to eliminate the native dependencies of the status bar object
// because those would seriously impede the script conversion of the base class.
class SBarInfoWrapper : BaseStatusBar