diff --git a/src/gl/dynlights/gl_shadowmap.cpp b/src/gl/dynlights/gl_shadowmap.cpp index 0f493b751..4ef06efa3 100644 --- a/src/gl/dynlights/gl_shadowmap.cpp +++ b/src/gl/dynlights/gl_shadowmap.cpp @@ -82,12 +82,10 @@ ADD_STAT(shadowmap) return out; } -CUSTOM_CVAR(Int, gl_shadowmap_quality, 128, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Int, gl_shadowmap_quality, 512, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { switch (self) { - case 32: - case 64: case 128: case 256: case 512: diff --git a/src/polyrenderer/scene/poly_cull.cpp b/src/polyrenderer/scene/poly_cull.cpp index 93041650d..e759bdda4 100644 --- a/src/polyrenderer/scene/poly_cull.cpp +++ b/src/polyrenderer/scene/poly_cull.cpp @@ -33,11 +33,32 @@ void PolyCull::CullScene(const TriMatrix &worldToClip, const PolyClipPlane &port ClearSolidSegments(); MarkViewFrustum(); + if (level.LevelName != lastLevelName) // Is this the best way to detect a level change? + { + lastLevelName = level.LevelName; + SubsectorDepths.clear(); + SubsectorDepths.resize(level.subsectors.Size(), 0xffffffff); + SectorSeen.clear(); + SectorSeen.resize(level.sectors.Size()); + } + else + { + for (const auto &sub : PvsSectors) + SubsectorDepths[sub->Index()] = 0xffffffff; + SubsectorDepths.resize(level.subsectors.Size(), 0xffffffff); + + for (const auto §or : SeenSectors) + SectorSeen[sector->Index()] = false; + SectorSeen.resize(level.sectors.Size()); + } + PvsSectors.clear(); - PvsLineStart.clear(); - PvsLineVisible.clear(); SeenSectors.clear(); - SubsectorDepths.clear(); + + NextPvsLineStart = 0; + PvsLineStart.clear(); + PvsLineVisible.resize(level.segs.Size()); + PortalClipPlane = portalClipPlane; // Cull front to back @@ -108,7 +129,7 @@ void PolyCull::CullSubsector(subsector_t *sub) // Mark that we need to render this PvsSectors.push_back(sub); - PvsLineStart.push_back((uint32_t)PvsLineVisible.size()); + PvsLineStart.push_back(NextPvsLineStart); DVector3 viewpos = PolyRenderer::Instance()->Viewpoint.Pos; @@ -122,7 +143,7 @@ void PolyCull::CullSubsector(subsector_t *sub) DVector2 pt2 = line->v2->fPos() - viewpos; if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0) { - PvsLineVisible.push_back(false); + PvsLineVisible[NextPvsLineStart++] = false; continue; } @@ -130,7 +151,7 @@ void PolyCull::CullSubsector(subsector_t *sub) if ((PortalClipPlane.A * line->v1->fX() + PortalClipPlane.B * line->v1->fY() + PortalClipPlane.D <= 0.0) || (PortalClipPlane.A * line->v2->fX() + PortalClipPlane.B * line->v2->fY() + PortalClipPlane.D <= 0.0)) { - PvsLineVisible.push_back(false); + PvsLineVisible[NextPvsLineStart++] = false; continue; } @@ -142,11 +163,16 @@ void PolyCull::CullSubsector(subsector_t *sub) } // Mark if this line was visible - PvsLineVisible.push_back(lineVisible); + PvsLineVisible[NextPvsLineStart++] = lineVisible; } - SeenSectors.insert(sub->sector); - SubsectorDepths[sub] = subsectorDepth; + if (!SectorSeen[sub->sector->Index()]) + { + SectorSeen[sub->sector->Index()] = true; + SeenSectors.push_back(sub->sector); + } + + SubsectorDepths[sub->Index()] = subsectorDepth; } void PolyCull::ClearSolidSegments() diff --git a/src/polyrenderer/scene/poly_cull.h b/src/polyrenderer/scene/poly_cull.h index 29c47134d..fe8000501 100644 --- a/src/polyrenderer/scene/poly_cull.h +++ b/src/polyrenderer/scene/poly_cull.h @@ -40,8 +40,9 @@ public: double MaxCeilingHeight = 0.0; double MinFloorHeight = 0.0; - std::set SeenSectors; - std::unordered_map SubsectorDepths; + std::vector SeenSectors; + std::vector SectorSeen; + std::vector SubsectorDepths; static angle_t PointToPseudoAngle(double x, double y); @@ -69,6 +70,8 @@ private: void MarkSegmentCulled(angle_t angle1, angle_t angle2); + FString lastLevelName; + std::vector SolidSegments; std::vector TempInvertSolidSegments; const int SolidCullScale = 3000; @@ -78,6 +81,7 @@ private: std::vector PvsLineStart; std::vector PvsLineVisible; + uint32_t NextPvsLineStart = 0; static angle_t AngleToPseudo(angle_t ang); }; diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index d315a02e5..6f84c2d4f 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -213,9 +213,8 @@ void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, doub if (level.nodes.Size() == 0) { subsector_t *sub = &level.subsectors[0]; - auto it = Cull.SubsectorDepths.find(sub); - if (it != Cull.SubsectorDepths.end()) - TranslucentObjects[thread->ThreadIndex].push_back(thread->FrameMemory->NewObject(thing, sub, it->second, sortDistance, 0.0f, 1.0f, StencilValue)); + if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff) + TranslucentObjects[thread->ThreadIndex].push_back(thread->FrameMemory->NewObject(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, 0.0f, 1.0f, StencilValue)); } else { @@ -254,9 +253,8 @@ void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, doub subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); - auto it = Cull.SubsectorDepths.find(sub); - if (it != Cull.SubsectorDepths.end()) - TranslucentObjects[thread->ThreadIndex].push_back(thread->FrameMemory->NewObject(thing, sub, it->second, sortDistance, (float)t1, (float)t2, StencilValue)); + if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff) + TranslucentObjects[thread->ThreadIndex].push_back(thread->FrameMemory->NewObject(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, (float)t1, (float)t2, StencilValue)); } void RenderPolyScene::RenderLine(PolyRenderThread *thread, subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth) diff --git a/src/r_videoscale.cpp b/src/r_videoscale.cpp index c666f08cc..f8ec6ab85 100644 --- a/src/r_videoscale.cpp +++ b/src/r_videoscale.cpp @@ -25,9 +25,38 @@ #include "c_dispatch.h" #include "c_cvars.h" -CUSTOM_CVAR (Int, vid_scalemode, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +#define NUMSCALEMODES 5 + +namespace { - if (self < 0 || self > 6) + struct v_ScaleTable + { + bool isValid; + bool isLinear; + uint32_t(*GetScaledWidth)(uint32_t Width); + uint32_t(*GetScaledHeight)(uint32_t Height); + bool isScaled43; + }; + v_ScaleTable vScaleTable[NUMSCALEMODES] = + { + // isValid, isLinear, GetScaledWidth(), GetScaledHeight(), isScaled43 + { true, false, [](uint32_t Width)->uint32_t { return Width; }, [](uint32_t Height)->uint32_t { return Height; }, false }, // 0 - Native + { true, true, [](uint32_t Width)->uint32_t { return Width; }, [](uint32_t Height)->uint32_t { return Height; }, false }, // 1 - Native (Linear) + { true, false, [](uint32_t Width)->uint32_t { return 320; }, [](uint32_t Height)->uint32_t { return 200; }, true }, // 2 - 320x200 + { true, false, [](uint32_t Width)->uint32_t { return 640; }, [](uint32_t Height)->uint32_t { return 400; }, true }, // 3 - 640x400 + { true, true, [](uint32_t Width)->uint32_t { return 1280; }, [](uint32_t Height)->uint32_t { return 800; }, true }, // 4 - 1280x800 + }; +} + +CUSTOM_CVAR(Float, vid_scalefactor, 1.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self <= 0.0 || self > 2.0) + self = 1.0; +} + +CUSTOM_CVAR(Int, vid_scalemode, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 0 || self >= NUMSCALEMODES || vScaleTable[self].isValid == false) { self = 0; } @@ -35,53 +64,23 @@ CUSTOM_CVAR (Int, vid_scalemode, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) bool ViewportLinearScale() { - switch(vid_scalemode) - { - default: return false; - case 4: - case 5: - case 6: return true; - } + // vid_scalefactor > 1 == forced linear scale + return (vid_scalefactor > 1.0) ? true : vScaleTable[vid_scalemode].isLinear; } int ViewportScaledWidth(int width) { - switch (vid_scalemode) - { - default: - case 0: return width; - case 1: return 320; - case 2: return 640; - case 3: return (int)roundf(width * 0.5f); - case 4: return (int)roundf(width * 0.75f); - case 5: return width * 2; - case 6: return 1280; - } + return vScaleTable[vid_scalemode].GetScaledWidth((int)((float)width * vid_scalefactor)); } int ViewportScaledHeight(int height) { - switch (vid_scalemode) - { - default: - case 0: return height; - case 1: return 200; - case 2: return 400; - case 3: return (int)roundf(height * 0.5f); - case 4: return (int)roundf(height * 0.75f); - case 5: return height * 2; - case 6: return 800; - } + return vScaleTable[vid_scalemode].GetScaledHeight((int)((float)height * vid_scalefactor)); } bool ViewportIsScaled43() { - switch (vid_scalemode) - { - default: return false; - case 1: - case 2: - case 6: return true; - } + return vScaleTable[vid_scalemode].isScaled43; } + diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 3c20a7bfd..8448665db 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2193,6 +2193,7 @@ VIDMNU_ASPECTRATIO = "Aspect ratio"; VIDMNU_FORCEASPECT = "Force aspect ratio"; VIDMNU_5X4ASPECTRATIO = "Enable 5:4 aspect ratio"; VIDMNU_SCALEMODE = "Resolution scale"; +VIDMNU_SCALEFACTOR = "Scale Factor"; VIDMNU_ENTERTEXT = "Press ENTER to set mode"; VIDMNU_TESTTEXT1 = "T to test mode for 5 seconds"; VIDMNU_TESTTEXT2 = "Please wait 5 seconds..."; @@ -2378,6 +2379,8 @@ OPTVAL_VTFZDOOM = "ZDoom (Forced)"; OPTVAL_VTFVANILLA = "Vanilla (Forced)"; OPTVAL_VTAZDOOM = "Auto (ZDoom Preferred)"; OPTVAL_VTAVANILLA = "Auto (Vanilla Preferred)"; +OPTVAL_SCALENEAREST = "Scaled (Nearest)"; +OPTVAL_SCALELINEAR = "Scaled (Linear)"; // Colors C_BRICK = "\cabrick"; @@ -2685,13 +2688,14 @@ GLTEXMNU_TRIMSPREDGE = "Trim sprite edges"; GLTEXMNU_SORTDRAWLIST = "Sort draw lists by texture"; // Dynamic Light Options -GLLIGHTMNU_TITLE = "DYNAMIC LIGHTS"; -GLLIGHTMNU_LIGHTSENABLED = "Dynamic Lights (OpenGL)"; -GLLIGHTMNU_LIGHTDEFS = "Enable light definitions"; -GLLIGHTMNU_CLIPLIGHTS = "Clip lights"; -GLLIGHTMNU_LIGHTSPRITES = "Lights affect sprites"; -GLLIGHTMNU_LIGHTPARTICLES = "Lights affect particles"; -GLLIGHTMNU_LIGHTSHADOWMAP = "Light shadowmaps"; +GLLIGHTMNU_TITLE = "DYNAMIC LIGHTS"; +GLLIGHTMNU_LIGHTSENABLED = "Dynamic Lights (OpenGL)"; +GLLIGHTMNU_LIGHTDEFS = "Enable light definitions"; +GLLIGHTMNU_CLIPLIGHTS = "Clip lights"; +GLLIGHTMNU_LIGHTSPRITES = "Lights affect sprites"; +GLLIGHTMNU_LIGHTPARTICLES = "Lights affect particles"; +GLLIGHTMNU_LIGHTSHADOWMAP = "Light shadowmaps"; +GLLIGHTMNU_LIGHTSHADOWMAPQUALITY = "Shadowmap quality"; // OpenGL Preferences GLPREFMNU_TITLE = "OPENGL PREFERENCES"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index b95d53852..729a914eb 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1858,13 +1858,11 @@ OptionValue RatiosTFT } OptionValue ScaleModes { - 0, "$OPTVAL_OFF" - 1, "320x200" - 2, "640x400" - 3, "0.5x" - 4, "0.75x" - 5, "2x SSAA" - 6, "1280x800" + 0, "$OPTVAL_SCALENEAREST" + 1, "$OPTVAL_SCALELINEAR" + 2, "320x200" + 3, "640x400" + 4, "1280x800" } OptionMenu VideoModeMenu protected @@ -1880,6 +1878,7 @@ OptionMenu VideoModeMenu protected Option "$VIDMNU_FORCEASPECT", "vid_aspect", "ForceRatios" Option "$VIDMNU_5X4ASPECTRATIO", "vid_tft", "YesNo" Option "$VIDMNU_SCALEMODE", "vid_scalemode", "ScaleModes" + Slider "$VIDMNU_SCALEFACTOR", "vid_scalefactor", 0.25, 2.0, 0.25, 2 StaticText " " ScreenResolution "res_0" ScreenResolution "res_1" @@ -2128,6 +2127,14 @@ OptionValue VRMode 7, "$OPTVAL_QUADBUFFERED" } +OptionValue ShadowMapQuality +{ + 128, "128" + 256, "256" + 512, "512" + 1024, "1024" +} + OptionMenu "GLTextureGLOptions" protected { Title "$GLTEXMNU_TITLE" @@ -2148,13 +2155,14 @@ OptionMenu "GLTextureGLOptions" protected OptionMenu "GLLightOptions" protected { Title "$GLLIGHTMNU_TITLE" - Option "$TCMNU_DYNLIGHTS", "r_dynlights", "OnOff" - Option "$GLLIGHTMNU_LIGHTSENABLED", gl_lights, "OnOff" - Option "$GLLIGHTMNU_LIGHTDEFS", gl_attachedlights, "YesNo" - Option "$GLLIGHTMNU_CLIPLIGHTS", gl_lights_checkside, "YesNo" - Option "$GLLIGHTMNU_LIGHTSPRITES", gl_light_sprites, "YesNo" - Option "$GLLIGHTMNU_LIGHTPARTICLES", gl_light_particles, "YesNo" - Option "$GLLIGHTMNU_LIGHTSHADOWMAP", gl_light_shadowmap, "YesNo" + Option "$TCMNU_DYNLIGHTS", "r_dynlights", "OnOff" + Option "$GLLIGHTMNU_LIGHTSENABLED", gl_lights, "OnOff" + Option "$GLLIGHTMNU_LIGHTDEFS", gl_attachedlights, "YesNo" + Option "$GLLIGHTMNU_CLIPLIGHTS", gl_lights_checkside, "YesNo" + Option "$GLLIGHTMNU_LIGHTSPRITES", gl_light_sprites, "YesNo" + Option "$GLLIGHTMNU_LIGHTPARTICLES", gl_light_particles, "YesNo" + Option "$GLLIGHTMNU_LIGHTSHADOWMAP", gl_light_shadowmap, "YesNo" + Option "$GLLIGHTMNU_LIGHTSHADOWMAPQUALITY", gl_shadowmap_quality, "ShadowMapQuality" } OptionMenu "OpenGLOptions" protected