diff --git a/src/polyrenderer/poly_renderer.cpp b/src/polyrenderer/poly_renderer.cpp index 53f051b1f9..184cb9697f 100644 --- a/src/polyrenderer/poly_renderer.cpp +++ b/src/polyrenderer/poly_renderer.cpp @@ -32,6 +32,7 @@ #include "po_man.h" #include "st_stuff.h" #include "g_levellocals.h" +#include "p_effect.h" #include "polyrenderer/scene/poly_light.h" #include "swrenderer/scene/r_scene.h" #include "swrenderer/drawers/r_draw_rgba.h" diff --git a/src/polyrenderer/scene/poly_particle.h b/src/polyrenderer/scene/poly_particle.h index 6327f9e784..f94cdc781c 100644 --- a/src/polyrenderer/scene/poly_particle.h +++ b/src/polyrenderer/scene/poly_particle.h @@ -39,3 +39,19 @@ private: ParticleTextureSize = 64 }; }; + +class PolyTranslucentParticle : public PolyTranslucentObject +{ +public: + PolyTranslucentParticle(particle_t *particle, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue) : PolyTranslucentObject(subsectorDepth, 0.0), particle(particle), sub(sub), StencilValue(stencilValue) { } + + void Render(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override + { + RenderPolyParticle spr; + spr.Render(worldToClip, portalPlane, particle, sub, StencilValue + 1); + } + + particle_t *particle = nullptr; + subsector_t *sub = nullptr; + uint32_t StencilValue = 0; +}; diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index 9e390f67f8..2754e701ae 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -430,7 +430,7 @@ void Render3DFloorPlane::RenderPlanes(const TriMatrix &worldToClip, const PolyCl if (!plane.Masked) plane.Render(worldToClip, clipPlane); else - translucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(plane, subsectorDepth)); + translucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(plane, subsectorDepth)); } } @@ -470,7 +470,7 @@ void Render3DFloorPlane::RenderPlanes(const TriMatrix &worldToClip, const PolyCl if (!plane.Masked) plane.Render(worldToClip, clipPlane); else - translucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(plane, subsectorDepth)); + translucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(plane, subsectorDepth)); } } } diff --git a/src/polyrenderer/scene/poly_plane.h b/src/polyrenderer/scene/poly_plane.h index 6b9f515678..0deca401cc 100644 --- a/src/polyrenderer/scene/poly_plane.h +++ b/src/polyrenderer/scene/poly_plane.h @@ -69,3 +69,16 @@ public: bool Additive = false; double Alpha = 1.0; }; + +class PolyTranslucent3DFloorPlane : public PolyTranslucentObject +{ +public: + PolyTranslucent3DFloorPlane(Render3DFloorPlane plane, uint32_t subsectorDepth) : PolyTranslucentObject(subsectorDepth, 1e7), plane(plane) { } + + void Render(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override + { + plane.Render(worldToClip, portalPlane); + } + + Render3DFloorPlane plane; +}; diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index 7c79d865f6..1e47d515a1 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -26,9 +26,14 @@ #include "p_maputl.h" #include "sbar.h" #include "r_data/r_translate.h" -#include "polyrenderer/scene/poly_scene.h" #include "polyrenderer/poly_renderer.h" +#include "polyrenderer/scene/poly_scene.h" #include "polyrenderer/scene/poly_light.h" +#include "polyrenderer/scene/poly_wall.h" +#include "polyrenderer/scene/poly_wallsprite.h" +#include "polyrenderer/scene/poly_plane.h" +#include "polyrenderer/scene/poly_particle.h" +#include "polyrenderer/scene/poly_sprite.h" EXTERN_CVAR(Int, r_portal_recursions) @@ -151,7 +156,7 @@ void RenderPolyScene::RenderSubsector(subsector_t *sub, uint32_t subsectorDepth) for (int i = ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Particles[i].snext) { particle_t *particle = Particles + i; - TranslucentObjects.push_back(memory.NewObject(particle, sub, subsectorDepth)); + TranslucentObjects.push_back(memory.NewObject(particle, sub, subsectorDepth, StencilValue)); } } @@ -233,7 +238,7 @@ void RenderPolyScene::RenderSprite(AActor *thing, double sortDistance, const DVe subsector_t *sub = &level.subsectors[0]; auto it = SubsectorDepths.find(sub); if (it != SubsectorDepths.end()) - TranslucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(thing, sub, it->second, sortDistance, 0.0f, 1.0f)); + TranslucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(thing, sub, it->second, sortDistance, 0.0f, 1.0f, StencilValue)); } else { @@ -274,7 +279,7 @@ void RenderPolyScene::RenderSprite(AActor *thing, double sortDistance, DVector2 auto it = SubsectorDepths.find(sub); if (it != SubsectorDepths.end()) - TranslucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(thing, sub, it->second, sortDistance, (float)t1, (float)t2)); + TranslucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(thing, sub, it->second, sortDistance, (float)t1, (float)t2, StencilValue)); } void RenderPolyScene::RenderLine(subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth) @@ -419,29 +424,9 @@ void RenderPolyScene::RenderTranslucent(int portalDepth) for (auto it = TranslucentObjects.rbegin(); it != TranslucentObjects.rend(); ++it) { PolyTranslucentObject *obj = *it; - // To do: convert PolyTranslucentObject to an interface with subclasses! - if (obj->type == PolyTranslucentObjectType::Particle) - { - RenderPolyParticle spr; - spr.Render(WorldToClip, PortalPlane, obj->particle, obj->sub, StencilValue + 1); - } - else if (obj->type == PolyTranslucentObjectType::Wall) - { - obj->wall.Render(WorldToClip, PortalPlane); - } - else if (obj->type == PolyTranslucentObjectType::Plane) - { - obj->plane.Render(WorldToClip, PortalPlane); - } - else if (obj->type == PolyTranslucentObjectType::Thing && (obj->thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) - { - RenderPolyWallSprite wallspr; - wallspr.Render(WorldToClip, PortalPlane, obj->thing, obj->sub, StencilValue + 1); - } - else if (obj->type == PolyTranslucentObjectType::Thing) - { - RenderPolySprite spr; - spr.Render(WorldToClip, PortalPlane, obj->thing, obj->sub, StencilValue + 1, obj->SpriteLeft, obj->SpriteRight); - } + obj->Render(WorldToClip, PortalPlane); + obj->~PolyTranslucentObject(); } + + TranslucentObjects.clear(); } diff --git a/src/polyrenderer/scene/poly_scene.h b/src/polyrenderer/scene/poly_scene.h index 5e768fbdb4..2c41d15b76 100644 --- a/src/polyrenderer/scene/poly_scene.h +++ b/src/polyrenderer/scene/poly_scene.h @@ -29,49 +29,26 @@ #include "doomdata.h" #include "r_utility.h" #include "polyrenderer/drawers/poly_triangle.h" -#include "poly_wall.h" -#include "poly_sprite.h" -#include "poly_wallsprite.h" #include "poly_playersprite.h" -#include "poly_particle.h" -#include "poly_plane.h" #include "poly_cull.h" #include #include -enum class PolyTranslucentObjectType -{ - Particle, - Thing, - Wall, - Plane -}; - class PolyTranslucentObject { public: - PolyTranslucentObject(particle_t *particle, subsector_t *sub, uint32_t subsectorDepth) : type(PolyTranslucentObjectType::Particle), particle(particle), sub(sub), subsectorDepth(subsectorDepth) { } - PolyTranslucentObject(AActor *thing, subsector_t *sub, uint32_t subsectorDepth, double dist, float t1, float t2) : type(PolyTranslucentObjectType::Thing), thing(thing), sub(sub), subsectorDepth(subsectorDepth), DistanceSquared(dist), SpriteLeft(t1), SpriteRight(t2) { } - PolyTranslucentObject(RenderPolyWall wall) : type(PolyTranslucentObjectType::Wall), wall(wall), subsectorDepth(wall.SubsectorDepth), DistanceSquared(1.e6) { } - PolyTranslucentObject(Render3DFloorPlane plane, uint32_t subsectorDepth) : type(PolyTranslucentObjectType::Plane), plane(plane), subsectorDepth(subsectorDepth), DistanceSquared(1.e7) { } + PolyTranslucentObject(uint32_t subsectorDepth = 0, double distanceSquared = 0.0) : subsectorDepth(subsectorDepth), DistanceSquared(distanceSquared) { } + virtual ~PolyTranslucentObject() { } + + virtual void Render(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) = 0; bool operator<(const PolyTranslucentObject &other) const { return subsectorDepth != other.subsectorDepth ? subsectorDepth < other.subsectorDepth : DistanceSquared < other.DistanceSquared; } - PolyTranslucentObjectType type; - particle_t *particle = nullptr; - AActor *thing = nullptr; - subsector_t *sub = nullptr; - - RenderPolyWall wall; - Render3DFloorPlane plane; - - uint32_t subsectorDepth = 0; - double DistanceSquared = 0.0; - - float SpriteLeft = 0.0f, SpriteRight = 1.0f; + uint32_t subsectorDepth; + double DistanceSquared; }; class PolyDrawSectorPortal; diff --git a/src/polyrenderer/scene/poly_sprite.h b/src/polyrenderer/scene/poly_sprite.h index 12fe63f680..abc5e20a4e 100644 --- a/src/polyrenderer/scene/poly_sprite.h +++ b/src/polyrenderer/scene/poly_sprite.h @@ -38,3 +38,29 @@ private: static double GetSpriteFloorZ(AActor *thing, const DVector2 &thingpos); static double GetSpriteCeilingZ(AActor *thing, const DVector2 &thingpos); }; + +class PolyTranslucentThing : public PolyTranslucentObject +{ +public: + PolyTranslucentThing(AActor *thing, subsector_t *sub, uint32_t subsectorDepth, double dist, float t1, float t2, uint32_t stencilValue) : PolyTranslucentObject(subsectorDepth, dist), thing(thing), sub(sub), SpriteLeft(t1), SpriteRight(t2), StencilValue(stencilValue) { } + + void Render(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override + { + if ((thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) + { + RenderPolyWallSprite wallspr; + wallspr.Render(worldToClip, portalPlane, thing, sub, StencilValue + 1); + } + else + { + RenderPolySprite spr; + spr.Render(worldToClip, portalPlane, thing, sub, StencilValue + 1, SpriteLeft, SpriteRight); + } + } + + AActor *thing = nullptr; + subsector_t *sub = nullptr; + float SpriteLeft = 0.0f; + float SpriteRight = 1.0f; + uint32_t StencilValue = 0; +}; diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index 847c9eb7c0..deaf850fd7 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -170,7 +170,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlan FTexture *midtex = TexMan(line->sidedef->GetTexture(side_t::mid), true); if ((midtex && midtex->UseType != FTexture::TEX_Null) || wall.FogBoundary) - translucentWallsOutput.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(wall)); + translucentWallsOutput.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(wall)); if (polyportal) { @@ -237,7 +237,7 @@ void RenderPolyWall::Render3DFloorLine(const TriMatrix &worldToClip, const PolyC if (!wall.Masked) wall.Render(worldToClip, clipPlane); else - translucentWallsOutput.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(wall)); + translucentWallsOutput.push_back(PolyRenderer::Instance()->FrameMemory.NewObject(wall)); } void RenderPolyWall::SetCoords(const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2) diff --git a/src/polyrenderer/scene/poly_wall.h b/src/polyrenderer/scene/poly_wall.h index 7107316a66..34b46cb6c3 100644 --- a/src/polyrenderer/scene/poly_wall.h +++ b/src/polyrenderer/scene/poly_wall.h @@ -92,3 +92,16 @@ private: void CalcVMidPart(FTexture *tex, const line_t *line, const side_t *side, double topz, double bottomz, double yoffset); void CalcVBottomPart(FTexture *tex, const line_t *line, const side_t *side, double topz, double bottomz, double unpeggedceil, double yoffset); }; + +class PolyTranslucentWall : public PolyTranslucentObject +{ +public: + PolyTranslucentWall(RenderPolyWall wall) : PolyTranslucentObject(wall.SubsectorDepth, 1e6), wall(wall) { } + + void Render(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override + { + wall.Render(worldToClip, portalPlane); + } + + RenderPolyWall wall; +};