diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 185d2a6de..84dcd4d29 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -120,9 +120,26 @@ Note: All fields default to false unless mentioned otherwise. blockhitscan = ; // Line blocks hitscan attacks locknumber = ; // Line special is locked arg0str = ; // Alternate string-based version of arg0 - moreids = ; // Additional line IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505") + moreids = ; // Additional line IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505") - transparent = ; // true = line is a Strife transparent line (alpha 0.25) + transparent = ; // true = line is a Strife transparent line (alpha 0.25) + + automapstyle = ; // 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 = ; // true = line is initially visible on automap. * Note about arg0str @@ -171,14 +188,14 @@ Note: All fields default to false unless mentioned otherwise. yscaleceiling = ; // Y texture scale of ceiling texture, Default = 1.0. rotationfloor = ; // Rotation of floor texture in degrees, Default = 0.0. rotationceiling = ; // Rotation of ceiling texture in degrees, Default = 0.0. - ceilingplane_a = ; // Define the plane equation for the sector's ceiling. Default is a horizontal plane at 'heightceiling'. - ceilingplane_b = ; // 'heightceiling' will still be used to calculate texture alignment. - ceilingplane_c = ; // The plane equation will only be used if all 4 values are given. - ceilingplane_d = ; - floorplane_a = ; // Define the plane equation for the sector's floor. Default is a horizontal plane at 'heightfloor'. - floorplane_b = ; // 'heightfloor' will still be used to calculate texture alignment. - floorplane_c = ; // The plane equation will only be used if all 4 values are given. - floorplane_d = ; + ceilingplane_a = ; // Define the plane equation for the sector's ceiling. Default is a horizontal plane at 'heightceiling'. + ceilingplane_b = ; // 'heightceiling' will still be used to calculate texture alignment. + ceilingplane_c = ; // The plane equation will only be used if all 4 values are given. + ceilingplane_d = ; + floorplane_a = ; // Define the plane equation for the sector's floor. Default is a horizontal plane at 'heightfloor'. + floorplane_b = ; // 'heightfloor' will still be used to calculate texture alignment. + floorplane_c = ; // The plane equation will only be used if all 4 values are given. + floorplane_d = ; lightfloor = ; // The floor's light level. Default is 0. lightceiling = ; // The ceiling's light level. Default is 0. lightfloorabsolute = ; // true = 'lightfloor' is an absolute value. Default is @@ -196,8 +213,8 @@ Note: All fields default to false unless mentioned otherwise. fadecolor = ; // Sector's fog color as RRGGBB value, default = 0x000000. desaturation = ; // Color desaturation factor. 0 = none, 1 = full, default = 0. silent = ; // Actors in this sector make no sound, - nofallingdamage = ; // Falling damage is disabled in this sector - noattack = ; // Blocks monster attacks in this sector. + nofallingdamage = ; // Falling damage is disabled in this sector + noattack = ; // Blocks monster attacks in this sector. dropactors = ; // Actors drop with instantly moving floors (*) norespawn = ; // Players can not respawn in this sector soundsequence = ; // The sound sequence to play when this sector moves. Placing a @@ -215,21 +232,21 @@ Note: All fields default to false unless mentioned otherwise. damagehazard = ; // Changes damage model to Strife's delayed damage for the given sector. Default = false. floorterrain = ; // Sets the terrain for the sector's floor. Default = 'use the flat texture's terrain definition.' ceilingterrain = ; // Sets the terrain for the sector's ceiling. Default = 'use the flat texture's terrain definition.' - floor_reflect = ; // reflectiveness of floor (OpenGL only, not functional on sloped sectors) - ceiling_reflect = ; // reflectiveness of ceiling (OpenGL only, not functional on sloped sectors) - fogdensity = ; // 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 = ; // 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 = ; // 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 = ; // 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 = ; // 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 = ; // Material color of sector's floor. Default is white (0xffffff) - color_ceiling = ; // Material color of sector's ceiling. Default is white (0xffffff) - color_walltop = ; // 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 = ; // Material color of bottom of sector's sidedefs (OpenGL 3.x and later only) Default is white (0xffffff) - color_sprites = ; // Material color of sprites in sector. Default is white (0xffffff) - + floor_reflect = ; // reflectiveness of floor (OpenGL only, not functional on sloped sectors) + ceiling_reflect = ; // reflectiveness of ceiling (OpenGL only, not functional on sloped sectors) + fogdensity = ; // 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 = ; // 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 = ; // 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 = ; // 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 = ; // 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 = ; // Material color of sector's floor. Default is white (0xffffff) + color_ceiling = ; // Material color of sector's ceiling. Default is white (0xffffff) + color_walltop = ; // 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 = ; // Material color of bottom of sector's sidedefs (OpenGL 3.x and later only) Default is white (0xffffff) + color_sprites = ; // Material color of sprites in sector. Default is white (0xffffff) + portal_ceil_blocksound = // ceiling portal blocks sound. portal_ceil_disabled = // ceiling portal disabled. @@ -241,8 +258,8 @@ Note: All fields default to false unless mentioned otherwise. portal_floor_nopass = // ceiling portal blocks movement if true. portal_floor_norender = // ceiling portal not rendered. portal_floor_overlaytype = // 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 fields default to false unless mentioned otherwise. thing { - skill# = // Unlike the base spec, # can range from 1-16. - class# = // Unlike the base spec, # can range from 1-16. - conversation = // Assigns a conversation dialogue to this thing. + skill# = // Unlike the base spec, # can range from 1-16. + class# = // Unlike the base spec, # can range from 1-16. + conversation = // Assigns a conversation dialogue to this thing. // Parameter is the conversation ID, 0 meaning none. countsecret = ; // Picking up this actor counts as a secret. arg0str = ; // Alternate string-based version of arg0 - gravity = ; // Set per-actor gravity. Positive values are multiplied with the class's property, - // negative values are used as their absolute. Default = 1.0. - - health = ; // Set per-actor health. Positive values are multiplied with the class's property, - // negative values are used as their absolute. Default = 1. - - renderstyle = ; // 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 = ; // Fill color used by the "stencil", "addstencil" and "translucentstencil" rendestyles, as RRGGBB value, default = 0x000000. - alpha = ; // Translucency of this actor (if applicable to renderstyle), default is 1.0. - score = ; // Score value of this actor, overriding the class default if not null. Default = 0. - pitch = ; // Pitch of thing in degrees. Default = 0 (horizontal). - roll = ; // Pitch of thing in degrees. Default = 0 (horizontal). - scalex = ; // Vertical scaling on thing. Default = 0 (ignored). - scaley = ; // Horizontal scaling on thing. Default = 0 (ignored). - scale = ; // Vertical and horizontal scaling on thing. Default = 0 (ignored). - floatbobphase = ; // Sets the thing's floatbobphase. Valid phase values are 0-63. Default = -1 (use actor class default). + gravity = ; // Set per-actor gravity. Positive values are multiplied with the class's property, + // negative values are used as their absolute. Default = 1.0. + + health = ; // Set per-actor health. Positive values are multiplied with the class's property, + // negative values are used as their absolute. Default = 1. + + renderstyle = ; // 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 = ; // Fill color used by the "stencil", "addstencil" and "translucentstencil" rendestyles, as RRGGBB value, default = 0x000000. + alpha = ; // Translucency of this actor (if applicable to renderstyle), default is 1.0. + score = ; // Score value of this actor, overriding the class default if not null. Default = 0. + pitch = ; // Pitch of thing in degrees. Default = 0 (horizontal). + roll = ; // Pitch of thing in degrees. Default = 0 (horizontal). + scalex = ; // Vertical scaling on thing. Default = 0 (ignored). + scaley = ; // Horizontal scaling on thing. Default = 0 (ignored). + scale = ; // Vertical and horizontal scaling on thing. Default = 0 (ignored). + floatbobphase = ; // 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 =============================================================================== diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0acecbe6a..16c23743a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/am_map.cpp b/src/am_map.cpp index 5b717e285..20f99de36 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -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)) { diff --git a/src/doomdata.h b/src/doomdata.h index 58bfea68a..38a65ca50 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -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.) }; diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index 5ff6c7710..0dd2930ff 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -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; isector->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; diff --git a/src/gl/data/gl_vertexbuffer.cpp b/src/gl/data/gl_vertexbuffer.cpp index ce32b3ab4..bf867f13e 100644 --- a/src/gl/data/gl_vertexbuffer.cpp +++ b/src/gl/data/gl_vertexbuffer.cpp @@ -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); + } } diff --git a/src/gl/data/gl_vertexbuffer.h b/src/gl/data/gl_vertexbuffer.h index 28fe8f45c..7c54b1916 100644 --- a/src/gl/data/gl_vertexbuffer.h +++ b/src/gl/data/gl_vertexbuffer.h @@ -95,6 +95,7 @@ public: class FFlatVertexBuffer : public FVertexBuffer, public FFlatVertexGenerator { + unsigned int ibo_id; FFlatVertex *map; unsigned int mIndex; std::atomic 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() diff --git a/src/gl/models/gl_models.h b/src/gl/models/gl_models.h index f9458890a..821705c34 100644 --- a/src/gl/models/gl_models.h +++ b/src/gl/models/gl_models.h @@ -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; diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index f8d2ead8f..154fae2d6 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -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; diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index d3ac02671..7cdf3b01d 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -87,7 +87,7 @@ class FGLRenderer public: OpenGLFrameBuffer *framebuffer; - GLPortal *mClipPortal; + //GLPortal *mClipPortal; GLPortal *mCurrentPortal; int mMirrorCount; int mPlaneMirrorCount; diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 305a5177c..a0a1c5cc8 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -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; diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index 1db6602a5..8aa4d0093 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -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) diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index b9ee2067d..abcdbe70b 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -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(§orrenderflags[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 FDrawInfo::AllocVertices(unsigned int count) { unsigned int index = -1; diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index 05ca3dd8d..8da945e6c 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -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 &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 diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index ff55d1161..70ca080f2 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -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; isector->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; isector->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; } diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index e5c1064af..25b2ff236 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -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; iportalcoverage[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 (afclipper.SafeAddClipRangeRealAngles(r_viewpoint.Angles.Yaw.BAMs()+af, r_viewpoint.Angles.Yaw.BAMs()-af); + if (afmClipper->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); +} diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index 628ea4614..5f646f41c 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -49,7 +49,7 @@ extern UniqueList UniquePlaneMirrors; struct GLEEHorizonPortal; class GLSceneDrawer; -class GLPortal +class GLPortal : public IPortal { static TArray 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 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 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; } diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 70350b018..f2e0301fb 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -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(); diff --git a/src/gl/scene/gl_scenedrawer.h b/src/gl/scene/gl_scenedrawer.h index cc712c4ac..d075e1418 100644 --- a/src/gl/scene/gl_scenedrawer.h +++ b/src/gl/scene/gl_scenedrawer.h @@ -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 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); diff --git a/src/gl/scene/gl_skydome.cpp b/src/gl/scene/gl_skydome.cpp index a476d2ab3..38a70ea33 100644 --- a/src/gl/scene/gl_skydome.cpp +++ b/src/gl/scene/gl_skydome.cpp @@ -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; diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 2713cf759..2bafaf72a 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -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; } diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index a49593550..2dbe156dd 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -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); } diff --git a/src/gl/stereo3d/gl_stereo_cvars.cpp b/src/gl/stereo3d/gl_stereo_cvars.cpp index c726ef4bb..e826e9a12 100644 --- a/src/gl/stereo3d/gl_stereo_cvars.cpp +++ b/src/gl/stereo3d/gl_stereo_cvars.cpp @@ -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) diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index d83581249..81cbd7eeb 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -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); diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index a220b0a34..898820cc9 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -64,7 +64,6 @@ public: bool HWGammaActive = false; // Are we using hardware or software gamma? std::shared_ptr 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 diff --git a/src/gl_load/gl_interface.cpp b/src/gl_load/gl_interface.cpp index ee47ce5a0..6e07259f5 100644 --- a/src/gl_load/gl_interface.cpp +++ b/src/gl_load/gl_interface.cpp @@ -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; diff --git a/src/hwrenderer/data/flatvertices.cpp b/src/hwrenderer/data/flatvertices.cpp index 86bf78261..1decb2c04 100644 --- a/src/hwrenderer/data/flatvertices.cpp +++ b/src/hwrenderer/data/flatvertices.cpp @@ -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; knumlines; 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; knumlines; 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; jsubsectorcount; 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; jsubsectorcount; 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 &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 &fakes = sec->e->FakeFloor.Sectors; - for (unsigned g=0; gvboindex[2+h] = CreateSectorVertices(fsec, plane, false); + fsec->iboindex[2 + h] = CreateIndexedSectorVertices(fsec, plane, false, gen[fsec->Index()]); } // and finally all attached 3D floors TArray &xf = sec->e->XFloor.attached; - for (unsigned g=0; gtop.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 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; iz = (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); } diff --git a/src/hwrenderer/data/flatvertices.h b/src/hwrenderer/data/flatvertices.h index 9a45558b5..3025a6820 100644 --- a/src/hwrenderer/data/flatvertices.h +++ b/src/hwrenderer/data/flatvertices.h @@ -45,9 +45,32 @@ class FFlatVertexGenerator { protected: TArray vbo_shadowdata; + TArray ibo_data; + FFlatVertex *mMap; + // Temporary data for creating an indexed buffer + struct FIndexGenerationInfo + { + TArray vertices; + TMap 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 &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 \ No newline at end of file diff --git a/src/gl/scene/gl_bsp.cpp b/src/hwrenderer/scene/hw_bsp.cpp similarity index 82% rename from src/gl/scene/gl_bsp.cpp rename to src/hwrenderer/scene/hw_bsp.cpp index 2449fce9e..4393424c1 100644 --- a/src/gl/scene/gl_bsp.cpp +++ b/src/hwrenderer/scene/hw_bsp.cpp @@ -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; } diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index 429981c89..e9db60a09 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -3,6 +3,7 @@ #include #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 spriteindex; - bool clipPortal; + IPortal *mClipPortal; FRotator mAngles; FVector2 mViewVector; AActor *mViewActor; IShadowMap *mShadowMap; + Clipper *mClipper; TArray MissingUpperTextures; TArray MissingLowerTextures; @@ -104,16 +109,38 @@ struct HWDrawInfo TArray ss_renderflags; TArray 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 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 AllocVertices(unsigned int count) = 0; - virtual int ClipPoint(const DVector3 &pos) = 0; - - }; diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index 7aa7e0b7d..5758cf0b8 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -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); diff --git a/src/hwrenderer/scene/hw_fakeflat.cpp b/src/hwrenderer/scene/hw_fakeflat.cpp index 0e22e276f..e4e986ca8 100644 --- a/src/hwrenderer/scene/hw_fakeflat.cpp +++ b/src/hwrenderer/scene/hw_fakeflat.cpp @@ -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. + } +} diff --git a/src/hwrenderer/scene/hw_flats.cpp b/src/hwrenderer/scene/hw_flats.cpp index dabee535d..27e31843f 100644 --- a/src/hwrenderer/scene/hw_flats.cpp +++ b/src/hwrenderer/scene/hw_flats.cpp @@ -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; diff --git a/src/hwrenderer/scene/hw_portal.h b/src/hwrenderer/scene/hw_portal.h index 3037ed8c1..695daaa98 100644 --- a/src/hwrenderer/scene/hw_portal.h +++ b/src/hwrenderer/scene/hw_portal.h @@ -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; } +}; diff --git a/src/hwrenderer/scene/hw_renderhacks.cpp b/src/hwrenderer/scene/hw_renderhacks.cpp index 5eacd9dfc..57fef57e0 100644 --- a/src/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/hwrenderer/scene/hw_renderhacks.cpp @@ -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(§orrenderflags[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) { diff --git a/src/hwrenderer/scene/hw_sprites.cpp b/src/hwrenderer/scene/hw_sprites.cpp index 6814d1760..0e86b88ba 100644 --- a/src/hwrenderer/scene/hw_sprites.cpp +++ b/src/hwrenderer/scene/hw_sprites.cpp @@ -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; diff --git a/src/hwrenderer/scene/hw_weapon.cpp b/src/hwrenderer/scene/hw_weapon.cpp index 781f3395a..c22d2183a 100644 --- a/src/hwrenderer/scene/hw_weapon.cpp +++ b/src/hwrenderer/scene/hw_weapon.cpp @@ -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; diff --git a/src/hwrenderer/textures/hw_precache.cpp b/src/hwrenderer/textures/hw_precache.cpp index a40a8a821..a6342d2fb 100644 --- a/src/hwrenderer/textures/hw_precache.cpp +++ b/src/hwrenderer/textures/hw_precache.cpp @@ -119,7 +119,7 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap &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++) diff --git a/src/namedef.h b/src/namedef.h index 9e6d3811a..b098a06c0 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -537,6 +537,8 @@ xx(Repeatspecial) xx(Conversation) xx(Locknumber) xx(Midtex3dimpassible) +xx(Revealed) +xx(AutomapStyle) xx(Playercross) xx(Playeruse) diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index 4254c92d4..5c6096f84 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -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)) { diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 56850f6a0..dba5a109e 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -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; } diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 24a7fd5fd..6acf9e37c 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -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 diff --git a/src/polyrenderer/drawers/poly_triangle.cpp b/src/polyrenderer/drawers/poly_triangle.cpp index 37052aee7..beefb33d7 100644 --- a/src/polyrenderer/drawers/poly_triangle.cpp +++ b/src/polyrenderer/drawers/poly_triangle.cpp @@ -79,6 +79,11 @@ void PolyTriangleDrawer::SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw queue->Push(ccw); } +void PolyTriangleDrawer::SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided) +{ + queue->Push(twosided); +} + void PolyTriangleDrawer::SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable) { queue->Push(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) { } diff --git a/src/polyrenderer/drawers/poly_triangle.h b/src/polyrenderer/drawers/poly_triangle.h index 3cd88d803..628bdb009 100644 --- a/src/polyrenderer/drawers/poly_triangle.h +++ b/src/polyrenderer/drawers/poly_triangle.h @@ -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: diff --git a/src/polyrenderer/scene/poly_model.cpp b/src/polyrenderer/scene/poly_model.cpp index bb0c3fb52..cc8a111ea 100644 --- a/src/polyrenderer/scene/poly_model.cpp +++ b/src/polyrenderer/scene/poly_model.cpp @@ -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(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(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) diff --git a/src/polyrenderer/scene/poly_model.h b/src/polyrenderer/scene/poly_model.h index cc12f9e6e..cbfafce59 100644 --- a/src/polyrenderer/scene/poly_model.h +++ b/src/polyrenderer/scene/poly_model.h @@ -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; diff --git a/src/polyrenderer/scene/poly_playersprite.cpp b/src/polyrenderer/scene/poly_playersprite.cpp index c7d75ef33..e08857de9 100644 --- a/src/polyrenderer/scene/poly_playersprite.cpp +++ b/src/polyrenderer/scene/poly_playersprite.cpp @@ -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); diff --git a/src/polyrenderer/scene/poly_sprite.cpp b/src/polyrenderer/scene/poly_sprite.cpp index 12406b5c0..88ffb99b6 100644 --- a/src/polyrenderer/scene/poly_sprite.cpp +++ b/src/polyrenderer/scene/poly_sprite.cpp @@ -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; diff --git a/src/portal.h b/src/portal.h index f194c3886..343e09b29 100644 --- a/src/portal.h +++ b/src/portal.h @@ -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); }; diff --git a/src/r_data/models/models.cpp b/src/r_data/models/models.cpp index ad4e72576..1a898f062 100644 --- a/src/r_data/models/models.cpp +++ b/src/r_data/models/models.cpp @@ -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(time)); + ticFraction = I_GetTimeFrac(); } - inter = static_cast(curState->Tics - curTics - ticFraction) / static_cast(curState->Tics); + inter = static_cast(curState->Tics - curTics + ticFraction) / static_cast(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 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;iVoxel->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 ); } diff --git a/src/r_data/models/models.h b/src/r_data/models/models.h index 91d3d14d6..b0d0f0230 100644 --- a/src/r_data/models/models.h +++ b/src/r_data/models/models.h @@ -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 { diff --git a/src/r_data/models/models_md2.cpp b/src/r_data/models/models_md2.cpp index 999e0cd82..ce9566a8f 100644 --- a/src/r_data/models/models_md2.cpp +++ b/src/r_data/models/models_md2.cpp @@ -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); } diff --git a/src/r_data/models/models_md3.cpp b/src/r_data/models/models_md3.cpp index 31f2c31cb..f47ee90cd 100644 --- a/src/r_data/models/models_md3.cpp +++ b/src/r_data/models/models_md3.cpp @@ -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); diff --git a/src/r_data/models/models_ue1.cpp b/src/r_data/models/models_ue1.cpp index e07f471b9..98ea08a19 100644 --- a/src/r_data/models/models_ue1.cpp +++ b/src/r_data/models/models_ue1.cpp @@ -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; jSetMaterial(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; iCreateVertexBuffer(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=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 ) diff --git a/src/r_data/models/models_ue1.h b/src/r_data/models/models_ue1.h index 91d568047..dc6209fa2 100644 --- a/src/r_data/models/models_ue1.h +++ b/src/r_data/models/models_ue1.h @@ -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 diff --git a/src/r_data/models/models_voxel.cpp b/src/r_data/models/models_voxel.cpp index 3c9af2374..e25a72613 100644 --- a/src/r_data/models/models_voxel.cpp +++ b/src/r_data/models/models_voxel.cpp @@ -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); } diff --git a/src/r_data/sprites.cpp b/src/r_data/sprites.cpp index ce6123c18..c1f1f3e02 100644 --- a/src/r_data/sprites.cpp +++ b/src/r_data/sprites.cpp @@ -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(); } diff --git a/src/r_defs.h b/src/r_defs.h index 49a6d244d..4ba0d45d3 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -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 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 { diff --git a/src/swrenderer/scene/r_opaque_pass.cpp b/src/swrenderer/scene/r_opaque_pass.cpp index 14e42379d..5a88c8086 100644 --- a/src/swrenderer/scene/r_opaque_pass.cpp +++ b/src/swrenderer/scene/r_opaque_pass.cpp @@ -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); diff --git a/src/swrenderer/things/r_model.cpp b/src/swrenderer/things/r_model.cpp index 8040797b5..2d09ca276 100644 --- a/src/swrenderer/things/r_model.cpp +++ b/src/swrenderer/things/r_model.cpp @@ -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) diff --git a/src/swrenderer/things/r_model.h b/src/swrenderer/things/r_model.h index 0519d5588..004636e69 100644 --- a/src/swrenderer/things/r_model.h +++ b/src/swrenderer/things/r_model.h @@ -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; diff --git a/src/swrenderer/things/r_playersprite.cpp b/src/swrenderer/things/r_playersprite.cpp index acb521500..e1156f4fd 100644 --- a/src/swrenderer/things/r_playersprite.cpp +++ b/src/swrenderer/things/r_playersprite.cpp @@ -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(); diff --git a/src/win32/win32gliface.cpp b/src/win32/win32gliface.cpp index 875a1a78b..cb6da5ff9 100644 --- a/src/win32/win32gliface.cpp +++ b/src/win32/win32gliface.cpp @@ -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() diff --git a/wadsrc/static/shaders/glsl/material_normal.fp b/wadsrc/static/shaders/glsl/material_normal.fp index b048f4559..6b65de6a3 100644 --- a/wadsrc/static/shaders/glsl/material_normal.fp +++ b/wadsrc/static/shaders/glsl/material_normal.fp @@ -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 diff --git a/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt b/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt index efc6bedc8..96f006320 100644 --- a/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt +++ b/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt @@ -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