diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 384306ed8e..978b327598 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -713,7 +713,6 @@ file( GLOB HEADER_FILES rendering/polyrenderer/*.h rendering/polyrenderer/math/*.h rendering/polyrenderer/drawers/*.h - rendering/polyrenderer/scene/*.h rendering/polyrenderer/backend/*.h rendering/hwrenderer/data/*.h rendering/hwrenderer/dynlights/*.h @@ -786,21 +785,6 @@ set ( SWRENDER_SOURCES ) set( POLYRENDER_SOURCES - rendering/polyrenderer/poly_renderer.cpp - rendering/polyrenderer/poly_renderthread.cpp - rendering/polyrenderer/scene/poly_scene.cpp - rendering/polyrenderer/scene/poly_portal.cpp - rendering/polyrenderer/scene/poly_cull.cpp - rendering/polyrenderer/scene/poly_decal.cpp - rendering/polyrenderer/scene/poly_particle.cpp - rendering/polyrenderer/scene/poly_plane.cpp - rendering/polyrenderer/scene/poly_playersprite.cpp - rendering/polyrenderer/scene/poly_wall.cpp - rendering/polyrenderer/scene/poly_wallsprite.cpp - rendering/polyrenderer/scene/poly_sprite.cpp - rendering/polyrenderer/scene/poly_model.cpp - rendering/polyrenderer/scene/poly_sky.cpp - rendering/polyrenderer/scene/poly_light.cpp rendering/polyrenderer/drawers/poly_buffer.cpp rendering/polyrenderer/drawers/poly_triangle.cpp rendering/polyrenderer/drawers/poly_draw_args.cpp @@ -1564,7 +1548,6 @@ source_group("Rendering\\Software Renderer\\Viewport" REGULAR_EXPRESSION "^${CMA source_group("Rendering\\Poly Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rendering/polyrenderer/.+") source_group("Rendering\\Poly Renderer\\Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rendering/polyrenderer/math/.+") source_group("Rendering\\Poly Renderer\\Drawers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rendering/polyrenderer/drawers/.+") -source_group("Rendering\\Poly Renderer\\Scene" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rendering/polyrenderer/scene/.+") source_group("Rendering\\Poly Renderer\\Backend" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rendering/polyrenderer/backend/.+") source_group("Render Data" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/.+") source_group("Render Data\\Models" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/models/.+") diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.cpp b/src/rendering/polyrenderer/drawers/poly_draw_args.cpp index fe5dd1e8d9..50e8a82ae0 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.cpp @@ -36,7 +36,7 @@ #include "swrenderer/r_swcolormaps.h" #include "poly_draw_args.h" #include "swrenderer/viewport/r_viewport.h" -#include "polyrenderer/poly_renderthread.h" +#include "polyrenderer/drawers/poly_triangle.h" void PolyDrawArgs::SetTexture(const uint8_t *texels, int width, int height) { @@ -97,13 +97,6 @@ void PolyDrawArgs::SetLight(FSWColormap *base_colormap, uint32_t lightlevel, dou { mGlobVis = (float)globVis; - PolyCameraLight *cameraLight = PolyCameraLight::Instance(); - if (cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) - { - lightlevel = cameraLight->FixedLightLevel() >= 0 ? cameraLight->FixedLightLevel() : 255; - fixed = true; - } - mLight = clamp(lightlevel, 0, 255); mFixedLight = fixed; mLightRed = base_colormap->Color.r; @@ -203,6 +196,7 @@ void PolyDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint3 ///////////////////////////////////////////////////////////////////////////// +#if 0 void RectDrawArgs::SetTexture(FSoftwareTexture *texture, FRenderStyle style) { mTexture = texture; @@ -351,3 +345,4 @@ void RectDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint3 SetStyle(Translation() ? TriBlendMode::AddShadedTranslated : TriBlendMode::AddShaded, alpha); } } +#endif diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.h b/src/rendering/polyrenderer/drawers/poly_draw_args.h index 0c6a6791a0..83df644215 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.h +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.h @@ -167,6 +167,7 @@ private: uint32_t mDynLightColor = 0; }; +#if 0 class RectDrawArgs { public: @@ -233,3 +234,4 @@ private: bool mSimpleShade = true; float mX0, mX1, mY0, mY1, mU0, mU1, mV0, mV1; }; +#endif diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 9fd779cdcd..53676532a3 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -35,7 +35,6 @@ #include "v_palette.h" #include "r_data/colormaps.h" #include "poly_triangle.h" -#include "polyrenderer/poly_renderer.h" #include "swrenderer/drawers/r_draw_rgba.h" #include "screen_triangle.h" #include "x86.h" @@ -724,6 +723,7 @@ void DrawPolyTrianglesCommand::Execute(DrawerThread *thread) ///////////////////////////////////////////////////////////////////////////// +#if 0 void DrawRectCommand::Execute(DrawerThread *thread) { auto renderTarget = PolyRenderer::Instance()->RenderTarget; @@ -737,3 +737,4 @@ void DrawRectCommand::Execute(DrawerThread *thread) else ScreenTriangle::RectDrawers8[blendmode](destOrg, destWidth, destHeight, destPitch, &args, PolyTriangleThreadData::Get(thread)); } +#endif diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 50c0f6ad49..99a54585ee 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -240,6 +240,7 @@ private: PolyDrawMode mode; }; +#if 0 class DrawRectCommand : public PolyDrawerCommand { public: @@ -250,3 +251,4 @@ public: private: RectDrawArgs args; }; +#endif diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index dc6a66c3c9..45656e35e0 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -1588,6 +1588,7 @@ void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTrian } } +#if 0 template void DrawRect8(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread) { @@ -2115,6 +2116,7 @@ void DrawRect32(const void *destOrg, int destWidth, int destHeight, int destPitc else DrawRectOpt32(destOrg, destWidth, destHeight, destPitch, args, thread); } +#endif void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *, PolyTriangleThreadData *) = { @@ -2180,6 +2182,7 @@ void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs &DrawSpan32 }; +#if 0 void(*ScreenTriangle::RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *) = { &DrawRect8, @@ -2243,6 +2246,7 @@ void(*ScreenTriangle::RectDrawers32[])(const void *, int, int, int, const RectDr &DrawRect32, &DrawRect32 }; +#endif void(*ScreenTriangle::TriangleDrawers[])(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread, int16_t *edges, int topY, int bottomY) = { diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.h b/src/rendering/polyrenderer/drawers/screen_triangle.h index 66ae24f653..cee3975a37 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.h +++ b/src/rendering/polyrenderer/drawers/screen_triangle.h @@ -25,6 +25,7 @@ #include #include #include "r_data/renderstyle.h" +#include "rendering/swrenderer/drawers/r_draw.h" class FString; class PolyDrawArgs; @@ -138,8 +139,10 @@ public: static void(*SpanDrawers8[])(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); static void(*SpanDrawers32[])(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); +#if 0 static void(*RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *); static void(*RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *); +#endif static int FuzzStart; }; diff --git a/src/rendering/polyrenderer/poly_all.cpp b/src/rendering/polyrenderer/poly_all.cpp index 29b3c7fe1e..0d7295d7f4 100644 --- a/src/rendering/polyrenderer/poly_all.cpp +++ b/src/rendering/polyrenderer/poly_all.cpp @@ -1,21 +1,6 @@ #include "../swrenderer/textures/r_swtexture.h" -#include "poly_renderer.cpp" -#include "poly_renderthread.cpp" #include "drawers/poly_buffer.cpp" #include "drawers/poly_draw_args.cpp" #include "drawers/poly_triangle.cpp" #include "drawers/screen_triangle.cpp" #include "math/gpu_types.cpp" -#include "scene/poly_cull.cpp" -#include "scene/poly_decal.cpp" -#include "scene/poly_particle.cpp" -#include "scene/poly_plane.cpp" -#include "scene/poly_playersprite.cpp" -#include "scene/poly_portal.cpp" -#include "scene/poly_scene.cpp" -#include "scene/poly_sky.cpp" -#include "scene/poly_sprite.cpp" -#include "scene/poly_model.cpp" -#include "scene/poly_wall.cpp" -#include "scene/poly_wallsprite.cpp" -#include "scene/poly_light.cpp" diff --git a/src/rendering/polyrenderer/poly_renderer.cpp b/src/rendering/polyrenderer/poly_renderer.cpp deleted file mode 100644 index 9c36424883..0000000000 --- a/src/rendering/polyrenderer/poly_renderer.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "sbar.h" -#include "st_stuff.h" -#include "r_data/r_translate.h" -#include "r_data/r_interpolate.h" -#include "r_data/models/models.h" -#include "poly_renderer.h" -#include "d_net.h" -#include "po_man.h" -#include "st_stuff.h" -#include "g_levellocals.h" -#include "p_effect.h" -#include "actorinlines.h" -#include "polyrenderer/scene/poly_light.h" -#include "swrenderer/scene/r_scene.h" -#include "swrenderer/drawers/r_draw_rgba.h" -#include "swrenderer/viewport/r_viewport.h" -#include "swrenderer/r_swcolormaps.h" - -EXTERN_CVAR(Int, screenblocks) -EXTERN_CVAR(Float, r_visibility) -EXTERN_CVAR(Bool, r_models) - -extern bool r_modelscene; - -///////////////////////////////////////////////////////////////////////////// - -PolyRenderer *PolyRenderer::Instance() -{ - static PolyRenderer scene; - return &scene; -} - -PolyRenderer::PolyRenderer() -{ -} - -void PolyRenderer::RenderView(player_t *player, DCanvas *target, void *videobuffer, int bufferpitch) -{ - using namespace swrenderer; - - R_ExecuteSetViewSize(Viewpoint, Viewwindow); - - RenderTarget = target; - RenderToCanvas = false; - - RenderActorView(player->mo, true, false); - - Threads.MainThread()->FlushDrawQueue(); - - auto copyqueue = std::make_shared(Threads.MainThread()->FrameMemory.get()); - copyqueue->Push(videobuffer, bufferpitch, target->GetPixels(), target->GetWidth(), target->GetHeight(), target->GetPitch(), target->IsBgra() ? 4 : 1); - DrawerThreads::Execute(copyqueue); - - PolyDrawerWaitCycles.Clock(); - DrawerThreads::WaitForWorkers(); - PolyDrawerWaitCycles.Unclock(); -} - -void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines) -{ - // Save a bunch of silly globals: - auto savedViewpoint = Viewpoint; - auto savedViewwindow = Viewwindow; - auto savedviewwindowx = viewwindowx; - auto savedviewwindowy = viewwindowy; - auto savedviewwidth = viewwidth; - auto savedviewheight = viewheight; - auto savedviewactive = viewactive; - auto savedRenderTarget = RenderTarget; - - // Setup the view: - RenderTarget = canvas; - RenderToCanvas = true; - R_SetWindow(Viewpoint, Viewwindow, 12, width, height, height, true); - viewwindowx = x; - viewwindowy = y; - viewactive = true; - - // Render: - RenderActorView(actor, false, dontmaplines); - Threads.MainThread()->FlushDrawQueue(); - DrawerThreads::WaitForWorkers(); - - RenderToCanvas = false; - - // Restore silly globals: - Viewpoint = savedViewpoint; - Viewwindow = savedViewwindow; - viewwindowx = savedviewwindowx; - viewwindowy = savedviewwindowy; - viewwidth = savedviewwidth; - viewheight = savedviewheight; - viewactive = savedviewactive; - RenderTarget = savedRenderTarget; -} - -void PolyRenderer::RenderActorView(AActor *actor, bool drawpsprites, bool dontmaplines) -{ - PolyTotalBatches = 0; - PolyTotalTriangles = 0; - PolyTotalDrawCalls = 0; - PolyCullCycles.Reset(); - PolyOpaqueCycles.Reset(); - PolyMaskedCycles.Reset(); - PolyDrawerWaitCycles.Reset(); - - DontMapLines = dontmaplines; - - R_SetupFrame(Viewpoint, Viewwindow, actor); - Level = Viewpoint.ViewLevel; - - static bool firstcall = true; - if (firstcall) - { - swrenderer::R_InitFuzzTable(RenderTarget->GetPitch()); - firstcall = false; - } - - swrenderer::R_UpdateFuzzPosFrameStart(); - - if (APART(R_OldBlend)) NormalLight.Maps = realcolormaps.Maps; - else NormalLight.Maps = realcolormaps.Maps + NUMCOLORMAPS * 256 * R_OldBlend; - - Light.SetVisibility(Viewwindow, r_visibility); - - PolyCameraLight::Instance()->SetCamera(Viewpoint, RenderTarget, actor); - //Viewport->SetupFreelook(); - - ActorRenderFlags savedflags = 0; - if (Viewpoint.camera) - { - savedflags = Viewpoint.camera->renderflags; - - // Never draw the player unless in chasecam mode - if (!Viewpoint.showviewer) - Viewpoint.camera->renderflags |= RF_INVISIBLE; - } - - ScreenTriangle::FuzzStart = (ScreenTriangle::FuzzStart + 14) % FUZZTABLE; - - r_modelscene = r_models && Models.Size() > 0; - - NextStencilValue = 0; - Threads.Clear(); - Threads.MainThread()->SectorPortals.clear(); - Threads.MainThread()->LinePortals.clear(); - Threads.MainThread()->TranslucentObjects.clear(); - - PolyTriangleDrawer::ResizeBuffers(RenderTarget); - PolyTriangleDrawer::ClearStencil(Threads.MainThread()->DrawQueue, 0); - SetSceneViewport(); - - PolyPortalViewpoint mainViewpoint = SetupPerspectiveMatrix(); - mainViewpoint.StencilValue = GetNextStencilValue(); - Scene.CurrentViewpoint = &mainViewpoint; - Scene.Render(&mainViewpoint); - if (drawpsprites) - PlayerSprites.Render(Threads.MainThread()); - - Scene.CurrentViewpoint = nullptr; - - if (Viewpoint.camera) - Viewpoint.camera->renderflags = savedflags; -} - -void PolyRenderer::RenderRemainingPlayerSprites() -{ - PlayerSprites.RenderRemainingSprites(); -} - -void PolyRenderer::SetSceneViewport() -{ - using namespace swrenderer; - - if (!RenderToCanvas) // Rendering to screen - { - int height; - if (screenblocks >= 10) - height = SCREENHEIGHT; - else - height = (screenblocks*SCREENHEIGHT / 10) & ~7; - - int bottom = SCREENHEIGHT - (height + viewwindowy - ((height - viewheight) / 2)); - PolyTriangleDrawer::SetViewport(Threads.MainThread()->DrawQueue, viewwindowx, SCREENHEIGHT - bottom - height, viewwidth, height, RenderTarget); - } - else // Rendering to camera texture - { - PolyTriangleDrawer::SetViewport(Threads.MainThread()->DrawQueue, 0, 0, RenderTarget->GetWidth(), RenderTarget->GetHeight(), RenderTarget); - } -} - -PolyPortalViewpoint PolyRenderer::SetupPerspectiveMatrix(bool mirror) -{ - // We have to scale the pitch to account for the pixel stretching, because the playsim doesn't know about this and treats it as 1:1. - double radPitch = Viewpoint.Angles.Pitch.Normalized180().Radians(); - double angx = cos(radPitch); - double angy = sin(radPitch) * PolyRenderer::Instance()->Level->info->pixelstretch; - double alen = sqrt(angx*angx + angy*angy); - float adjustedPitch = (float)asin(angy / alen); - float adjustedViewAngle = (float)(Viewpoint.Angles.Yaw - 90).Radians(); - - float ratio = Viewwindow.WidescreenRatio; - float fovratio = (Viewwindow.WidescreenRatio >= 1.3f) ? 1.333333f : ratio; - - float fovy = (float)(2 * DAngle::ToDegrees(atan(tan(Viewpoint.FieldOfView.Radians() / 2) / fovratio)).Degrees); - - PolyPortalViewpoint portalViewpoint; - - portalViewpoint.WorldToView = - Mat4f::Rotate((float)Viewpoint.Angles.Roll.Radians(), 0.0f, 0.0f, 1.0f) * - Mat4f::Rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) * - Mat4f::Rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) * - Mat4f::Scale(1.0f, PolyRenderer::Instance()->Level->info->pixelstretch, 1.0f) * - Mat4f::SwapYZ() * - Mat4f::Translate((float)-Viewpoint.Pos.X, (float)-Viewpoint.Pos.Y, (float)-Viewpoint.Pos.Z); - - portalViewpoint.Mirror = mirror; - - if (mirror) - portalViewpoint.WorldToView = Mat4f::Scale(-1.0f, 1.0f, 1.0f) * portalViewpoint.WorldToView; - - portalViewpoint.WorldToClip = Mat4f::Perspective(fovy, ratio, 5.0f, 65535.0f, Handedness::Right, ClipZRange::NegativePositiveW) * portalViewpoint.WorldToView; - - return portalViewpoint; -} - -cycle_t PolyCullCycles, PolyOpaqueCycles, PolyMaskedCycles, PolyDrawerWaitCycles; -int PolyTotalBatches, PolyTotalTriangles, PolyTotalDrawCalls; - -ADD_STAT(polyfps) -{ - FString out; - out.Format("frame=%04.1f ms cull=%04.1f ms opaque=%04.1f ms masked=%04.1f ms drawers=%04.1f ms", - FrameCycles.TimeMS(), PolyCullCycles.TimeMS(), PolyOpaqueCycles.TimeMS(), PolyMaskedCycles.TimeMS(), PolyDrawerWaitCycles.TimeMS()); - out.AppendFormat("\nbatches drawn: %d triangles drawn: %d drawcalls: %d", PolyTotalBatches, PolyTotalTriangles, PolyTotalDrawCalls); - return out; -} diff --git a/src/rendering/polyrenderer/poly_renderer.h b/src/rendering/polyrenderer/poly_renderer.h deleted file mode 100644 index b40f5d44db..0000000000 --- a/src/rendering/polyrenderer/poly_renderer.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include -#include -#include -#include -#include "doomdata.h" -#include "r_utility.h" -#include "scene/poly_portal.h" -#include "scene/poly_playersprite.h" -#include "scene/poly_light.h" -#include "swrenderer/r_memory.h" -#include "poly_renderthread.h" -#include "stats.h" - -class AActor; -class DCanvas; -class PolyPortalViewpoint; -class DrawerCommandQueue; -typedef std::shared_ptr DrawerCommandQueuePtr; - -extern cycle_t PolyCullCycles, PolyOpaqueCycles, PolyMaskedCycles, PolyDrawerWaitCycles; -extern int PolyTotalBatches, PolyTotalTriangles, PolyTotalDrawCalls; - -class PolyRenderer -{ -public: - PolyRenderer(); - - void RenderView(player_t *player, DCanvas *target, void *videobuffer, int bufferpitch); - void RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines); - void RenderRemainingPlayerSprites(); - - static PolyRenderer *Instance(); - - PolyPortalViewpoint SetupPerspectiveMatrix(bool mirror = false); - - uint32_t GetNextStencilValue() { uint32_t value = NextStencilValue; NextStencilValue += 2; return value; } - - bool DontMapLines = false; - - PolyRenderThreads Threads; - DCanvas *RenderTarget = nullptr; - bool RenderToCanvas = false; - FViewWindow Viewwindow; - FRenderViewpoint Viewpoint; - PolyLightVisibility Light; - RenderPolyScene Scene; - FLevelLocals *Level; - -private: - void RenderActorView(AActor *actor, bool drawpsprites, bool dontmaplines); - void SetSceneViewport(); - - RenderPolyPlayerSprites PlayerSprites; - uint32_t NextStencilValue = 0; -}; diff --git a/src/rendering/polyrenderer/poly_renderthread.cpp b/src/rendering/polyrenderer/poly_renderthread.cpp deleted file mode 100644 index 7e5c834ca1..0000000000 --- a/src/rendering/polyrenderer/poly_renderthread.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "m_bbox.h" - -#include "p_lnspec.h" -#include "p_setup.h" -#include "a_sharedglobal.h" -#include "g_level.h" -#include "p_effect.h" -#include "doomstat.h" -#include "r_state.h" -#include "v_palette.h" -#include "r_sky.h" -#include "po_man.h" -#include "r_data/colormaps.h" -#include "poly_renderthread.h" -#include "poly_renderer.h" -#include - -#ifdef WIN32 -void PeekThreadedErrorPane(); -#endif - -EXTERN_CVAR(Int, r_scene_multithreaded); - -PolyRenderThread::PolyRenderThread(int threadIndex) : MainThread(threadIndex == 0), ThreadIndex(threadIndex) -{ - FrameMemory.reset(new RenderMemory()); - DrawQueue = std::make_shared(FrameMemory.get()); -} - -PolyRenderThread::~PolyRenderThread() -{ -} - -void PolyRenderThread::FlushDrawQueue() -{ - DrawerThreads::Execute(DrawQueue); - - UsedDrawQueues.push_back(DrawQueue); - DrawQueue.reset(); - - if (!FreeDrawQueues.empty()) - { - DrawQueue = FreeDrawQueues.back(); - FreeDrawQueues.pop_back(); - } - else - { - DrawQueue = std::make_shared(FrameMemory.get()); - } -} - -static std::mutex loadmutex; -void PolyRenderThread::PrepareTexture(FSoftwareTexture *texture, FRenderStyle style) -{ - if (texture == nullptr) - return; - - // Textures may not have loaded/refreshed yet. The shared code doing - // this is not thread safe. By calling GetPixels in a mutex lock we - // make sure that only one thread is loading a texture at any given - // time. - // - // It is critical that this function is called before any direct - // calls to GetPixels for this to work. - - std::unique_lock lock(loadmutex); - - const FSoftwareTextureSpan *spans; - if (PolyRenderer::Instance()->RenderTarget->IsBgra()) - { - texture->GetPixelsBgra(); - texture->GetColumnBgra(0, &spans); - } - else - { - bool alpha = !!(style.Flags & STYLEF_RedIsAlpha); - texture->GetPixels(alpha); - texture->GetColumn(alpha, 0, &spans); - } -} - -static std::mutex polyobjmutex; -void PolyRenderThread::PreparePolyObject(subsector_t *sub) -{ - std::unique_lock lock(polyobjmutex); - - if (sub->BSP == nullptr || sub->BSP->bDirty) - { - sub->BuildPolyBSP(); - } -} - -///////////////////////////////////////////////////////////////////////////// - -PolyRenderThreads::PolyRenderThreads() -{ - std::unique_ptr thread(new PolyRenderThread(0)); - Threads.push_back(std::move(thread)); -} - -PolyRenderThreads::~PolyRenderThreads() -{ - StopThreads(); -} - -void PolyRenderThreads::Clear() -{ - for (auto &thread : Threads) - { - thread->FrameMemory->Clear(); - thread->DrawQueue->Clear(); - - while (!thread->UsedDrawQueues.empty()) - { - auto queue = thread->UsedDrawQueues.back(); - thread->UsedDrawQueues.pop_back(); - queue->Clear(); - thread->FreeDrawQueues.push_back(queue); - } - } -} - -void PolyRenderThreads::RenderThreadSlices(int totalcount, std::function workerCallback, std::function collectCallback) -{ - WorkerCallback = workerCallback; - - int numThreads = std::thread::hardware_concurrency(); - if (numThreads == 0) - numThreads = 1; - - if (r_scene_multithreaded == 0 || r_multithreaded == 0) - numThreads = 1; - else if (r_scene_multithreaded != 1) - numThreads = r_scene_multithreaded; - - if (numThreads != (int)Threads.size()) - { - StopThreads(); - StartThreads(numThreads); - } - - // Setup threads: - std::unique_lock start_lock(start_mutex); - for (int i = 0; i < numThreads; i++) - { - Threads[i]->Start = totalcount * i / numThreads; - Threads[i]->End = totalcount * (i + 1) / numThreads; - } - run_id++; - start_lock.unlock(); - - // Notify threads to run - if (Threads.size() > 1) - { - start_condition.notify_all(); - } - - // Do the main thread ourselves: - RenderThreadSlice(MainThread()); - - // Wait for everyone to finish: - if (Threads.size() > 1) - { - using namespace std::chrono_literals; - std::unique_lock end_lock(end_mutex); - finished_threads++; - if (!end_condition.wait_for(end_lock, 5s, [&]() { return finished_threads == Threads.size(); })) - { -#ifdef WIN32 - PeekThreadedErrorPane(); -#endif - // Invoke the crash reporter so that we can capture the call stack of whatever the hung worker thread is doing - int *threadCrashed = nullptr; - *threadCrashed = 0xdeadbeef; - } - finished_threads = 0; - } - - for (int i = 0; i < numThreads; i++) - { - Threads[i]->FlushDrawQueue(); - } - - WorkerCallback = {}; - - for (int i = 1; i < numThreads; i++) - { - collectCallback(Threads[i].get()); - } -} - -void PolyRenderThreads::RenderThreadSlice(PolyRenderThread *thread) -{ - WorkerCallback(thread); -} - -void PolyRenderThreads::StartThreads(size_t numThreads) -{ - while (Threads.size() < (size_t)numThreads) - { - std::unique_ptr thread(new PolyRenderThread((int)Threads.size())); - auto renderthread = thread.get(); - int start_run_id = run_id; - thread->thread = std::thread([=]() - { - int last_run_id = start_run_id; - while (true) - { - // Wait until we are signalled to run: - std::unique_lock start_lock(start_mutex); - start_condition.wait(start_lock, [&]() { return run_id != last_run_id || shutdown_flag; }); - if (shutdown_flag) - break; - last_run_id = run_id; - start_lock.unlock(); - - RenderThreadSlice(renderthread); - - // Notify main thread that we finished: - std::unique_lock end_lock(end_mutex); - finished_threads++; - end_lock.unlock(); - end_condition.notify_all(); - } - }); - Threads.push_back(std::move(thread)); - } -} - -void PolyRenderThreads::StopThreads() -{ - std::unique_lock lock(start_mutex); - shutdown_flag = true; - lock.unlock(); - start_condition.notify_all(); - while (Threads.size() > 1) - { - Threads.back()->thread.join(); - Threads.pop_back(); - } - lock.lock(); - shutdown_flag = false; -} diff --git a/src/rendering/polyrenderer/poly_renderthread.h b/src/rendering/polyrenderer/poly_renderthread.h deleted file mode 100644 index d6be7db158..0000000000 --- a/src/rendering/polyrenderer/poly_renderthread.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include -#include -#include "swrenderer/r_memory.h" - -class DrawerCommandQueue; -typedef std::shared_ptr DrawerCommandQueuePtr; -class RenderMemory; -class PolyTranslucentObject; -class PolyDrawSectorPortal; -class PolyDrawLinePortal; -struct FDynamicLight; - -class PolyRenderThread -{ -public: - PolyRenderThread(int threadIndex); - ~PolyRenderThread(); - - void FlushDrawQueue(); - - int Start = 0; - int End = 0; - bool MainThread = false; - int ThreadIndex = 0; - - std::unique_ptr FrameMemory; - DrawerCommandQueuePtr DrawQueue; - - std::vector TranslucentObjects; - std::vector> SectorPortals; - std::vector> LinePortals; - - TArray AddedLightsArray; - - // Make sure texture can accessed safely - void PrepareTexture(FSoftwareTexture *texture, FRenderStyle style); - - // Setup poly object in a threadsafe manner - void PreparePolyObject(subsector_t *sub); - -private: - std::thread thread; - std::vector UsedDrawQueues; - std::vector FreeDrawQueues; - - friend class PolyRenderThreads; -}; - -class PolyRenderThreads -{ -public: - PolyRenderThreads(); - ~PolyRenderThreads(); - - void Clear(); - void RenderThreadSlices(int totalcount, std::function workerCallback, std::function collectCallback); - - PolyRenderThread *MainThread() { return Threads.front().get(); } - int NumThreads() const { return (int)Threads.size(); } - - std::vector> Threads; - -private: - void RenderThreadSlice(PolyRenderThread *thread); - - void StartThreads(size_t numThreads); - void StopThreads(); - - std::function WorkerCallback; - - std::mutex start_mutex; - std::condition_variable start_condition; - bool shutdown_flag = false; - int run_id = 0; - std::mutex end_mutex; - std::condition_variable end_condition; - size_t finished_threads = 0; -}; diff --git a/src/rendering/polyrenderer/scene/poly_cull.cpp b/src/rendering/polyrenderer/scene/poly_cull.cpp deleted file mode 100644 index 1428a5931f..0000000000 --- a/src/rendering/polyrenderer/scene/poly_cull.cpp +++ /dev/null @@ -1,421 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "sbar.h" -#include "r_data/r_translate.h" -#include "poly_cull.h" -#include "polyrenderer/poly_renderer.h" - -void PolyCull::CullScene(sector_t *portalSector, line_t *portalLine) -{ - for (uint32_t sub : PvsSubsectors) - SubsectorDepths[sub] = 0xffffffff; - SubsectorDepths.resize(PolyRenderer::Instance()->Level->subsectors.Size(), 0xffffffff); - - for (uint32_t sector : SeenSectors) - SectorSeen[sector] = false; - SectorSeen.resize(PolyRenderer::Instance()->Level->sectors.Size()); - - PvsSubsectors.clear(); - SeenSectors.clear(); - - NextPvsLineStart = 0; - PvsLineStart.clear(); - PvsLineVisible.resize(PolyRenderer::Instance()->Level->segs.Size()); - - PortalSector = portalSector; - PortalLine = portalLine; - - SolidSegments.clear(); - - if (portalLine) - { - DVector3 viewpos = PolyRenderer::Instance()->Viewpoint.Pos; - DVector2 pt1 = portalLine->v1->fPos() - viewpos; - DVector2 pt2 = portalLine->v2->fPos() - viewpos; - if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0) - { - angle_t angle1 = PointToPseudoAngle(portalLine->v1->fX(), portalLine->v1->fY()); - angle_t angle2 = PointToPseudoAngle(portalLine->v2->fX(), portalLine->v2->fY()); - MarkSegmentCulled(angle1, angle2); - } - else - { - angle_t angle2 = PointToPseudoAngle(portalLine->v1->fX(), portalLine->v1->fY()); - angle_t angle1 = PointToPseudoAngle(portalLine->v2->fX(), portalLine->v2->fY()); - MarkSegmentCulled(angle1, angle2); - } - InvertSegments(); - } - else - { - MarkViewFrustum(); - } - - // Cull front to back - FirstSkyHeight = true; - MaxCeilingHeight = 0.0; - MinFloorHeight = 0.0; - if (PolyRenderer::Instance()->Level->nodes.Size() == 0) - CullSubsector(&PolyRenderer::Instance()->Level->subsectors[0]); - else - CullNode(PolyRenderer::Instance()->Level->HeadNode()); -} - -void PolyCull::CullNode(void *node) -{ - while (!((size_t)node & 1)) // Keep going until found a subsector - { - node_t *bsp = (node_t *)node; - - // Decide which side the view point is on. - int side = PointOnSide(PolyRenderer::Instance()->Viewpoint.Pos, bsp); - - // Recursively divide front space (toward the viewer). - CullNode(bsp->children[side]); - - // Possibly divide back space (away from the viewer). - side ^= 1; - - if (!CheckBBox(bsp->bbox[side])) - return; - - node = bsp->children[side]; - } - - subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); - CullSubsector(sub); -} - -void PolyCull::CullSubsector(subsector_t *sub) -{ - // Ignore everything in front of the portal - if (PortalSector) - { - if (sub->sector != PortalSector) - return; - PortalSector = nullptr; - } - - // Update sky heights for the scene - if (!FirstSkyHeight) - { - MaxCeilingHeight = MAX(MaxCeilingHeight, sub->sector->ceilingplane.Zat0()); - MinFloorHeight = MIN(MinFloorHeight, sub->sector->floorplane.Zat0()); - } - else - { - MaxCeilingHeight = sub->sector->ceilingplane.Zat0(); - MinFloorHeight = sub->sector->floorplane.Zat0(); - FirstSkyHeight = false; - } - - uint32_t subsectorDepth = (uint32_t)PvsSubsectors.size(); - - // Mark that we need to render this - PvsSubsectors.push_back(sub->Index()); - PvsLineStart.push_back(NextPvsLineStart); - - DVector3 viewpos = PolyRenderer::Instance()->Viewpoint.Pos; - - // Update culling info for further bsp clipping - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - - // Skip lines not facing viewer - DVector2 pt1 = line->v1->fPos() - viewpos; - DVector2 pt2 = line->v2->fPos() - viewpos; - if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0) - { - PvsLineVisible[NextPvsLineStart++] = false; - continue; - } - - // Do not draw the portal line - if (line->linedef == PortalLine) - { - PvsLineVisible[NextPvsLineStart++] = false; - continue; - } - - angle_t angle2 = PointToPseudoAngle(line->v1->fX(), line->v1->fY()); - angle_t angle1 = PointToPseudoAngle(line->v2->fX(), line->v2->fY()); - bool lineVisible = !IsSegmentCulled(angle1, angle2); - if (lineVisible && IsSolidLine(line)) - { - MarkSegmentCulled(angle1, angle2); - } - - // Mark if this line was visible - PvsLineVisible[NextPvsLineStart++] = lineVisible; - } - - if (!SectorSeen[sub->sector->Index()]) - { - SectorSeen[sub->sector->Index()] = true; - SeenSectors.push_back(sub->sector->Index()); - } - - SubsectorDepths[sub->Index()] = subsectorDepth; -} - -bool PolyCull::IsSolidLine(seg_t *line) -{ - // One-sided - if (!line->backsector) return true; - - // Portal - if (line->linedef && line->linedef->isVisualPortal() && line->sidedef == line->linedef->sidedef[0]) return true; - - double frontCeilingZ1 = line->frontsector->ceilingplane.ZatPoint(line->v1); - double frontFloorZ1 = line->frontsector->floorplane.ZatPoint(line->v1); - double frontCeilingZ2 = line->frontsector->ceilingplane.ZatPoint(line->v2); - double frontFloorZ2 = line->frontsector->floorplane.ZatPoint(line->v2); - - double backCeilingZ1 = line->backsector->ceilingplane.ZatPoint(line->v1); - double backFloorZ1 = line->backsector->floorplane.ZatPoint(line->v1); - double backCeilingZ2 = line->backsector->ceilingplane.ZatPoint(line->v2); - double backFloorZ2 = line->backsector->floorplane.ZatPoint(line->v2); - - // Closed door. - if (backCeilingZ1 <= frontFloorZ1 && backCeilingZ2 <= frontFloorZ2) return true; - if (backFloorZ1 >= frontCeilingZ1 && backFloorZ2 >= frontCeilingZ2) return true; - - // properly render skies (consider door "open" if both ceilings are sky) - if (line->backsector->GetTexture(sector_t::ceiling) == skyflatnum && line->frontsector->GetTexture(sector_t::ceiling) == skyflatnum) return false; - - // if door is closed because back is shut: - if (!(backCeilingZ1 <= backFloorZ1 && backCeilingZ2 <= backFloorZ2)) return false; - - // preserve a kind of transparent door/lift special effect: - if (((backCeilingZ1 >= frontCeilingZ1 && backCeilingZ2 >= frontCeilingZ2) || line->sidedef->GetTexture(side_t::top).isValid()) - && ((backFloorZ1 <= frontFloorZ1 && backFloorZ2 <= frontFloorZ2) || line->sidedef->GetTexture(side_t::bottom).isValid())) - { - // killough 1/18/98 -- This function is used to fix the automap bug which - // showed lines behind closed doors simply because the door had a dropoff. - // - // It assumes that Doom has already ruled out a door being closed because - // of front-back closure (e.g. front floor is taller than back ceiling). - - // This fixes the automap floor height bug -- killough 1/18/98: - // killough 4/7/98: optimize: save result in doorclosed for use in r_segs.c - return true; - } - - return false; -} - -bool PolyCull::IsSegmentCulled(angle_t startAngle, angle_t endAngle) const -{ - if (startAngle > endAngle) - { - return IsSegmentCulled(startAngle, ANGLE_MAX) && IsSegmentCulled(0, endAngle); - } - - for (const auto &segment : SolidSegments) - { - if (startAngle >= segment.Start && endAngle <= segment.End) - return true; - else if (endAngle < segment.Start) - return false; - } - return false; -} - -void PolyCull::MarkSegmentCulled(angle_t startAngle, angle_t endAngle) -{ - if (startAngle > endAngle) - { - MarkSegmentCulled(startAngle, ANGLE_MAX); - MarkSegmentCulled(0, endAngle); - return; - } - - int count = (int)SolidSegments.size(); - int cur = 0; - while (cur < count) - { - if (SolidSegments[cur].Start <= startAngle && SolidSegments[cur].End >= endAngle) // Already fully marked - { - return; - } - else if (SolidSegments[cur].End >= startAngle && SolidSegments[cur].Start <= endAngle) // Merge segments - { - // Find last segment - int merge = cur; - while (merge + 1 != count && SolidSegments[merge + 1].Start <= endAngle) - merge++; - - // Apply new merged range - SolidSegments[cur].Start = MIN(SolidSegments[cur].Start, startAngle); - SolidSegments[cur].End = MAX(SolidSegments[merge].End, endAngle); - - // Remove additional segments we merged with - if (merge > cur) - SolidSegments.erase(SolidSegments.begin() + (cur + 1), SolidSegments.begin() + (merge + 1)); - - return; - } - else if (SolidSegments[cur].Start > startAngle) // Insert new segment - { - SolidSegments.insert(SolidSegments.begin() + cur, { startAngle, endAngle }); - return; - } - cur++; - } - SolidSegments.push_back({ startAngle, endAngle }); - -#if 0 - count = (int)SolidSegments.size(); - for (int i = 1; i < count; i++) - { - if (SolidSegments[i - 1].Start >= SolidSegments[i].Start || - SolidSegments[i - 1].End >= SolidSegments[i].Start || - SolidSegments[i - 1].End + 1 == SolidSegments[i].Start || - SolidSegments[i].Start > SolidSegments[i].End) - { - I_FatalError("MarkSegmentCulled is broken!"); - } - } -#endif -} - -int PolyCull::PointOnSide(const DVector2 &pos, const node_t *node) -{ - return DMulScale32(FLOAT2FIXED(pos.Y) - node->y, node->dx, node->x - FLOAT2FIXED(pos.X), node->dy) > 0; -} - -bool PolyCull::CheckBBox(float *bspcoord) -{ - // Occlusion test using solid segments: - static const uint8_t checkcoord[12][4] = - { - { 3,0,2,1 }, - { 3,0,2,0 }, - { 3,1,2,0 }, - { 0 }, - { 2,0,2,1 }, - { 0,0,0,0 }, - { 3,1,3,0 }, - { 0 }, - { 2,0,3,1 }, - { 2,1,3,1 }, - { 2,1,3,0 } - }; - - // Find the corners of the box that define the edges from current viewpoint. - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - int boxpos = (viewpoint.Pos.X <= bspcoord[BOXLEFT] ? 0 : viewpoint.Pos.X < bspcoord[BOXRIGHT] ? 1 : 2) + - (viewpoint.Pos.Y >= bspcoord[BOXTOP] ? 0 : viewpoint.Pos.Y > bspcoord[BOXBOTTOM] ? 4 : 8); - - if (boxpos == 5) return true; - - const uint8_t *check = checkcoord[boxpos]; - angle_t angle1 = PointToPseudoAngle(bspcoord[check[0]], bspcoord[check[1]]); - angle_t angle2 = PointToPseudoAngle(bspcoord[check[2]], bspcoord[check[3]]); - - return !IsSegmentCulled(angle2, angle1); -} - -void PolyCull::InvertSegments() -{ - TempInvertSolidSegments.swap(SolidSegments); - SolidSegments.clear(); - angle_t cur = 0; - for (const auto &segment : TempInvertSolidSegments) - { - if (cur < segment.Start) - MarkSegmentCulled(cur, segment.Start - 1); - if (segment.End == ANGLE_MAX) - return; - cur = segment.End + 1; - } - MarkSegmentCulled(cur, ANGLE_MAX); -} - -void PolyCull::MarkViewFrustum() -{ - // Clips things outside the viewing frustum. - auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - auto &viewwindow = PolyRenderer::Instance()->Viewwindow; - double tilt = fabs(viewpoint.Angles.Pitch.Degrees); - if (tilt > 46.0) // If the pitch is larger than this you can look all around - return; - - double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*viewpoint.FieldOfView.Degrees*48.0 / AspectMultiplier(viewwindow.WidescreenRatio) / 90.0; - angle_t a1 = DAngle(floatangle).BAMs(); - if (a1 < ANGLE_180) - { - MarkSegmentCulled(AngleToPseudo(viewpoint.Angles.Yaw.BAMs() + a1), AngleToPseudo(viewpoint.Angles.Yaw.BAMs() - a1)); - } -} - -//----------------------------------------------------------------------------- -// -// ! Returns the pseudoangle between the line p1 to (infinity, p1.y) and the -// line from p1 to p2. The pseudoangle has the property that the ordering of -// points by true angle around p1 and ordering of points by pseudoangle are the -// same. -// -// For clipping exact angles are not needed. Only the ordering matters. -// This is about as fast as the fixed point R_PointToAngle2 but without -// the precision issues associated with that function. -// -//----------------------------------------------------------------------------- - -angle_t PolyCull::PointToPseudoAngle(double x, double y) -{ - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - double vecx = x - viewpoint.Pos.X; - double vecy = y - viewpoint.Pos.Y; - - if (vecx == 0 && vecy == 0) - { - return 0; - } - else - { - double result = vecy / (fabs(vecx) + fabs(vecy)); - if (vecx < 0) - { - result = 2. - result; - } - return xs_Fix<30>::ToFix(result); - } -} - -angle_t PolyCull::AngleToPseudo(angle_t ang) -{ - double vecx = cos(ang * M_PI / ANGLE_180); - double vecy = sin(ang * M_PI / ANGLE_180); - - double result = vecy / (fabs(vecx) + fabs(vecy)); - if (vecx < 0) - { - result = 2.f - result; - } - return xs_Fix<30>::ToFix(result); -} diff --git a/src/rendering/polyrenderer/scene/poly_cull.h b/src/rendering/polyrenderer/scene/poly_cull.h deleted file mode 100644 index 81fa193875..0000000000 --- a/src/rendering/polyrenderer/scene/poly_cull.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include "polyrenderer/drawers/poly_triangle.h" -#include -#include - -class PolyCull -{ -public: - void CullScene(sector_t *portalSector, line_t *portalLine); - - bool IsLineSegVisible(uint32_t subsectorDepth, uint32_t lineIndex) - { - return PvsLineVisible[PvsLineStart[subsectorDepth] + lineIndex]; - } - - std::vector PvsSubsectors; - double MaxCeilingHeight = 0.0; - double MinFloorHeight = 0.0; - - std::vector SeenSectors; - std::vector SectorSeen; - std::vector SubsectorDepths; - - static angle_t PointToPseudoAngle(double x, double y); - -private: - struct SolidSegment - { - SolidSegment(angle_t start, angle_t end) : Start(start), End(end) { } - angle_t Start, End; - }; - - void MarkViewFrustum(); - void InvertSegments(); - - static bool IsSolidLine(seg_t *line); - - bool IsSegmentCulled(angle_t angle1, angle_t angle2) const; - - void CullNode(void *node); - void CullSubsector(subsector_t *sub); - int PointOnSide(const DVector2 &pos, const node_t *node); - - // Checks BSP node/subtree bounding box. - // Returns true if some part of the bbox might be visible. - bool CheckBBox(float *bspcoord); - - void MarkSegmentCulled(angle_t angle1, angle_t angle2); - - std::vector SolidSegments; - std::vector TempInvertSolidSegments; - std::vector PortalVisibility; - bool FirstSkyHeight = true; - - sector_t *PortalSector = nullptr; - line_t *PortalLine = nullptr; - - std::vector PvsLineStart; - std::vector PvsLineVisible; - uint32_t NextPvsLineStart = 0; - - static angle_t AngleToPseudo(angle_t ang); -}; diff --git a/src/rendering/polyrenderer/scene/poly_decal.cpp b/src/rendering/polyrenderer/scene/poly_decal.cpp deleted file mode 100644 index 54ba769559..0000000000 --- a/src/rendering/polyrenderer/scene/poly_decal.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "sbar.h" -#include "r_data/r_translate.h" -#include "poly_decal.h" -#include "polyrenderer/poly_renderer.h" -#include "polyrenderer/scene/poly_light.h" -#include "polyrenderer/poly_renderthread.h" -#include "a_sharedglobal.h" -#include "swrenderer/scene/r_scene.h" - -void RenderPolyDecal::RenderWallDecals(PolyRenderThread *thread, const seg_t *line, uint32_t stencilValue) -{ - if (line->linedef == nullptr && line->sidedef == nullptr) - return; - - for (DBaseDecal *decal = line->sidedef->AttachedDecals; decal != nullptr; decal = decal->WallNext) - { - RenderPolyDecal render; - render.Render(thread, decal, line, stencilValue); - } -} - -void RenderPolyDecal::Render(PolyRenderThread *thread, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue) -{ - if (decal->RenderFlags & RF_INVISIBLE || !viewactive || !decal->PicNum.isValid()) - return; - - FTexture *ttex = TexMan.GetPalettedTexture(decal->PicNum, true); - if (ttex == nullptr || !ttex->isValid()) - return; - - FSoftwareTexture *tex = ttex->GetSoftwareTexture(); - - sector_t *front, *back; - GetDecalSectors(decal, line, &front, &back); - - // Calculate unclipped position and UV coordinates - - // decals should not use renderer specific offsets. - double edge_left = tex->GetLeftOffset(0) * decal->ScaleX; - double edge_right = (tex->GetWidth() - tex->GetLeftOffset(0)) * decal->ScaleX; - - DVector2 angvec = (line->v2->fPos() - line->v1->fPos()).Unit(); - DVector2 normal = { angvec.Y, -angvec.X }; - - double dcx, dcy; - decal->GetXY(line->sidedef, dcx, dcy); - DVector2 decal_pos = DVector2(dcx, dcy) + normal; - DVector2 decal_left = decal_pos - edge_left * angvec; - DVector2 decal_right = decal_pos + edge_right * angvec; - - bool flipTextureX = (decal->RenderFlags & RF_XFLIP) == RF_XFLIP; - double u_left = flipTextureX ? 1.0 : 0.0; - double u_right = flipTextureX ? 1.0 - tex->GetScale().X : tex->GetScale().X; - double u_unit = (u_right - u_left) / (edge_left + edge_right); - - double zpos = GetDecalZ(decal, line, front, back); - double spriteHeight = decal->ScaleY / tex->GetScale().Y * tex->GetHeight(); - double ztop = zpos + spriteHeight - spriteHeight * 0.5; - double zbottom = zpos - spriteHeight * 0.5; - - double v_top = 0.0; - double v_bottom = tex->GetScale().Y; - double v_unit = (v_bottom - v_top) / (zbottom - ztop); - - // Clip decal to wall part - - double walltopz, wallbottomz; - GetWallZ(decal, line, front, back, walltopz, wallbottomz); - - double clip_left_v1 = (decal_left - line->v1->fPos()) | angvec; - double clip_right_v1 = (decal_right - line->v1->fPos()) | angvec; - double clip_left_v2 = (decal_left - line->v2->fPos()) | angvec; - double clip_right_v2 = (decal_right - line->v2->fPos()) | angvec; - - if ((clip_left_v1 <= 0.0 && clip_right_v1 <= 0.0) || (clip_left_v2 >= 0.0 && clip_right_v2 >= 0.0)) - return; - - if (clip_left_v1 < 0.0) - { - decal_left -= angvec * clip_left_v1; - u_left -= u_unit * clip_left_v1; - } - if (clip_right_v1 < 0.0) - { - decal_right -= angvec * clip_right_v1; - u_right -= u_unit * clip_right_v1; - } - if (clip_left_v2 > 0.0) - { - decal_left -= angvec * clip_left_v2; - u_left -= u_unit * clip_left_v2; - } - if (clip_right_v2 > 0.0) - { - decal_right -= angvec * clip_right_v2; - u_right -= u_unit * clip_right_v2; - } - - double clip_top_floor = ztop - wallbottomz; - double clip_bottom_floor = zbottom - wallbottomz; - double clip_top_ceiling = ztop - walltopz; - double clip_bottom_ceiling = zbottom - walltopz; - - if ((clip_top_floor <= 0.0 && clip_bottom_floor <= 0.0) || (clip_top_ceiling >= 0.0 && clip_bottom_ceiling >= 0.0)) - return; - - if (clip_top_floor < 0.0) - { - ztop -= clip_top_floor; - v_top -= v_unit * clip_top_floor; - } - if (clip_bottom_floor < 0.0) - { - zbottom -= clip_bottom_floor; - v_bottom -= v_unit * clip_bottom_floor; - } - if (clip_top_ceiling > 0.0) - { - ztop -= clip_top_ceiling; - v_top -= v_unit * clip_top_ceiling; - } - if (clip_bottom_ceiling > 0.0) - { - zbottom -= clip_bottom_ceiling; - v_bottom -= v_unit * clip_bottom_ceiling; - } - - // Generate vertices for the decal - - TriVertex *vertices = thread->FrameMemory->AllocMemory(4); - vertices[0].x = (float)decal_left.X; - vertices[0].y = (float)decal_left.Y; - vertices[0].z = (float)ztop; - vertices[0].w = 1.0f; - vertices[0].u = (float)u_left; - vertices[0].v = 1.0f - (float)v_top; - vertices[1].x = (float)decal_right.X; - vertices[1].y = (float)decal_right.Y; - vertices[1].z = (float)ztop; - vertices[1].w = 1.0f; - vertices[1].u = (float)u_right; - vertices[1].v = 1.0f - (float)v_top; - vertices[2].x = (float)decal_right.X; - vertices[2].y = (float)decal_right.Y; - vertices[2].z = (float)zbottom; - vertices[2].w = 1.0f; - vertices[2].u = (float)u_right; - vertices[2].v = 1.0f - (float)v_bottom; - vertices[3].x = (float)decal_left.X; - vertices[3].y = (float)decal_left.Y; - vertices[3].z = (float)zbottom; - vertices[3].w = 1.0f; - vertices[3].u = (float)u_left; - vertices[3].v = 1.0f - (float)v_bottom; - - // Light calculations - - bool foggy = false; - int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4; - bool fullbrightSprite = (decal->RenderFlags & RF_FULLBRIGHT) == RF_FULLBRIGHT; - int lightlevel = fullbrightSprite ? 255 : front->lightlevel + actualextralight; - - PolyDrawArgs args; - args.SetLight(GetColorTable(front->Colormap), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), fullbrightSprite); - args.SetColor(0xff000000 | decal->AlphaColor, decal->AlphaColor >> 24); - args.SetStyle(decal->RenderStyle, decal->Alpha, decal->AlphaColor, decal->Translation, tex, false); - args.SetStencilTestValue(stencilValue); - args.SetDepthTest(true); - args.SetWriteStencil(false); - args.SetWriteDepth(false); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, 4, PolyDrawMode::TriangleFan); -} - -void RenderPolyDecal::GetDecalSectors(DBaseDecal *decal, const seg_t *line, sector_t **front, sector_t **back) -{ - // for 3d-floor segments use the model sector as reference - if ((decal->RenderFlags&RF_CLIPMASK) == RF_CLIPMID) - *front = decal->Sector; - else - *front = line->frontsector; - - *back = (line->backsector != nullptr) ? line->backsector : line->frontsector; -} - -double RenderPolyDecal::GetDecalZ(DBaseDecal *decal, const seg_t *line, sector_t *front, sector_t *back) -{ - switch (decal->RenderFlags & RF_RELMASK) - { - default: - return decal->Z; - case RF_RELUPPER: - if (line->linedef->flags & ML_DONTPEGTOP) - return decal->Z + front->GetPlaneTexZ(sector_t::ceiling); - else - return decal->Z + back->GetPlaneTexZ(sector_t::ceiling); - case RF_RELLOWER: - if (line->linedef->flags & ML_DONTPEGBOTTOM) - return decal->Z + front->GetPlaneTexZ(sector_t::ceiling); - else - return decal->Z + back->GetPlaneTexZ(sector_t::floor); - break; - case RF_RELMID: - if (line->linedef->flags & ML_DONTPEGBOTTOM) - return decal->Z + front->GetPlaneTexZ(sector_t::floor); - else - return decal->Z + front->GetPlaneTexZ(sector_t::ceiling); - } -} - -void RenderPolyDecal::GetWallZ(DBaseDecal *decal, const seg_t *line, sector_t *front, sector_t *back, double &walltopz, double &wallbottomz) -{ - double frontceilz1 = front->ceilingplane.ZatPoint(line->v1); - double frontfloorz1 = front->floorplane.ZatPoint(line->v1); - double frontceilz2 = front->ceilingplane.ZatPoint(line->v2); - double frontfloorz2 = front->floorplane.ZatPoint(line->v2); - if (back == nullptr) - { - walltopz = MAX(frontceilz1, frontceilz2); - wallbottomz = MIN(frontfloorz1, frontfloorz2); - } - else - { - double backceilz1 = back->ceilingplane.ZatPoint(line->v1); - double backfloorz1 = back->floorplane.ZatPoint(line->v1); - double backceilz2 = back->ceilingplane.ZatPoint(line->v2); - double backfloorz2 = back->floorplane.ZatPoint(line->v2); - double topceilz1 = frontceilz1; - double topceilz2 = frontceilz2; - double topfloorz1 = MAX(MIN(backceilz1, frontceilz1), frontfloorz1); - double topfloorz2 = MAX(MIN(backceilz2, frontceilz2), frontfloorz2); - double bottomceilz1 = MIN(MAX(frontfloorz1, backfloorz1), frontceilz1); - double bottomceilz2 = MIN(MAX(frontfloorz2, backfloorz2), frontceilz2); - double bottomfloorz1 = frontfloorz1; - double bottomfloorz2 = frontfloorz2; - double middleceilz1 = topfloorz1; - double middleceilz2 = topfloorz2; - double middlefloorz1 = MIN(bottomceilz1, middleceilz1); - double middlefloorz2 = MIN(bottomceilz2, middleceilz2); - - switch (decal->RenderFlags & RF_RELMASK) - { - default: - walltopz = MAX(frontceilz1, frontceilz2); - wallbottomz = MIN(frontfloorz1, frontfloorz2); - break; - case RF_RELUPPER: - walltopz = MAX(topceilz1, topceilz2); - wallbottomz = MIN(topfloorz1, topfloorz2); - break; - case RF_RELLOWER: - walltopz = MAX(bottomceilz1, bottomceilz2); - wallbottomz = MIN(bottomfloorz1, bottomfloorz2); - break; - case RF_RELMID: - walltopz = MAX(middleceilz1, middleceilz2); - wallbottomz = MIN(middlefloorz1, middlefloorz2); - } - } -} diff --git a/src/rendering/polyrenderer/scene/poly_decal.h b/src/rendering/polyrenderer/scene/poly_decal.h deleted file mode 100644 index 5ca597109a..0000000000 --- a/src/rendering/polyrenderer/scene/poly_decal.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include "polyrenderer/drawers/poly_triangle.h" - -class RenderPolyDecal -{ -public: - static void RenderWallDecals(PolyRenderThread *thread, const seg_t *line, uint32_t stencilValue); - -private: - void Render(PolyRenderThread *thread, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue); - - void GetDecalSectors(DBaseDecal *decal, const seg_t *line, sector_t **front, sector_t **back); - double GetDecalZ(DBaseDecal *decal, const seg_t *line, sector_t *front, sector_t *back); - void GetWallZ(DBaseDecal *decal, const seg_t *line, sector_t *front, sector_t *back, double &walltopz, double &wallbottomz); -}; diff --git a/src/rendering/polyrenderer/scene/poly_light.cpp b/src/rendering/polyrenderer/scene/poly_light.cpp deleted file mode 100644 index e7ebf4c1e0..0000000000 --- a/src/rendering/polyrenderer/scene/poly_light.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "sbar.h" -#include "poly_light.h" -#include "polyrenderer/poly_renderer.h" - -void PolyLightVisibility::SetVisibility(FViewWindow &viewwindow, float vis) -{ - GlobVis = R_GetGlobVis(viewwindow, vis); -} - -fixed_t PolyLightVisibility::LightLevelToShade(int lightlevel, bool foggy) -{ - bool nolightfade = !foggy && ((PolyRenderer::Instance()->Level->flags3 & LEVEL3_NOLIGHTFADE)); - if (nolightfade) - { - return (MAX(255 - lightlevel, 0) * NUMCOLORMAPS) << (FRACBITS - 8); - } - else - { - // Convert a light level into an unbounded colormap index (shade). Result is - // fixed point. Why the +12? I wish I knew, but experimentation indicates it - // is necessary in order to best reproduce Doom's original lighting. - return (NUMCOLORMAPS * 2 * FRACUNIT) - ((lightlevel + 12) * (FRACUNIT*NUMCOLORMAPS / 128)); - } -} diff --git a/src/rendering/polyrenderer/scene/poly_light.h b/src/rendering/polyrenderer/scene/poly_light.h deleted file mode 100644 index 988dc718da..0000000000 --- a/src/rendering/polyrenderer/scene/poly_light.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include "swrenderer/scene/r_light.h" - -struct FViewWindow; - -// Keep using the software renderer's camera light class, for now. -// The DFrameBuffer abstraction relies on this being globally shared -typedef swrenderer::CameraLight PolyCameraLight; - -class PolyLightVisibility -{ -public: - void SetVisibility(FViewWindow &viewwindow, float vis); - - double WallGlobVis(bool foggy) const { return (NoLightFade && !foggy) ? 0.0 : GlobVis; } - double SpriteGlobVis(bool foggy) const { return (NoLightFade && !foggy) ? 0.0 : GlobVis; } - double ParticleGlobVis(bool foggy) const { return (NoLightFade && !foggy) ? 0.0 : GlobVis * 0.5; } - - // The vis value to pass into the GETPALOOKUP or LIGHTSCALE macros - double WallVis(double screenZ, bool foggy) const { return WallGlobVis(foggy) / screenZ; } - double SpriteVis(double screenZ, bool foggy) const { return SpriteGlobVis(foggy) / screenZ; } - double ParticleVis(double screenZ, bool foggy) const { return ParticleGlobVis(foggy) / screenZ; } - - static fixed_t LightLevelToShade(int lightlevel, bool foggy); - -private: - double GlobVis = 0.0f; - bool NoLightFade = false; -}; diff --git a/src/rendering/polyrenderer/scene/poly_model.cpp b/src/rendering/polyrenderer/scene/poly_model.cpp deleted file mode 100644 index e3bffcb491..0000000000 --- a/src/rendering/polyrenderer/scene/poly_model.cpp +++ /dev/null @@ -1,321 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "sbar.h" -#include "r_data/r_translate.h" -#include "poly_model.h" -#include "polyrenderer/poly_renderer.h" -#include "polyrenderer/scene/poly_light.h" -#include "polyrenderer/poly_renderthread.h" -#include "r_data/r_vanillatrans.h" -#include "actorinlines.h" -#include "i_time.h" - -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); - - renderer.sector = actor->Sector; - renderer.RenderStyle = actor->RenderStyle; - renderer.RenderAlpha = (float)actor->Alpha; - if (!renderer.RenderStyle.IsVisible(renderer.RenderAlpha)) - return; - - bool foggy = false; - int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4; - bool fullbrightSprite = ((actor->renderflags & RF_FULLBRIGHT) || (actor->flags5 & MF5_BRIGHT)); - renderer.lightlevel = fullbrightSprite ? 255 : actor->Sector->lightlevel + actualextralight; - renderer.visibility = PolyRenderer::Instance()->Light.SpriteGlobVis(foggy); - - renderer.fillcolor = actor->fillcolor; - renderer.Translation = actor->Translation; - - renderer.AddLights(actor); - renderer.RenderModel(x, y, z, smf, actor, PolyRenderer::Instance()->Viewpoint.TicFrac); - PolyTriangleDrawer::SetModelVertexShader(thread->DrawQueue, -1, -1, 0.0f); - PolyTriangleDrawer::SetTransform(thread->DrawQueue, thread->FrameMemory->NewObject(worldToClip), nullptr); -} - -static bool isBright(DPSprite *psp) -{ - if (psp != nullptr && psp->GetState() != nullptr) - { - bool disablefullbright = false; - FTextureID lump = sprites[psp->GetSprite()].GetSpriteFrame(psp->GetFrame(), 0, 0., nullptr); - if (lump.isValid()) - { - FTexture * tex = TexMan.GetPalettedTexture(lump, true); - if (tex) disablefullbright = tex->isFullbrightDisabled(); - } - return psp->GetState()->GetFullbright() && !disablefullbright; - } - return false; -} - -void PolyRenderHUDModel(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy) -{ - PolyModelRenderer renderer(thread, worldToClip, stencilValue); - - AActor *playermo = players[consoleplayer].camera; - auto rs = psp->GetRenderStyle(playermo->RenderStyle, playermo->Alpha); - renderer.sector = playermo->Sector; - renderer.RenderStyle = rs.first; - renderer.RenderAlpha = rs.second; - if (psp->Flags & PSPF_FORCEALPHA) renderer.RenderAlpha = 0.0f; - if (!renderer.RenderStyle.IsVisible(renderer.RenderAlpha)) - return; - - bool foggy = false; - int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4; - bool fullbrightSprite = isBright(psp); - renderer.lightlevel = fullbrightSprite ? 255 : playermo->Sector->lightlevel + actualextralight; - renderer.visibility = PolyRenderer::Instance()->Light.SpriteGlobVis(foggy); - - PalEntry ThingColor = (playermo->RenderStyle.Flags & STYLEF_ColorIsFixed) ? playermo->fillcolor : 0xffffff; - ThingColor.a = 255; - - renderer.fillcolor = fullbrightSprite ? ThingColor : ThingColor.Modulate(playermo->Sector->SpecialColors[sector_t::sprites]); - renderer.Translation = 0xffffffff;// playermo->Translation; - - renderer.RenderHUDModel(psp, ofsx, ofsy); - PolyTriangleDrawer::SetModelVertexShader(thread->DrawQueue, -1, -1, 0.0f); -} - -///////////////////////////////////////////////////////////////////////////// - -PolyModelRenderer::PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue) : Thread(thread), WorldToClip(worldToClip), StencilValue(stencilValue) -{ -} - -void PolyModelRenderer::AddLights(AActor *actor) -{ - if (r_dynlights && actor) - { - auto &addedLights = Thread->AddedLightsArray; - - addedLights.Clear(); - - float x = (float)actor->X(); - float y = (float)actor->Y(); - float z = (float)actor->Center(); - float actorradius = (float)actor->RenderRadius(); - float radiusSquared = actorradius * actorradius; - - BSPWalkCircle(actor->Level, x, y, radiusSquared, [&](subsector_t *subsector) // Iterate through all subsectors potentially touched by actor - { - FLightNode * node = subsector->section->lighthead; - while (node) // check all lights touching a subsector - { - FDynamicLight *light = node->lightsource; - if (light->ShouldLightActor(actor)) - { - int group = subsector->sector->PortalGroup; - DVector3 pos = light->PosRelative(group); - float radius = (float)(light->GetRadius() + actorradius); - double dx = pos.X - x; - double dy = pos.Y - y; - double dz = pos.Z - z; - double distSquared = dx * dx + dy * dy + dz * dz; - if (distSquared < radius * radius) // Light and actor touches - { - if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector - { - addedLights.Push(light); - } - } - } - node = node->nextLight; - } - }); - - NumLights = addedLights.Size(); - Lights = Thread->FrameMemory->AllocMemory(NumLights); - for (int i = 0; i < NumLights; i++) - { - FDynamicLight *lightsource = addedLights[i]; - - bool is_point_light = lightsource->IsAttenuated(); - - uint32_t red = lightsource->GetRed(); - uint32_t green = lightsource->GetGreen(); - uint32_t blue = lightsource->GetBlue(); - - PolyLight &light = Lights[i]; - light.x = (float)lightsource->X(); - light.y = (float)lightsource->Y(); - light.z = (float)lightsource->Z(); - light.radius = 256.0f / lightsource->GetRadius(); - light.color = (red << 16) | (green << 8) | blue; - if (is_point_light) - light.radius = -light.radius; - } - } -} - -void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) -{ - const_cast(objectToWorldMatrix).copy(ObjectToWorld.Matrix); - SetTransform(); - - if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal] || !!(smf->flags & MDL_DONTCULLBACKFACES)) - PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true); - PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, !mirrored); -} - -void PolyModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf) -{ - if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal] || !!(smf->flags & MDL_DONTCULLBACKFACES)) - PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false); - PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, true); -} - -IModelVertexBuffer *PolyModelRenderer::CreateVertexBuffer(bool needindex, bool singleframe) -{ - return new PolyModelVertexBuffer(needindex, singleframe); -} - -VSMatrix PolyModelRenderer::GetViewToWorldMatrix() -{ - Mat4f swapYZ = Mat4f::Null(); - swapYZ.Matrix[0 + 0 * 4] = 1.0f; - swapYZ.Matrix[1 + 2 * 4] = 1.0f; - swapYZ.Matrix[2 + 1 * 4] = 1.0f; - swapYZ.Matrix[3 + 3 * 4] = 1.0f; - - VSMatrix worldToView; - worldToView.loadMatrix((PolyRenderer::Instance()->Scene.CurrentViewpoint->WorldToView * swapYZ).Matrix); - - VSMatrix objectToWorld; - worldToView.inverseMatrix(objectToWorld); - return objectToWorld; -} - -void PolyModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix, bool mirrored) -{ - const_cast(objectToWorldMatrix).copy(ObjectToWorld.Matrix); - SetTransform(); - PolyTriangleDrawer::SetWeaponScene(Thread->DrawQueue, true); - - if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal]) - PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true); - PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, mirrored); -} - -void PolyModelRenderer::EndDrawHUDModel(AActor *actor) -{ - PolyTriangleDrawer::SetWeaponScene(Thread->DrawQueue, false); - - if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal]) - PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false); - PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, true); -} - -void PolyModelRenderer::SetInterpolation(double interpolation) -{ - InterpolationFactor = (float)interpolation; -} - -void PolyModelRenderer::SetMaterial(FTexture *skin, bool clampNoFilter, int translation) -{ - SkinTexture = skin? skin->GetSoftwareTexture() : nullptr; -} - -void PolyModelRenderer::SetTransform() -{ - Mat4f swapYZ = Mat4f::Null(); - swapYZ.Matrix[0 + 0 * 4] = 1.0f; - swapYZ.Matrix[1 + 2 * 4] = 1.0f; - swapYZ.Matrix[2 + 1 * 4] = 1.0f; - swapYZ.Matrix[3 + 3 * 4] = 1.0f; - ObjectToWorld = swapYZ * ObjectToWorld; - - PolyTriangleDrawer::SetTransform(Thread->DrawQueue, Thread->FrameMemory->NewObject(WorldToClip * ObjectToWorld), Thread->FrameMemory->NewObject(ObjectToWorld)); -} - -void PolyModelRenderer::DrawArrays(int start, int count) -{ - PolyDrawArgs args; - auto nc = !!(sector->Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING); - args.SetLight(GetSpriteColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], nc), lightlevel, visibility, fullbrightSprite); args.SetLights(Lights, NumLights); - args.SetStencilTestValue(StencilValue); - args.SetClipPlane(0, PolyClipPlane()); - args.SetStyle(RenderStyle, RenderAlpha, fillcolor, Translation, SkinTexture, fullbrightSprite); - args.SetDepthTest(true); - args.SetWriteDepth(true); - args.SetWriteStencil(false); - PolyTriangleDrawer::DrawArray(Thread->DrawQueue, args, VertexBuffer + start, count); -} - -void PolyModelRenderer::DrawElements(int numIndices, size_t offset) -{ - PolyDrawArgs args; - auto nc = !!(sector->Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING); - args.SetLight(GetSpriteColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], nc), lightlevel, visibility, fullbrightSprite); args.SetLights(Lights, NumLights); - args.SetStencilTestValue(StencilValue); - args.SetClipPlane(0, PolyClipPlane()); - args.SetStyle(RenderStyle, RenderAlpha, fillcolor, Translation, SkinTexture, fullbrightSprite); - args.SetDepthTest(true); - args.SetWriteDepth(true); - args.SetWriteStencil(false); - PolyTriangleDrawer::DrawElements(Thread->DrawQueue, args, VertexBuffer, IndexBuffer + offset / sizeof(unsigned int), numIndices); -} - -///////////////////////////////////////////////////////////////////////////// - -PolyModelVertexBuffer::PolyModelVertexBuffer(bool needindex, bool singleframe) -{ -} - -PolyModelVertexBuffer::~PolyModelVertexBuffer() -{ -} - -FModelVertex *PolyModelVertexBuffer::LockVertexBuffer(unsigned int size) -{ - mVertexBuffer.Resize(size); - return &mVertexBuffer[0]; -} - -void PolyModelVertexBuffer::UnlockVertexBuffer() -{ -} - -unsigned int *PolyModelVertexBuffer::LockIndexBuffer(unsigned int size) -{ - mIndexBuffer.Resize(size); - return &mIndexBuffer[0]; -} - -void PolyModelVertexBuffer::UnlockIndexBuffer() -{ -} - -void PolyModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) -{ - PolyModelRenderer *polyrenderer = (PolyModelRenderer *)renderer; - polyrenderer->VertexBuffer = mVertexBuffer.Size() ? &mVertexBuffer[0] : nullptr; - polyrenderer->IndexBuffer = mIndexBuffer.Size() ? &mIndexBuffer[0] : nullptr; - PolyTriangleDrawer::SetModelVertexShader(polyrenderer->Thread->DrawQueue, frame1, frame2, polyrenderer->InterpolationFactor); -} diff --git a/src/rendering/polyrenderer/scene/poly_model.h b/src/rendering/polyrenderer/scene/poly_model.h deleted file mode 100644 index bdf6c94230..0000000000 --- a/src/rendering/polyrenderer/scene/poly_model.h +++ /dev/null @@ -1,93 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include "polyrenderer/drawers/poly_triangle.h" -#include "r_data/matrix.h" -#include "r_data/models/models.h" - -void PolyRenderModel(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor); -void PolyRenderHUDModel(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy); - -class PolyModelRenderer : public FModelRenderer -{ -public: - PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue); - - void AddLights(AActor *actor); - - ModelRendererType GetType() const override { return PolyModelRendererType; } - - void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) override; - void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override; - IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override; - VSMatrix GetViewToWorldMatrix() override; - void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix, bool mirrored) override; - void EndDrawHUDModel(AActor *actor) override; - void SetInterpolation(double interpolation) override; - void SetMaterial(FTexture *skin, bool clampNoFilter, int translation) override; - void DrawArrays(int start, int count) override; - void DrawElements(int numIndices, size_t offset) override; - - void SetTransform(); - - PolyRenderThread *Thread = nullptr; - const Mat4f &WorldToClip; - uint32_t StencilValue = 0; - - FRenderStyle RenderStyle; - float RenderAlpha; - sector_t *sector; - bool fullbrightSprite; - int lightlevel; - double visibility; - uint32_t fillcolor; - uint32_t Translation; - - Mat4f ObjectToWorld; - FSoftwareTexture *SkinTexture = nullptr; - unsigned int *IndexBuffer = nullptr; - FModelVertex *VertexBuffer = nullptr; - float InterpolationFactor = 0.0; - PolyLight *Lights = nullptr; - int NumLights = 0; -}; - -class PolyModelVertexBuffer : public IModelVertexBuffer -{ -public: - PolyModelVertexBuffer(bool needindex, bool singleframe); - ~PolyModelVertexBuffer(); - - FModelVertex *LockVertexBuffer(unsigned int size) override; - void UnlockVertexBuffer() override; - - unsigned int *LockIndexBuffer(unsigned int size) override; - void UnlockIndexBuffer() override; - - void SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) override; - -private: - TArray mVertexBuffer; - TArray mIndexBuffer; -}; diff --git a/src/rendering/polyrenderer/scene/poly_particle.cpp b/src/rendering/polyrenderer/scene/poly_particle.cpp deleted file mode 100644 index b8c7374075..0000000000 --- a/src/rendering/polyrenderer/scene/poly_particle.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "sbar.h" -#include "r_data/r_translate.h" -#include "poly_particle.h" -#include "polyrenderer/poly_renderer.h" -#include "polyrenderer/scene/poly_light.h" -#include "polyrenderer/poly_renderthread.h" - -EXTERN_CVAR(Int, gl_particles_style) - -void RenderPolyParticle::Render(PolyRenderThread *thread, particle_t *particle, subsector_t *sub, uint32_t stencilValue) -{ - double timefrac = PolyRenderer::Instance()->Viewpoint.TicFrac; - if (paused || PolyRenderer::Instance()->Viewpoint.ViewLevel->isFrozen()) - timefrac = 0.; - DVector3 pos = particle->Pos + (particle->Vel * timefrac); - double psize = particle->size / 8.0; - double zpos = pos.Z; - - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - - DVector2 points[2] = - { - { pos.X - viewpoint.Sin * psize, pos.Y + viewpoint.Cos * psize }, - { pos.X + viewpoint.Sin * psize, pos.Y - viewpoint.Cos * psize } - }; - - TriVertex *vertices = thread->FrameMemory->AllocMemory(4); - - bool foggy = false; - int actualextralight = foggy ? 0 : viewpoint.extralight << 4; - - std::pair offsets[4] = - { - { 0.0f, 1.0f }, - { 1.0f, 1.0f }, - { 1.0f, 0.0f }, - { 0.0f, 0.0f }, - }; - - for (int i = 0; i < 4; i++) - { - auto &p = (i == 0 || i == 3) ? points[0] : points[1]; - - vertices[i].x = (float)p.X; - vertices[i].y = (float)p.Y; - vertices[i].z = (float)(zpos + psize * (2.0 * offsets[i].second - 1.0)); - vertices[i].w = 1.0f; - vertices[i].u = (float)(offsets[i].first); - vertices[i].v = (float)(1.0f - offsets[i].second); - } - - bool fullbrightSprite = particle->bright != 0; - int lightlevel = fullbrightSprite ? 255 : sub->sector->lightlevel + actualextralight; - - PolyDrawArgs args; - args.SetLight(GetColorTable(sub->sector->Colormap), lightlevel, PolyRenderer::Instance()->Light.ParticleGlobVis(foggy), fullbrightSprite); - args.SetDepthTest(true); - args.SetColor(particle->color | 0xff000000, particle->color >> 24); - args.SetStyle(TriBlendMode::Shaded, particle->alpha); - args.SetStencilTestValue(stencilValue); - args.SetWriteStencil(false); - args.SetWriteDepth(false); - args.SetTexture(GetParticleTexture(), ParticleTextureSize, ParticleTextureSize); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, 4, PolyDrawMode::TriangleFan); -} - -uint8_t *RenderPolyParticle::GetParticleTexture() -{ - static uint8_t particle_texture[NumParticleTextures][ParticleTextureSize * ParticleTextureSize]; - static bool first_call = true; - if (first_call) - { - double center = ParticleTextureSize * 0.5f; - for (int y = 0; y < ParticleTextureSize; y++) - { - for (int x = 0; x < ParticleTextureSize; x++) - { - double dx = (center - x - 0.5f) / center; - double dy = (center - y - 0.5f) / center; - double dist2 = dx * dx + dy * dy; - double round_alpha = clamp(1.7f - dist2 * 1.7f, 0.0f, 1.0f); - double smooth_alpha = clamp(1.1f - dist2 * 1.1f, 0.0f, 1.0f); - - particle_texture[0][x + y * ParticleTextureSize] = 255; - particle_texture[1][x + y * ParticleTextureSize] = (int)(round_alpha * 255.0f + 0.5f); - particle_texture[2][x + y * ParticleTextureSize] = (int)(smooth_alpha * 255.0f + 0.5f); - } - } - first_call = false; - } - return particle_texture[MIN(gl_particles_style, NumParticleTextures)]; -} diff --git a/src/rendering/polyrenderer/scene/poly_particle.h b/src/rendering/polyrenderer/scene/poly_particle.h deleted file mode 100644 index 5d6b46a97d..0000000000 --- a/src/rendering/polyrenderer/scene/poly_particle.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include "polyrenderer/drawers/poly_triangle.h" -#include "p_effect.h" - -class RenderPolyParticle -{ -public: - void Render(PolyRenderThread *thread, particle_t *particle, subsector_t *sub, uint32_t stencilValue); - -private: - static uint8_t *GetParticleTexture(); - - enum - { - NumParticleTextures = 3, - 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(PolyRenderThread *thread) override - { - RenderPolyParticle spr; - spr.Render(thread, particle, sub, StencilValue + 1); - } - - particle_t *particle = nullptr; - subsector_t *sub = nullptr; - uint32_t StencilValue = 0; -}; diff --git a/src/rendering/polyrenderer/scene/poly_plane.cpp b/src/rendering/polyrenderer/scene/poly_plane.cpp deleted file mode 100644 index 1a1ceb0e0c..0000000000 --- a/src/rendering/polyrenderer/scene/poly_plane.cpp +++ /dev/null @@ -1,565 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "sbar.h" -#include "r_data/r_translate.h" -#include "poly_plane.h" -#include "poly_portal.h" -#include "polyrenderer/poly_renderer.h" -#include "r_sky.h" -#include "polyrenderer/scene/poly_light.h" -#include "polyrenderer/poly_renderthread.h" -#include "p_lnspec.h" -#include "a_dynlight.h" - -EXTERN_CVAR(Int, r_3dfloors) - -void RenderPolyPlane::RenderPlanes(PolyRenderThread *thread, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals, size_t sectorPortalsStart) -{ - if (fakeflat.FrontSector->CenterFloor() == fakeflat.FrontSector->CenterCeiling()) - return; - - RenderPolyPlane plane; - plane.Render(thread, fakeflat, stencilValue, true, skyCeilingHeight, sectorPortals, sectorPortalsStart); - plane.Render(thread, fakeflat, stencilValue, false, skyFloorHeight, sectorPortals, sectorPortalsStart); -} - -void RenderPolyPlane::Render(PolyRenderThread *thread, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals, size_t sectorPortalsStart) -{ - FSectorPortal *portal = fakeflat.FrontSector->ValidatePortal(ceiling ? sector_t::ceiling : sector_t::floor); - if (!portal || (portal->mFlags & PORTSF_INSKYBOX) == PORTSF_INSKYBOX) // Do not recurse into portals we already recursed into - { - RenderNormal(thread, fakeflat, stencilValue, ceiling, skyHeight); - } - else - { - RenderPortal(thread, fakeflat, stencilValue, ceiling, skyHeight, portal, sectorPortals, sectorPortalsStart); - } -} - -void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight) -{ - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - - FTextureID picnum = fakeflat.FrontSector->GetTexture(ceiling ? sector_t::ceiling : sector_t::floor); - if (picnum != skyflatnum) - { - FTexture *tex = TexMan.GetPalettedTexture(picnum, true); - if (!tex || !tex->isValid()) - return; - - PolyPlaneUVTransform transform = PolyPlaneUVTransform(ceiling ? fakeflat.FrontSector->planes[sector_t::ceiling].xform : fakeflat.FrontSector->planes[sector_t::floor].xform, tex->GetSoftwareTexture()); - TriVertex *vertices = CreatePlaneVertices(thread, fakeflat.Subsector, transform, ceiling ? fakeflat.FrontSector->ceilingplane : fakeflat.FrontSector->floorplane); - - PolyDrawArgs args; - SetLightLevel(thread, args, fakeflat, ceiling); - SetDynLights(thread, args, fakeflat.Subsector, ceiling); - args.SetStencilTestValue(stencilValue); - args.SetWriteStencil(true, stencilValue + 1); - args.SetTexture(tex->GetSoftwareTexture(), DefaultRenderStyle()); - args.SetStyle(TriBlendMode::Opaque); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); - } - else - { - TriVertex *vertices = CreateSkyPlaneVertices(thread, fakeflat.Subsector, skyHeight); - - PolyDrawArgs args; - args.SetStencilTestValue(stencilValue); - args.SetWriteStencil(true, 255); - args.SetWriteColor(false); - args.SetWriteDepth(false); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); - - RenderSkyWalls(thread, args, fakeflat.Subsector, nullptr, ceiling, skyHeight); - } -} - -void RenderPolyPlane::RenderPortal(PolyRenderThread *thread, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector> §orPortals, size_t sectorPortalsStart) -{ - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - - PolyDrawSectorPortal *polyportal = nullptr; - std::vector portalSegments; - - // Skip portals not facing the camera - if ((ceiling && fakeflat.FrontSector->ceilingplane.PointOnSide(viewpoint.Pos) < 0) || - (!ceiling && fakeflat.FrontSector->floorplane.PointOnSide(viewpoint.Pos) < 0)) - { - return; - } - - for (size_t i = sectorPortalsStart; i < sectorPortals.size(); i++) - { - if (sectorPortals[i]->Portal == portal) // To do: what other criteria do we need to check for? - { - polyportal = sectorPortals[i].get(); - break; - } - } - if (!polyportal) - { - sectorPortals.push_back(std::unique_ptr(new PolyDrawSectorPortal(portal, ceiling))); - polyportal = sectorPortals.back().get(); - } - -#if 0 - // Calculate portal clipping - portalSegments.reserve(sub->numlines); - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - - DVector2 pt1 = line->v1->fPos() - viewpoint.Pos; - DVector2 pt2 = line->v2->fPos() - viewpoint.Pos; - bool backside = pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0; - if (!backside) - { - angle_t angle1, angle2; - if (cull.GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2)) - portalSegments.push_back({ angle1, angle2 }); - } - else - { - angle_t angle1, angle2; - if (cull.GetAnglesForLine(line->v2->fX(), line->v2->fY(), line->v1->fX(), line->v1->fY(), angle1, angle2)) - portalSegments.push_back({ angle1, angle2 }); - } - } -#endif - - TriVertex *vertices = CreateSkyPlaneVertices(thread, fakeflat.Subsector, skyHeight); - - PolyDrawArgs args; - args.SetStencilTestValue(stencilValue); - args.SetWriteStencil(true, polyportal->StencilValue); - args.SetWriteColor(false); - args.SetWriteDepth(false); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); - - RenderSkyWalls(thread, args, fakeflat.Subsector, polyportal, ceiling, skyHeight); - - polyportal->Shape.push_back({ vertices, (int)fakeflat.Subsector->numlines }); -} - -void RenderPolyPlane::RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight) -{ - sector_t *frontsector = sub->sector; - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - - double skyBottomz1 = frontsector->ceilingplane.ZatPoint(line->v1); - double skyBottomz2 = frontsector->ceilingplane.ZatPoint(line->v2); - if (line->backsector) - { - sector_t *backsector = line->backsector; - - double backceilz1 = backsector->ceilingplane.ZatPoint(line->v1); - double backfloorz1 = backsector->floorplane.ZatPoint(line->v1); - double backceilz2 = backsector->ceilingplane.ZatPoint(line->v2); - double backfloorz2 = backsector->floorplane.ZatPoint(line->v2); - - bool bothSkyCeiling = frontsector->GetTexture(sector_t::ceiling) == skyflatnum && backsector->GetTexture(sector_t::ceiling) == skyflatnum; - - bool closedSector = backceilz1 == backfloorz1 && backceilz2 == backfloorz2; - if (ceiling && bothSkyCeiling && closedSector) - { - double frontceilz1 = frontsector->ceilingplane.ZatPoint(line->v1); - double frontfloorz1 = frontsector->floorplane.ZatPoint(line->v1); - double frontceilz2 = frontsector->ceilingplane.ZatPoint(line->v2); - double frontfloorz2 = frontsector->floorplane.ZatPoint(line->v2); - - double topceilz1 = frontceilz1; - double topceilz2 = frontceilz2; - double topfloorz1 = MIN(backceilz1, frontceilz1); - double topfloorz2 = MIN(backceilz2, frontceilz2); - double bottomceilz1 = MAX(frontfloorz1, backfloorz1); - double bottomceilz2 = MAX(frontfloorz2, backfloorz2); - double middleceilz1 = topfloorz1; - double middleceilz2 = topfloorz2; - double middlefloorz1 = MIN(bottomceilz1, middleceilz1); - double middlefloorz2 = MIN(bottomceilz2, middleceilz2); - - skyBottomz1 = middlefloorz1; - skyBottomz2 = middlefloorz2; - } - else if (bothSkyCeiling) - { - continue; - } - } - else if (polyportal && line->linedef && line->linedef->special == Line_Horizon) - { - // Not entirely correct as this closes the line horizon rather than allowing the floor to continue to infinity - skyBottomz1 = frontsector->floorplane.ZatPoint(line->v1); - skyBottomz2 = frontsector->floorplane.ZatPoint(line->v2); - } - - TriVertex *wallvert = thread->FrameMemory->AllocMemory(4); - - if (ceiling) - { - wallvert[0] = GetSkyVertex(line->v1, skyHeight); - wallvert[1] = GetSkyVertex(line->v2, skyHeight); - wallvert[2] = GetSkyVertex(line->v2, skyBottomz2); - wallvert[3] = GetSkyVertex(line->v1, skyBottomz1); - } - else - { - wallvert[0] = GetSkyVertex(line->v1, frontsector->floorplane.ZatPoint(line->v1)); - wallvert[1] = GetSkyVertex(line->v2, frontsector->floorplane.ZatPoint(line->v2)); - wallvert[2] = GetSkyVertex(line->v2, skyHeight); - wallvert[3] = GetSkyVertex(line->v1, skyHeight); - } - - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, wallvert, 4, PolyDrawMode::TriangleFan); - - if (polyportal) - { - polyportal->Shape.push_back({ wallvert, 4 }); - } - } -} - -void RenderPolyPlane::SetLightLevel(PolyRenderThread *thread, PolyDrawArgs &args, const PolyTransferHeights &fakeflat, bool ceiling) -{ - bool foggy = PolyRenderer::Instance()->Level->fadeto || fakeflat.FrontSector->Colormap.FadeColor || (PolyRenderer::Instance()->Level->flags & LEVEL_HASFADETABLE); - - int lightlevel = ceiling ? fakeflat.CeilingLightLevel : fakeflat.FloorLightLevel; - int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4; - lightlevel = clamp(lightlevel + actualextralight, 0, 255); - - PolyCameraLight *cameraLight = PolyCameraLight::Instance(); - FDynamicColormap *basecolormap = GetColorTable(fakeflat.FrontSector->Colormap, fakeflat.FrontSector->SpecialColors[ceiling ? sector_t::ceiling : sector_t::floor]); - if (cameraLight->FixedLightLevel() < 0 && fakeflat.FrontSector->e && fakeflat.FrontSector->e->XFloor.lightlist.Size()) - { - lightlist_t *light = P_GetPlaneLight(fakeflat.FrontSector, ceiling ? &fakeflat.FrontSector->ceilingplane : &fakeflat.FrontSector->floorplane, false); - basecolormap = GetColorTable(light->extra_colormap, fakeflat.FrontSector->SpecialColors[ceiling ? sector_t::ceiling : sector_t::floor]); - if (light->p_lightlevel != &fakeflat.FrontSector->lightlevel) // If this is the real ceiling, don't discard plane lighting R_FakeFlat() accounted for. - { - lightlevel = *light->p_lightlevel; - } - } - - args.SetLight(basecolormap, lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), false); -} - -void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling) -{ - if (!r_dynlights) - { - args.SetLights(nullptr, 0); - return; - } - - FLightNode *light_list = sub->section->lighthead; - - auto cameraLight = PolyCameraLight::Instance(); - if ((cameraLight->FixedLightLevel() >= 0) || (cameraLight->FixedColormap() != nullptr)) - { - args.SetLights(nullptr, 0); // [SP] Don't draw dynlights if invul/lightamp active - return; - } - - // Calculate max lights that can touch the wall so we can allocate memory for the list - int max_lights = 0; - FLightNode *cur_node = light_list; - while (cur_node) - { - if (cur_node->lightsource->IsActive()) - max_lights++; - cur_node = cur_node->nextLight; - } - - if (max_lights == 0) - { - args.SetLights(nullptr, 0); - return; - } - - int dc_num_lights = 0; - PolyLight *dc_lights = thread->FrameMemory->AllocMemory(max_lights); - - // Setup lights - cur_node = light_list; - while (cur_node) - { - if (cur_node->lightsource->IsActive()) - { - bool is_point_light = cur_node->lightsource->IsAttenuated(); - - // To do: cull lights not touching subsector - - uint32_t red = cur_node->lightsource->GetRed(); - uint32_t green = cur_node->lightsource->GetGreen(); - uint32_t blue = cur_node->lightsource->GetBlue(); - - auto &light = dc_lights[dc_num_lights++]; - light.x = (float)cur_node->lightsource->X(); - light.y = (float)cur_node->lightsource->Y(); - light.z = (float)cur_node->lightsource->Z(); - light.radius = 256.0f / cur_node->lightsource->GetRadius(); - light.color = (red << 16) | (green << 8) | blue; - if (is_point_light) - light.radius = -light.radius; - } - - cur_node = cur_node->nextLight; - } - - args.SetLights(dc_lights, dc_num_lights); - - DVector3 normal = ceiling ? sub->sector->ceilingplane.Normal() : sub->sector->floorplane.Normal(); - args.SetNormal({ (float)normal.X, (float)normal.Y, (float)normal.Z }); -} - -TriVertex *RenderPolyPlane::CreatePlaneVertices(PolyRenderThread *thread, subsector_t *sub, const PolyPlaneUVTransform &transform, const secplane_t &plane) -{ - TriVertex *vertices = thread->FrameMemory->AllocMemory(sub->numlines); - - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - double planeZ = plane.ZatPoint(viewpoint.Pos.XY()); - if (viewpoint.Pos.Z < planeZ) - { - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[sub->numlines - 1 - i]; - vertices[i] = transform.GetVertex(line->v1, plane.ZatPoint(line->v1)); - } - } - else - { - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - vertices[i] = transform.GetVertex(line->v1, plane.ZatPoint(line->v1)); - } - } - - return vertices; -} - -TriVertex *RenderPolyPlane::CreateSkyPlaneVertices(PolyRenderThread *thread, subsector_t *sub, double skyHeight) -{ - TriVertex *vertices = thread->FrameMemory->AllocMemory(sub->numlines); - - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - if (viewpoint.Pos.Z < skyHeight) - { - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[sub->numlines - 1 - i]; - vertices[i] = GetSkyVertex(line->v1, skyHeight); - } - } - else - { - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - vertices[i] = GetSkyVertex(line->v1, skyHeight); - } - } - - return vertices; -} - -///////////////////////////////////////////////////////////////////////////// - -PolyPlaneUVTransform::PolyPlaneUVTransform(const FTransform &transform, FSoftwareTexture *tex) -{ - if (tex) - { - xscale = (float)(transform.xScale * tex->GetScale().X / tex->GetWidth()); - yscale = (float)(transform.yScale * tex->GetScale().Y / tex->GetHeight()); - - double planeang = (transform.Angle + transform.baseAngle).Radians(); - cosine = (float)cos(planeang); - sine = (float)sin(planeang); - - xOffs = (float)transform.xOffs; - yOffs = (float)transform.yOffs; - } - else - { - xscale = 1.0f / 64.0f; - yscale = 1.0f / 64.0f; - cosine = 1.0f; - sine = 0.0f; - xOffs = 0.0f; - yOffs = 0.0f; - } -} - -///////////////////////////////////////////////////////////////////////////// - -void Render3DFloorPlane::RenderPlanes(PolyRenderThread *thread, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector &translucentObjects) -{ - if (!r_3dfloors || sub->sector->CenterFloor() == sub->sector->CenterCeiling()) - return; - - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - - auto frontsector = sub->sector; - auto &ffloors = frontsector->e->XFloor.ffloors; - - // 3D floor floors - for (int i = 0; i < (int)ffloors.Size(); i++) - { - F3DFloor *fakeFloor = ffloors[i]; - F3DFloor *prevFloor = i > 0 ? ffloors[i - 1] : nullptr; - if (!(fakeFloor->flags & FF_EXISTS)) continue; - if (!fakeFloor->model) continue; - if (!(fakeFloor->flags & FF_RENDERPLANES)) continue; - if (fakeFloor->alpha == 0) continue; - if (prevFloor && (prevFloor->flags & fakeFloor->flags & FF_SWIMMABLE)) continue; - - double fakeHeight = fakeFloor->top.plane->ZatPoint(frontsector->centerspot); - if (fakeFloor->top.plane->isSlope() || (fakeHeight < viewpoint.Pos.Z && fakeHeight > frontsector->floorplane.ZatPoint(frontsector->centerspot))) - { - Render3DFloorPlane plane; - plane.sub = sub; - plane.stencilValue = stencilValue; - plane.ceiling = false; - plane.fakeFloor = fakeFloor; - plane.Additive = !!(fakeFloor->flags & FF_ADDITIVETRANS); - if (!plane.Additive && fakeFloor->alpha == 255) - { - plane.Masked = false; - plane.Alpha = 1.0; - } - else - { - plane.Masked = true; - plane.Alpha = fakeFloor->alpha / 255.0; - } - - if (!plane.Masked) - plane.Render(thread); - else - translucentObjects.push_back(thread->FrameMemory->NewObject(plane, subsectorDepth)); - } - } - - // 3D floor ceilings - for (int i = 0; i < (int)ffloors.Size(); i++) - { - F3DFloor *fakeFloor = ffloors[i]; - F3DFloor *prevFloor = i > 0 ? ffloors[i - 1] : nullptr; - if (!(fakeFloor->flags & FF_EXISTS)) continue; - if (!fakeFloor->model) continue; - if (!(fakeFloor->flags & FF_RENDERPLANES)) continue; - if (fakeFloor->alpha == 0) continue; - if (prevFloor && (prevFloor->flags & fakeFloor->flags & FF_SWIMMABLE)) continue; - - double fakeHeight = fakeFloor->bottom.plane->ZatPoint(frontsector->centerspot); - if (fakeFloor->bottom.plane->isSlope() || (fakeHeight > viewpoint.Pos.Z && fakeHeight < frontsector->ceilingplane.ZatPoint(frontsector->centerspot))) - { - Render3DFloorPlane plane; - plane.sub = sub; - plane.stencilValue = stencilValue; - plane.ceiling = true; - plane.fakeFloor = fakeFloor; - plane.Additive = !!(fakeFloor->flags & FF_ADDITIVETRANS); - if (!plane.Additive && fakeFloor->alpha == 255) - { - plane.Masked = false; - plane.Alpha = 1.0; - } - else - { - plane.Masked = true; - plane.Alpha = fakeFloor->alpha / 255.0; - } - - if (!plane.Masked) - plane.Render(thread); - else - translucentObjects.push_back(thread->FrameMemory->NewObject(plane, subsectorDepth)); - } - } -} - -void Render3DFloorPlane::Render(PolyRenderThread *thread) -{ - FTextureID picnum = ceiling ? *fakeFloor->bottom.texture : *fakeFloor->top.texture; - auto tex = TexMan.GetPalettedTexture(picnum, true); - if (!tex->isValid()) - return; - - PolyCameraLight *cameraLight = PolyCameraLight::Instance(); - - int lightlevel = 255; - bool foggy = false; - if (cameraLight->FixedLightLevel() < 0 && sub->sector->e->XFloor.lightlist.Size()) - { - lightlist_t *light = P_GetPlaneLight(sub->sector, ceiling ? fakeFloor->bottom.plane : fakeFloor->top.plane, ceiling); - //basecolormap = light->extra_colormap; - lightlevel = *light->p_lightlevel; - } - - int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4; - lightlevel = clamp(lightlevel + actualextralight, 0, 255); - - PolyPlaneUVTransform xform(ceiling ? fakeFloor->top.model->planes[sector_t::ceiling].xform : fakeFloor->top.model->planes[sector_t::floor].xform, tex->GetSoftwareTexture()); - - TriVertex *vertices = thread->FrameMemory->AllocMemory(sub->numlines); - if (ceiling) - { - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - vertices[sub->numlines - 1 - i] = xform.GetVertex(line->v1, fakeFloor->bottom.plane->ZatPoint(line->v1)); - } - } - else - { - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - vertices[i] = xform.GetVertex(line->v1, fakeFloor->top.plane->ZatPoint(line->v1)); - } - } - - PolyDrawArgs args; - args.SetLight(GetColorTable(sub->sector->Colormap), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), false); - if (!Masked) - { - args.SetStyle(TriBlendMode::Opaque); - args.SetStencilTestValue(stencilValue); - args.SetWriteStencil(true, stencilValue + 1); - } - else - { - args.SetStyle(Additive ? TriBlendMode::Add : TriBlendMode::Normal, MIN(Alpha, 1.0)); - args.SetStencilTestValue(stencilValue + 1); - args.SetWriteStencil(false); - args.SetDepthTest(true); - args.SetWriteDepth(true); - } - args.SetTexture(tex->GetSoftwareTexture(), DefaultRenderStyle()); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, sub->numlines, PolyDrawMode::TriangleFan); -} diff --git a/src/rendering/polyrenderer/scene/poly_plane.h b/src/rendering/polyrenderer/scene/poly_plane.h deleted file mode 100644 index 74c6c79565..0000000000 --- a/src/rendering/polyrenderer/scene/poly_plane.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include "polyrenderer/drawers/poly_triangle.h" - -class PolyDrawSectorPortal; - -class PolyPlaneUVTransform -{ -public: - PolyPlaneUVTransform(const FTransform &transform, FSoftwareTexture *tex); - - TriVertex GetVertex(vertex_t *v1, double height) const - { - TriVertex v; - v.x = (float)v1->fX(); - v.y = (float)v1->fY(); - v.z = (float)height; - v.w = 1.0f; - v.u = GetU(v.x, v.y); - v.v = GetV(v.x, v.y); - return v; - } - -private: - float GetU(float x, float y) const { return (xOffs + x * cosine - y * sine) * xscale; } - float GetV(float x, float y) const { return (yOffs - x * sine - y * cosine) * yscale; } - - float xscale; - float yscale; - float cosine; - float sine; - float xOffs, yOffs; -}; - -class RenderPolyPlane -{ -public: - static void RenderPlanes(PolyRenderThread *thread, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector> §orPortals, size_t sectorPortalsStart); - -private: - void Render(PolyRenderThread *thread, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector> §orPortals, size_t sectorPortalsStart); - - void RenderPortal(PolyRenderThread *thread, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector> §orPortals, size_t sectorPortalsStart); - void RenderNormal(PolyRenderThread *thread, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight); - - void RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight); - - void SetLightLevel(PolyRenderThread *thread, PolyDrawArgs &args, const PolyTransferHeights &fakeflat, bool ceiling); - void SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling); - - TriVertex *CreatePlaneVertices(PolyRenderThread *thread, subsector_t *sub, const PolyPlaneUVTransform &transform, const secplane_t &plane); - TriVertex *CreateSkyPlaneVertices(PolyRenderThread *thread, subsector_t *sub, double skyHeight); - - static TriVertex GetSkyVertex(vertex_t *v, double height) { return { (float)v->fX(), (float)v->fY(), (float)height, 1.0f, 0.0f, 0.0f }; } -}; - -class Render3DFloorPlane -{ -public: - static void RenderPlanes(PolyRenderThread *thread, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector &translucentObjects); - - void Render(PolyRenderThread *thread); - - subsector_t *sub = nullptr; - uint32_t stencilValue = 0; - bool ceiling = false; - F3DFloor *fakeFloor = nullptr; - bool Masked = false; - 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(PolyRenderThread *thread) override - { - plane.Render(thread); - } - - Render3DFloorPlane plane; -}; diff --git a/src/rendering/polyrenderer/scene/poly_playersprite.cpp b/src/rendering/polyrenderer/scene/poly_playersprite.cpp deleted file mode 100644 index 3cf04a53d5..0000000000 --- a/src/rendering/polyrenderer/scene/poly_playersprite.cpp +++ /dev/null @@ -1,548 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "sbar.h" -#include "r_data/r_translate.h" -#include "poly_playersprite.h" -#include "polyrenderer/poly_renderer.h" -#include "d_player.h" -#include "polyrenderer/scene/poly_light.h" -#include "polyrenderer/scene/poly_model.h" - -EXTERN_CVAR(Bool, r_drawplayersprites) -EXTERN_CVAR(Bool, r_deathcamera) -EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor) -extern bool r_modelscene; - -void RenderPolyPlayerSprites::Render(PolyRenderThread *thread) -{ - // This code cannot be moved directly to RenderRemainingSprites because the engine - // draws the canvas textures between this call and the final call to RenderRemainingSprites.. - // - // We also can't move it because the model render code relies on it - - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - - int i; - int lightnum; - DPSprite* psp; - DPSprite* weapon; - sector_t* sec = nullptr; - int floorlight, ceilinglight; - F3DFloor *rover; - - if (!r_drawplayersprites || - !viewpoint.camera || - !viewpoint.camera->player || - (players[consoleplayer].cheats & CF_CHASECAM) || - (r_deathcamera && viewpoint.camera->health <= 0)) - return; - - renderHUDModel = r_modelscene && IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player); - - PolyTransferHeights fakeflat(viewpoint.camera->subsector); - - FDynamicColormap *basecolormap; - PolyCameraLight *cameraLight = PolyCameraLight::Instance(); - bool nc = !!(viewpoint.camera->Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING); - - if (cameraLight->FixedLightLevel() < 0 && viewpoint.sector->e && viewpoint.sector->e->XFloor.lightlist.Size()) - { - for (i = viewpoint.sector->e->XFloor.lightlist.Size() - 1; i >= 0; i--) - { - if (viewpoint.Pos.Z <= viewpoint.sector->e->XFloor.lightlist[i].plane.Zat0()) - { - rover = viewpoint.sector->e->XFloor.lightlist[i].caster; - if (rover) - { - if (rover->flags & FF_DOUBLESHADOW && viewpoint.Pos.Z <= rover->bottom.plane->Zat0()) - break; - sec = rover->model; - if (rover->flags & FF_FADEWALLS) - basecolormap = GetSpriteColorTable(sec->Colormap, sec->SpecialColors[sector_t::sprites], nc); - else - basecolormap = GetSpriteColorTable(viewpoint.sector->e->XFloor.lightlist[i].extra_colormap, sec->SpecialColors[sector_t::sprites], nc); - } - break; - } - } - if (!sec) - { - sec = viewpoint.sector; - basecolormap = GetSpriteColorTable(sec->Colormap, sec->SpecialColors[sector_t::sprites], nc); - } - floorlight = ceilinglight = sec->lightlevel; - } - else - { // This used to use camera->Sector but due to interpolation that can be incorrect - // when the interpolated viewpoint is in a different sector than the camera. - - sec = fakeflat.FrontSector; - floorlight = fakeflat.FloorLightLevel; - ceilinglight = fakeflat.CeilingLightLevel; - - // [RH] set basecolormap - basecolormap = GetSpriteColorTable(sec->Colormap, sec->SpecialColors[sector_t::sprites], nc); - } - - // [RH] set foggy flag - bool foggy = (PolyRenderer::Instance()->Level->fadeto || basecolormap->Fade || (PolyRenderer::Instance()->Level->flags & LEVEL_HASFADETABLE)); - - // get light level - lightnum = ((floorlight + ceilinglight) >> 1) + (foggy ? 0 : viewpoint.extralight << 4); - int spriteshade = LightLevelToShade(lightnum, foggy) - 24 * FRACUNIT; - - if (viewpoint.camera->player != nullptr) - { - double wx, wy; - float bobx, boby; - - P_BobWeapon(viewpoint.camera->player, &bobx, &boby, viewpoint.TicFrac); - - // Interpolate the main weapon layer once so as to be able to add it to other layers. - if ((weapon = viewpoint.camera->player->FindPSprite(PSP_WEAPON)) != nullptr) - { - if (weapon->firstTic) - { - wx = weapon->x; - wy = weapon->y; - } - else - { - wx = weapon->oldx + (weapon->x - weapon->oldx) * viewpoint.TicFrac; - wy = weapon->oldy + (weapon->y - weapon->oldy) * viewpoint.TicFrac; - } - } - else - { - wx = 0; - wy = 0; - } - - // add all active psprites - psp = viewpoint.camera->player->psprites; - while (psp) - { - // [RH] Don't draw the targeter's crosshair if the player already has a crosshair set. - // It's possible this psprite's caller is now null but the layer itself hasn't been destroyed - // because it didn't tick yet (if we typed 'take all' while in the console for example). - // In this case let's simply not draw it to avoid crashing. - - if ((psp->GetID() != PSP_TARGETCENTER || CrosshairImage == nullptr) && psp->GetCaller() != nullptr) - { - RenderSprite(thread, psp, viewpoint.camera, bobx, boby, wx, wy, viewpoint.TicFrac, spriteshade, basecolormap, foggy); - } - - psp = psp->GetNext(); - } - } -} - -void RenderPolyPlayerSprites::RenderRemainingSprites() -{ - for (const PolyHWAccelPlayerSprite &sprite : AcceleratedSprites) - { - screen->DrawTexture(sprite.pic->GetTexture(), - viewwindowx + sprite.x1, - viewwindowy + viewheight / 2 - sprite.texturemid * sprite.yscale - 0.5, - DTA_DestWidthF, FIXED2DBL(sprite.pic->GetWidth() * sprite.xscale), - DTA_DestHeightF, sprite.pic->GetHeight() * sprite.yscale, - DTA_TranslationIndex, sprite.Translation, - DTA_FlipX, sprite.flip, - DTA_TopOffset, 0, - DTA_LeftOffset, 0, - DTA_ClipLeft, viewwindowx, - DTA_ClipTop, viewwindowy, - DTA_ClipRight, viewwindowx + viewwidth, - DTA_ClipBottom, viewwindowy + viewheight, - DTA_Alpha, sprite.Alpha, - DTA_RenderStyle, sprite.RenderStyle, - DTA_FillColor, sprite.FillColor, - DTA_SpecialColormap, sprite.special, - DTA_ColorOverlay, sprite.overlay.d, - DTA_Color, sprite.LightColor | 0xff000000, // the color here does not have a valid alpha component. - DTA_Desaturate, sprite.Desaturate, - TAG_DONE); - } - - AcceleratedSprites.Clear(); -} - -void RenderPolyPlayerSprites::RenderSprite(PolyRenderThread *thread, DPSprite *pspr, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac, int spriteshade, FDynamicColormap *basecolormap, bool foggy) -{ - double tx; - int x1; - int x2; - double sx, sy; - spritedef_t* sprdef; - spriteframe_t* sprframe; - FTextureID picnum; - uint16_t flip; - FTexture* ttex; - FSoftwareTexture* tex; - bool noaccel; - double alpha = owner->Alpha; - - // decide which patch to use - if ((unsigned)pspr->GetSprite() >= (unsigned)sprites.Size()) - { - DPrintf(DMSG_ERROR, "R_DrawPSprite: invalid sprite number %i\n", pspr->GetSprite()); - return; - } - sprdef = &sprites[pspr->GetSprite()]; - if (pspr->GetFrame() >= sprdef->numframes) - { - DPrintf(DMSG_ERROR, "R_DrawPSprite: invalid sprite frame %i : %i\n", pspr->GetSprite(), pspr->GetFrame()); - return; - } - - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - const auto &viewwindow = PolyRenderer::Instance()->Viewwindow; - DCanvas *renderTarget = PolyRenderer::Instance()->RenderTarget; - - // Force it to use software rendering when drawing to a canvas texture. - bool renderToCanvas = PolyRenderer::Instance()->RenderToCanvas; - - sprframe = &SpriteFrames[sprdef->spriteframes + pspr->GetFrame()]; - - picnum = sprframe->Texture[0]; - flip = sprframe->Flip & 1; - ttex = TexMan.GetTexture(picnum); - - if (!ttex->isValid()) - return; - - tex = ttex->GetSoftwareTexture(); - - if (pspr->firstTic) - { // Can't interpolate the first tic. - pspr->firstTic = false; - pspr->oldx = pspr->x; - pspr->oldy = pspr->y; - } - - sx = pspr->oldx + (pspr->x - pspr->oldx) * ticfrac; - sy = pspr->oldy + (pspr->y - pspr->oldy) * ticfrac + WEAPON_FUDGE_Y; - - if (pspr->Flags & PSPF_ADDBOB) - { - sx += (pspr->Flags & PSPF_MIRROR) ? -bobx : bobx; - sy += boby; - } - - if (pspr->Flags & PSPF_ADDWEAPON && pspr->GetID() != PSP_WEAPON) - { - sx += wx; - sy += wy; - } - - if (renderHUDModel) - { - PolyRenderHUDModel(thread, PolyRenderer::Instance()->Scene.CurrentViewpoint->WorldToClip, 1, pspr, (float)sx, (float)sy); - return; - } - - double yaspectMul = 1.2 * ((double)SCREENHEIGHT / SCREENWIDTH) * r_viewwindow.WidescreenRatio; - - double pspritexscale = viewwindow.centerxwide / 160.0; - double pspriteyscale = pspritexscale * yaspectMul; - double pspritexiscale = 1 / pspritexscale; - - int tleft = tex->GetScaledLeftOffsetPo(); - int twidth = tex->GetScaledWidth(); - - // calculate edges of the shape - //tx = sx - BASEXCENTER; - tx = (pspr->Flags & PSPF_MIRROR) ? ((BASEXCENTER - twidth) - (sx - tleft)) : ((sx - BASEXCENTER) - tleft); - - x1 = xs_RoundToInt(viewwindow.centerx + tx * pspritexscale); - - // off the right side - if (x1 > viewwidth) - return; - - tx += twidth; - x2 = xs_RoundToInt(viewwindow.centerx + tx * pspritexscale); - - // off the left side - if (x2 <= 0) - return; - - // store information in a vissprite - PolyNoAccelPlayerSprite vis; - - vis.renderflags = owner->renderflags; - - vis.texturemid = (BASEYCENTER - sy) * tex->GetScale().Y + tex->GetTopOffsetPo(); - - if (viewpoint.camera->player && (renderToCanvas || - viewheight == renderTarget->GetHeight() || - (renderTarget->GetWidth() > (BASEXCENTER * 2)))) - { // Adjust PSprite for fullscreen views - vis.texturemid -= pspr->GetYAdjust(renderToCanvas || viewheight == renderTarget->GetHeight()); - } - if (pspr->GetID() < PSP_TARGETCENTER) - { // Move the weapon down for 1280x1024. - vis.texturemid -= AspectPspriteOffset(viewwindow.WidescreenRatio); - } - vis.x1 = x1 < 0 ? 0 : x1; - vis.x2 = x2 >= viewwidth ? viewwidth : x2; - vis.xscale = FLOAT2FIXED(pspritexscale / tex->GetScale().X); - vis.yscale = float(pspriteyscale / tex->GetScale().Y); - vis.pic = tex; - - // If flip is used, provided that it's not already flipped (that would just invert itself) - // (It's an XOR...) - if (!(flip) != !(pspr->Flags & PSPF_FLIP)) - { - vis.xiscale = -FLOAT2FIXED(pspritexiscale * tex->GetScale().X); - vis.startfrac = (tex->GetWidth() << FRACBITS) - 1; - } - else - { - vis.xiscale = FLOAT2FIXED(pspritexiscale * tex->GetScale().X); - vis.startfrac = 0; - } - - if (vis.x1 > x1) - vis.startfrac += vis.xiscale*(vis.x1 - x1); - - noaccel = false; - FDynamicColormap *colormap_to_use = nullptr; - if (pspr->GetID() < PSP_TARGETCENTER) - { - auto rs = pspr->GetRenderStyle(owner->RenderStyle, owner->Alpha); - vis.RenderStyle = rs.first; - vis.Alpha = rs.second; - - if (!vis.RenderStyle.IsVisible(vis.Alpha)) - return; - - //----------------------------------------------------------------------------- - - // The software renderer cannot invert the source without inverting the overlay - // too. That means if the source is inverted, we need to do the reverse of what - // the invert overlay flag says to do. - bool invertcolormap = (vis.RenderStyle.Flags & STYLEF_InvertOverlay) != 0; - - if (vis.RenderStyle.Flags & STYLEF_InvertSource) - { - invertcolormap = !invertcolormap; - } - - const FState* const psprState = pspr->GetState(); - bool fullbright = !foggy && (psprState == nullptr ? false : psprState->GetFullbright()); - bool fadeToBlack = (vis.RenderStyle.Flags & STYLEF_FadeToBlack) != 0; - - vis.Light.SetColormap(0, spriteshade, basecolormap, fullbright, invertcolormap, fadeToBlack); - - colormap_to_use = (FDynamicColormap*)vis.Light.BaseColormap; - - if (viewpoint.camera->Inventory != nullptr) - { - visstyle_t visstyle; - visstyle.Alpha = vis.Alpha; - visstyle.RenderStyle = STYLE_Count; - visstyle.Invert = false; - - viewpoint.camera->Inventory->AlterWeaponSprite(&visstyle); - - if (!(pspr->Flags & PSPF_FORCEALPHA)) vis.Alpha = visstyle.Alpha; - - if (visstyle.RenderStyle != STYLE_Count && !(pspr->Flags & PSPF_FORCESTYLE)) - { - vis.RenderStyle = visstyle.RenderStyle; - } - - if (visstyle.Invert) - { - vis.Light.BaseColormap = &SpecialSWColormaps[INVERSECOLORMAP]; - vis.Light.ColormapNum = 0; - noaccel = true; - } - } - // If drawing with a BOOM colormap, disable acceleration. - if (vis.Light.BaseColormap == &NormalLight && NormalLight.Maps != realcolormaps.Maps) - { - noaccel = true; - } -#if 0 - // The HW 2D drawer should be able to handle this without problems - // If the main colormap has fixed lights, and this sprite is being drawn with that - // colormap, disable acceleration so that the lights can remain fixed. - PolyCameraLight *cameraLight = PolyCameraLight::Instance(); - if (!noaccel && cameraLight->ShaderColormap() == nullptr && - NormalLightHasFixedLights && vis.Light.BaseColormap == &NormalLight && - vis.pic->UseBasePalette()) - { - noaccel = true; - } -#endif - } - else - { - colormap_to_use = basecolormap; - - vis.Light.BaseColormap = basecolormap; - vis.Light.ColormapNum = 0; - } - - // Check for hardware-assisted 2D. If it's available, and this sprite is not - // fuzzy, don't draw it until after the switch to 2D mode. - if (!noaccel && !renderToCanvas) - { - FRenderStyle style = vis.RenderStyle; - style.CheckFuzz(); - if (style.BlendOp != STYLEOP_Fuzz) - { - PolyHWAccelPlayerSprite accelSprite; - - accelSprite.pic = vis.pic; - accelSprite.texturemid = vis.texturemid; - accelSprite.yscale = vis.yscale; - accelSprite.xscale = vis.xscale; - - accelSprite.Alpha = vis.Alpha; - accelSprite.RenderStyle = vis.RenderStyle; - accelSprite.Translation = vis.Translation; - accelSprite.FillColor = vis.FillColor; - - accelSprite.basecolormap = colormap_to_use; - accelSprite.x1 = x1; - accelSprite.flip = vis.xiscale < 0; - - if (vis.Light.BaseColormap >= &SpecialSWColormaps[0] && - vis.Light.BaseColormap < &SpecialSWColormaps[SpecialColormaps.Size()]) - { - accelSprite.special = &SpecialColormaps[vis.Light.BaseColormap - &SpecialSWColormaps[0]]; - } - else if (PolyCameraLight::Instance()->ShaderColormap()) - { - accelSprite.special = PolyCameraLight::Instance()->ShaderColormap(); - } - else - { - accelSprite.overlay = colormap_to_use->Fade; - accelSprite.overlay.a = uint8_t(vis.Light.ColormapNum * 255 / NUMCOLORMAPS); - accelSprite.LightColor = colormap_to_use->Color; - accelSprite.Desaturate = (uint8_t)clamp(colormap_to_use->Desaturate, 0, 255); - } - - AcceleratedSprites.Push(accelSprite); - return; - } - } - - vis.Render(thread); -} - -fixed_t RenderPolyPlayerSprites::LightLevelToShade(int lightlevel, bool foggy) -{ - bool nolightfade = !foggy && ((PolyRenderer::Instance()->Level->flags3 & LEVEL3_NOLIGHTFADE)); - if (nolightfade) - { - return (MAX(255 - lightlevel, 0) * NUMCOLORMAPS) << (FRACBITS - 8); - } - else - { - // Convert a light level into an unbounded colormap index (shade). Result is - // fixed point. Why the +12? I wish I knew, but experimentation indicates it - // is necessary in order to best reproduce Doom's original lighting. - return (NUMCOLORMAPS * 2 * FRACUNIT) - ((lightlevel + 12) * (FRACUNIT*NUMCOLORMAPS / 128)); - } -} - -///////////////////////////////////////////////////////////////////////// - -void PolyNoAccelPlayerSprite::Render(PolyRenderThread *thread) -{ - if (xscale == 0 || fabs(yscale) < (1.0f / 32000.0f)) - { // scaled to 0; can't see - return; - } - - RectDrawArgs args; - args.SetStyle(RenderStyle, Alpha, FillColor, Translation, pic, false); - args.SetLight(Light.BaseColormap, 255 - (Light.ColormapNum << 3)); - - double centerY = viewheight / 2; - double y1, y2; - if (renderflags & RF_YFLIP) - { - y1 = centerY + (texturemid - pic->GetHeight()) * (-yscale); - y2 = y1 + pic->GetHeight() * (-yscale); - } - else - { - y1 = centerY - texturemid * yscale; - y2 = y1 + pic->GetHeight() * yscale; - } - args.Draw(thread, viewwindowx + x1, viewwindowx + x2, viewwindowy + y1, viewwindowy + y2, 0.0f, 1.0f, 0.0f, 1.0f); -} - -///////////////////////////////////////////////////////////////////////////// - -void PolyColormapLight::SetColormap(double visibility, int shade, FDynamicColormap *basecolormap, bool fullbright, bool invertColormap, bool fadeToBlack) -{ - if (fadeToBlack) - { - if (invertColormap) // Fade to white - { - basecolormap = GetSpecialLights(basecolormap->Color, MAKERGB(255, 255, 255), basecolormap->Desaturate); - invertColormap = false; - } - else // Fade to black - { - basecolormap = GetSpecialLights(basecolormap->Color, MAKERGB(0, 0, 0), basecolormap->Desaturate); - } - } - - if (invertColormap) - { - basecolormap = GetSpecialLights(basecolormap->Color, basecolormap->Fade.InverseColor(), basecolormap->Desaturate); - } - - PolyCameraLight *cameraLight = PolyCameraLight::Instance(); - if (cameraLight->FixedColormap()) - { - BaseColormap = cameraLight->FixedColormap(); - ColormapNum = 0; - } - else if (cameraLight->FixedLightLevel() >= 0) - { - BaseColormap = (r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap; - ColormapNum = cameraLight->FixedLightLevel() >> COLORMAPSHIFT; - } - else if (fullbright) - { - BaseColormap = (r_fullbrightignoresectorcolor) ? &FullNormalLight : basecolormap; - ColormapNum = 0; - } - else - { - BaseColormap = basecolormap; - ColormapNum = GETPALOOKUP(visibility, shade); - } -} diff --git a/src/rendering/polyrenderer/scene/poly_playersprite.h b/src/rendering/polyrenderer/scene/poly_playersprite.h deleted file mode 100644 index cba6cda521..0000000000 --- a/src/rendering/polyrenderer/scene/poly_playersprite.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include "r_defs.h" - -class DPSprite; -struct FDynamicColormap; - -class PolyColormapLight -{ -public: - int ColormapNum = 0; - FSWColormap *BaseColormap = nullptr; - - void SetColormap(double visibility, int shade, FDynamicColormap *basecolormap, bool fullbright, bool invertColormap, bool fadeToBlack); -}; - -class PolyNoAccelPlayerSprite -{ -public: - short x1 = 0; - short x2 = 0; - - double texturemid = 0.0; - - fixed_t xscale = 0; - float yscale = 0.0f; - - FSoftwareTexture *pic = nullptr; - - fixed_t xiscale = 0; - fixed_t startfrac = 0; - - float Alpha = 0.0f; - FRenderStyle RenderStyle; - uint32_t Translation = 0; - uint32_t FillColor = 0; - - PolyColormapLight Light; - - short renderflags = 0; - - void Render(PolyRenderThread *thread); -}; - -class PolyHWAccelPlayerSprite -{ -public: - FSoftwareTexture *pic = nullptr; - double texturemid = 0.0; - float yscale = 0.0f; - fixed_t xscale = 0; - - float Alpha = 0.0f; - FRenderStyle RenderStyle; - uint32_t Translation = 0; - uint32_t FillColor = 0; - - FDynamicColormap *basecolormap = nullptr; - int x1 = 0; - - bool flip = false; - FSpecialColormap *special = nullptr; - PalEntry overlay = 0; - PalEntry LightColor = 0xffffffff; - uint8_t Desaturate = 0; -}; - -class RenderPolyPlayerSprites -{ -public: - void Render(PolyRenderThread *thread); - void RenderRemainingSprites(); - -private: - void RenderSprite(PolyRenderThread *thread, DPSprite *pspr, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac, int spriteshade, FDynamicColormap *basecolormap, bool foggy); - static fixed_t LightLevelToShade(int lightlevel, bool foggy); - - enum { BASEXCENTER = 160 }; - enum { BASEYCENTER = 100 }; - - TArray AcceleratedSprites; - sector_t tempsec; - bool renderHUDModel = false; -}; diff --git a/src/rendering/polyrenderer/scene/poly_portal.cpp b/src/rendering/polyrenderer/scene/poly_portal.cpp deleted file mode 100644 index c70d659ecb..0000000000 --- a/src/rendering/polyrenderer/scene/poly_portal.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "p_maputl.h" -#include "sbar.h" -#include "g_levellocals.h" -#include "r_data/r_translate.h" -#include "poly_portal.h" -#include "polyrenderer/poly_renderer.h" -#include "polyrenderer/scene/poly_light.h" -#include "polyrenderer/scene/poly_scene.h" - -///////////////////////////////////////////////////////////////////////////// - -PolyDrawSectorPortal::PolyDrawSectorPortal(FSectorPortal *portal, bool ceiling) : Portal(portal), Ceiling(ceiling) -{ - StencilValue = PolyRenderer::Instance()->GetNextStencilValue(); -} - -void PolyDrawSectorPortal::Render(int portalDepth) -{ - if (Portal->mType == PORTS_HORIZON || Portal->mType == PORTS_PLANE) - return; - - /*angle_t angle1 = PolyCull::PointToPseudoAngle(v1->fX(), v1->fY()); - angle_t angle2 = PolyCull::PointToPseudoAngle(v2->fX(), v2->fY()); - Segments.clear(); - Segments.push_back({ angle1, angle2 });*/ - - SaveGlobals(); - - PortalViewpoint = PolyRenderer::Instance()->SetupPerspectiveMatrix(); - PortalViewpoint.StencilValue = StencilValue; - PortalViewpoint.PortalDepth = portalDepth; - PortalViewpoint.PortalEnterSector = Portal->mDestination; - - PolyRenderer::Instance()->Scene.Render(&PortalViewpoint); - - RestoreGlobals(); -} - -void PolyDrawSectorPortal::SaveGlobals() -{ - auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - const auto &viewwindow = PolyRenderer::Instance()->Viewwindow; - - SavedViewpoint = viewpoint; - SavedInvisibility = viewpoint.camera ? (viewpoint.camera->renderflags & RF_INVISIBLE) == RF_INVISIBLE : false; - - if (Portal->mType == PORTS_SKYVIEWPOINT) - { - // Don't let gun flashes brighten the sky box - AActor *sky = Portal->mSkybox; - viewpoint.extralight = 0; - //PolyRenderer::Instance()->Light.SetVisibility(sky->args[0] * 0.25f); - viewpoint.Pos = sky->InterpolatedPosition(viewpoint.TicFrac); - viewpoint.Angles.Yaw = SavedViewpoint.Angles.Yaw + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * viewpoint.TicFrac); - } - else //if (Portal->mType == PORTS_STACKEDSECTORTHING || Portal->mType == PORTS_PORTAL || Portal->mType == PORTS_LINKEDPORTAL) - { - //extralight = pl->extralight; - //SetVisibility(pl->visibility); - viewpoint.Pos.X += Portal->mDisplacement.X; - viewpoint.Pos.Y += Portal->mDisplacement.Y; - } - - viewpoint.camera = nullptr; - viewpoint.sector = Portal->mDestination; - viewpoint.SetViewAngle(viewwindow); - - Portal->mFlags |= PORTSF_INSKYBOX; - if (Portal->mPartner > 0) PolyRenderer::Instance()->Level->sectorPortals[Portal->mPartner].mFlags |= PORTSF_INSKYBOX; -} - -void PolyDrawSectorPortal::RestoreGlobals() -{ - Portal->mFlags &= ~PORTSF_INSKYBOX; - if (Portal->mPartner > 0) PolyRenderer::Instance()->Level->sectorPortals[Portal->mPartner].mFlags &= ~PORTSF_INSKYBOX; - - auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - const auto &viewwindow = PolyRenderer::Instance()->Viewwindow; - - viewpoint = SavedViewpoint; - - if (viewpoint.camera) - { - if (SavedInvisibility) - viewpoint.camera->renderflags |= RF_INVISIBLE; - else - viewpoint.camera->renderflags &= ~RF_INVISIBLE; - } - - //PolyRenderer::Instance()->Light.SetVisibility(savedvisibility); - - viewpoint.SetViewAngle(viewwindow); -} - -///////////////////////////////////////////////////////////////////////////// - -PolyDrawLinePortal::PolyDrawLinePortal(FLinePortal *portal) : Portal(portal) -{ - StencilValue = PolyRenderer::Instance()->GetNextStencilValue(); -} - -PolyDrawLinePortal::PolyDrawLinePortal(line_t *mirror) : Mirror(mirror) -{ - StencilValue = PolyRenderer::Instance()->GetNextStencilValue(); -} - -void PolyDrawLinePortal::Render(int portalDepth) -{ - SaveGlobals(); - - // Find portal destination line and make sure it faces the right way - line_t *clipLine = Portal ? Portal->mDestination : Mirror; - DVector2 pt1 = clipLine->v1->fPos() - PolyRenderer::Instance()->Viewpoint.Pos; - DVector2 pt2 = clipLine->v2->fPos() - PolyRenderer::Instance()->Viewpoint.Pos; - bool backfacing = (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0); - - PortalViewpoint = PolyRenderer::Instance()->SetupPerspectiveMatrix(Mirror != nullptr); - PortalViewpoint.StencilValue = StencilValue; - PortalViewpoint.PortalDepth = portalDepth; - PortalViewpoint.PortalEnterLine = clipLine; - PortalViewpoint.PortalEnterSector = backfacing ? clipLine->frontsector : clipLine->backsector; - - PolyRenderer::Instance()->Scene.Render(&PortalViewpoint); - - RestoreGlobals(); -} - -void PolyDrawLinePortal::SaveGlobals() -{ - auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - const auto &viewwindow = PolyRenderer::Instance()->Viewwindow; - - SavedViewpoint = viewpoint; - SavedInvisibility = viewpoint.camera ? (viewpoint.camera->renderflags & RF_INVISIBLE) == RF_INVISIBLE : false; - - if (Mirror) - { - DAngle startang = viewpoint.Angles.Yaw; - DVector3 startpos = viewpoint.Pos; - - vertex_t *v1 = Mirror->v1; - - // Reflect the current view behind the mirror. - if (Mirror->Delta().X == 0) - { // vertical mirror - viewpoint.Pos.X = v1->fX() - startpos.X + v1->fX(); - } - else if (Mirror->Delta().Y == 0) - { // horizontal mirror - viewpoint.Pos.Y = v1->fY() - startpos.Y + v1->fY(); - } - else - { // any mirror - vertex_t *v2 = Mirror->v2; - - double dx = v2->fX() - v1->fX(); - double dy = v2->fY() - v1->fY(); - double x1 = v1->fX(); - double y1 = v1->fY(); - double x = startpos.X; - double y = startpos.Y; - - // the above two cases catch len == 0 - double r = ((x - x1)*dx + (y - y1)*dy) / (dx*dx + dy*dy); - - viewpoint.Pos.X = (x1 + r * dx) * 2 - x; - viewpoint.Pos.Y = (y1 + r * dy) * 2 - y; - } - viewpoint.Angles.Yaw = Mirror->Delta().Angle() * 2 - startang; - - if (viewpoint.camera) - viewpoint.camera->renderflags &= ~RF_INVISIBLE; - } - else - { - auto src = Portal->mOrigin; - auto dst = Portal->mDestination; - - P_TranslatePortalXY(src, viewpoint.Pos.X, viewpoint.Pos.Y); - P_TranslatePortalZ(src, viewpoint.Pos.Z); - P_TranslatePortalAngle(src, viewpoint.Angles.Yaw); - P_TranslatePortalXY(src, viewpoint.Path[0].X, viewpoint.Path[0].Y); - P_TranslatePortalXY(src, viewpoint.Path[1].X, viewpoint.Path[1].Y); - - if (viewpoint.camera && !viewpoint.showviewer) - viewpoint.camera->renderflags |= RF_INVISIBLE; - - /* What is this code trying to do? - if (viewpoint.camera) - { - viewpoint.camera->renderflags &= ~RF_INVISIBLE; - - if (!viewpoint.showviewer && P_PointOnLineSidePrecise(viewpoint.Path[0], dst) != P_PointOnLineSidePrecise(viewpoint.Path[1], dst)) - { - double distp = (viewpoint.Path[0] - viewpoint.Path[1]).Length(); - if (distp > EQUAL_EPSILON) - { - double dist1 = (viewpoint.Pos - viewpoint.Path[0]).Length(); - double dist2 = (viewpoint.Pos - viewpoint.Path[1]).Length(); - - if (dist1 + dist2 < distp + 1) - { - viewpoint.camera->renderflags |= RF_INVISIBLE; - } - } - } - } - */ - } - - viewpoint.camera = nullptr; - viewpoint.sector = viewpoint.ViewLevel->PointInRenderSubsector(viewpoint.Pos)->sector; - - viewpoint.SetViewAngle(viewwindow); -} - -void PolyDrawLinePortal::RestoreGlobals() -{ - auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - const auto &viewwindow = PolyRenderer::Instance()->Viewwindow; - - viewpoint = SavedViewpoint; - - if (viewpoint.camera) - { - if (SavedInvisibility) - viewpoint.camera->renderflags |= RF_INVISIBLE; - else - viewpoint.camera->renderflags &= ~RF_INVISIBLE; - } - - viewpoint.SetViewAngle(viewwindow); -} diff --git a/src/rendering/polyrenderer/scene/poly_portal.h b/src/rendering/polyrenderer/scene/poly_portal.h deleted file mode 100644 index 2c37266f6f..0000000000 --- a/src/rendering/polyrenderer/scene/poly_portal.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include "poly_scene.h" - -struct PolyPortalVertexRange -{ - PolyPortalVertexRange(const TriVertex *vertices, int count) : Vertices(vertices), Count(count) { } - const TriVertex *Vertices; - int Count; -}; - -class PolyPortalSegment -{ -public: - PolyPortalSegment(angle_t start, angle_t end) : Start(start), End(end) { } - angle_t Start, End; -}; - -class PolyDrawSectorPortal -{ -public: - PolyDrawSectorPortal(FSectorPortal *portal, bool ceiling); - - void Render(int portalDepth); - - FSectorPortal *Portal = nullptr; - uint32_t StencilValue = 0; - std::vector Shape; - -private: - void SaveGlobals(); - void RestoreGlobals(); - - bool Ceiling; - PolyPortalViewpoint PortalViewpoint; - - FRenderViewpoint SavedViewpoint; - bool SavedInvisibility; -}; - -class PolyDrawLinePortal -{ -public: - PolyDrawLinePortal(FLinePortal *portal); - PolyDrawLinePortal(line_t *mirror); - - void Render(int portalDepth); - - FLinePortal *Portal = nullptr; - line_t *Mirror = nullptr; - uint32_t StencilValue = 0; - std::vector Shape; - -private: - void SaveGlobals(); - void RestoreGlobals(); - - PolyPortalViewpoint PortalViewpoint; - - FRenderViewpoint SavedViewpoint; - bool SavedInvisibility; -}; diff --git a/src/rendering/polyrenderer/scene/poly_scene.cpp b/src/rendering/polyrenderer/scene/poly_scene.cpp deleted file mode 100644 index ec21c0e15f..0000000000 --- a/src/rendering/polyrenderer/scene/poly_scene.cpp +++ /dev/null @@ -1,594 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "p_maputl.h" -#include "sbar.h" -#include "r_data/r_translate.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) - -extern double model_distance_cull; - -///////////////////////////////////////////////////////////////////////////// - -RenderPolyScene::RenderPolyScene() -{ -} - -RenderPolyScene::~RenderPolyScene() -{ -} - -void RenderPolyScene::Render(PolyPortalViewpoint *viewpoint) -{ - PolyPortalViewpoint *oldviewpoint = CurrentViewpoint; - CurrentViewpoint = viewpoint; - - PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread(); - - CurrentViewpoint->ObjectsStart = thread->TranslucentObjects.size(); - CurrentViewpoint->SectorPortalsStart = thread->SectorPortals.size(); - CurrentViewpoint->LinePortalsStart = thread->LinePortals.size(); - - PolyCullCycles.Clock(); - Cull.CullScene(CurrentViewpoint->PortalEnterSector, CurrentViewpoint->PortalEnterLine); - PolyCullCycles.Unclock(); - - RenderSectors(); - - PolyMaskedCycles.Clock(); - const auto &rviewpoint = PolyRenderer::Instance()->Viewpoint; - for (uint32_t sectorIndex : Cull.SeenSectors) - { - sector_t *sector = &PolyRenderer::Instance()->Level->sectors[sectorIndex]; - for (AActor *thing = sector->thinglist; thing != nullptr; thing = thing->snext) - { - if (!RenderPolySprite::IsThingCulled(thing)) - { - int spritenum = thing->sprite; - bool isPicnumOverride = thing->picnum.isValid(); - FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); - double distanceSquared = (thing->Pos() - rviewpoint.Pos).LengthSquared(); - if (r_modelscene && modelframe && distanceSquared < model_distance_cull) - { - AddModel(thread, thing, distanceSquared, thing->Pos()); - } - else - { - DVector2 left, right; - if (!RenderPolySprite::GetLine(thing, left, right)) - continue; - AddSprite(thread, thing, distanceSquared, left, right); - } - } - } - } - PolyMaskedCycles.Unclock(); - - CurrentViewpoint->ObjectsEnd = thread->TranslucentObjects.size(); - CurrentViewpoint->SectorPortalsEnd = thread->SectorPortals.size(); - CurrentViewpoint->LinePortalsEnd = thread->LinePortals.size(); - - Skydome.Render(thread, CurrentViewpoint->WorldToView, CurrentViewpoint->WorldToClip); - - RenderPortals(); - RenderTranslucent(); - - CurrentViewpoint = oldviewpoint; -} - -void RenderPolyScene::RenderSectors() -{ - PolyRenderThread *mainthread = PolyRenderer::Instance()->Threads.MainThread(); - - int totalcount = (int)Cull.PvsSubsectors.size(); - uint32_t *subsectors = Cull.PvsSubsectors.data(); - - PolyOpaqueCycles.Clock(); - - PolyRenderer::Instance()->Threads.RenderThreadSlices(totalcount, [&](PolyRenderThread *thread) - { - PolyTriangleDrawer::SetCullCCW(thread->DrawQueue, !CurrentViewpoint->Mirror); - PolyTriangleDrawer::SetTransform(thread->DrawQueue, thread->FrameMemory->NewObject(CurrentViewpoint->WorldToClip), nullptr); - - if (thread != mainthread) - { - thread->TranslucentObjects.clear(); - thread->SectorPortals.clear(); - thread->LinePortals.clear(); - } - - int start = thread->Start; - int end = thread->End; - for (int i = start; i < end; i++) - { - RenderSubsector(thread, &PolyRenderer::Instance()->Level->subsectors[subsectors[i]], i); - } - }, [&](PolyRenderThread *thread) - { - const auto &objects = thread->TranslucentObjects; - mainthread->TranslucentObjects.insert(mainthread->TranslucentObjects.end(), objects.begin(), objects.end()); - }); - - PolyOpaqueCycles.Unclock(); -} - -void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth) -{ - sector_t *frontsector = sub->sector; - auto Level = frontsector->Level; - frontsector->MoreFlags |= SECMF_DRAWN; - - if (sub->polys) - { - if (sub->BSP == nullptr || sub->BSP->bDirty) - { - sub->BuildPolyBSP(); - - // This is done by the GL renderer, but not the sw renderer. No idea what the purpose is.. - for (unsigned i = 0; i < sub->BSP->Segs.Size(); i++) - { - sub->BSP->Segs[i].Subsector = sub; - sub->BSP->Segs[i].PartnerSeg = nullptr; - } - } - - if (sub->BSP->Nodes.Size() == 0) - { - RenderPolySubsector(thread, &sub->BSP->Subsectors[0], subsectorDepth, frontsector); - } - else - { - RenderPolyNode(thread, &sub->BSP->Nodes.Last(), subsectorDepth, frontsector); - } - } - - PolyTransferHeights fakeflat(sub); - - Render3DFloorPlane::RenderPlanes(thread, sub, CurrentViewpoint->StencilValue, subsectorDepth, thread->TranslucentObjects); - RenderPolyPlane::RenderPlanes(thread, fakeflat, CurrentViewpoint->StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, thread->SectorPortals, CurrentViewpoint->SectorPortalsStart); - - for (uint32_t i = 0; i < sub->numlines; i++) - { - if (Cull.IsLineSegVisible(subsectorDepth, i)) - { - seg_t *line = &sub->firstline[i]; - RenderLine(thread, sub, line, fakeflat.FrontSector, subsectorDepth); - } - } - - int subsectorIndex = sub->Index(); - for (int i = Level->ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Level->Particles[i].snext) - { - particle_t *particle = &Level->Particles[i]; - thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(particle, sub, subsectorDepth, CurrentViewpoint->StencilValue)); - } -} - -void RenderPolyScene::RenderPolyNode(PolyRenderThread *thread, void *node, uint32_t subsectorDepth, sector_t *frontsector) -{ - while (!((size_t)node & 1)) // Keep going until found a subsector - { - node_t *bsp = (node_t *)node; - - // Decide which side the view point is on. - int side = PointOnSide(PolyRenderer::Instance()->Viewpoint.Pos, bsp); - - // Recursively divide front space (toward the viewer). - RenderPolyNode(thread, bsp->children[side], subsectorDepth, frontsector); - - // Possibly divide back space (away from the viewer). - side ^= 1; - - // Don't bother culling on poly objects - //if (!CheckBBox(bsp->bbox[side])) - // return; - - node = bsp->children[side]; - } - - subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); - RenderPolySubsector(thread, sub, subsectorDepth, frontsector); -} - -void RenderPolyScene::RenderPolySubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth, sector_t *frontsector) -{ - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - - for (uint32_t i = 0; i < sub->numlines; i++) - { - seg_t *line = &sub->firstline[i]; - if (line->linedef) - { - // Reject lines not facing viewer - DVector2 pt1 = line->v1->fPos() - viewpoint.Pos; - DVector2 pt2 = line->v2->fPos() - viewpoint.Pos; - if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0) - continue; - - // Tell automap we saw this - if (!PolyRenderer::Instance()->DontMapLines && line->linedef) - { - line->linedef->flags |= ML_MAPPED; - sub->flags |= SSECMF_DRAWN; - } - - RenderPolyWall::RenderLine(thread, line, frontsector, subsectorDepth, CurrentViewpoint->StencilValue, thread->TranslucentObjects, thread->LinePortals, CurrentViewpoint->LinePortalsStart, CurrentViewpoint->PortalEnterLine); - } - } -} - -int RenderPolyScene::PointOnSide(const DVector2 &pos, const node_t *node) -{ - return DMulScale32(FLOAT2FIXED(pos.Y) - node->y, node->dx, node->x - FLOAT2FIXED(pos.X), node->dy) > 0; -} - -void RenderPolyScene::AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right) -{ - if (PolyRenderer::Instance()->Level->nodes.Size() == 0) - { - subsector_t *sub = &PolyRenderer::Instance()->Level->subsectors[0]; - if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff) - thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, 0.0f, 1.0f, CurrentViewpoint->StencilValue)); - } - else - { - AddSprite(thread, thing, sortDistance, left, right, 0.0, 1.0, PolyRenderer::Instance()->Level->HeadNode()); - } -} - -void RenderPolyScene::AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node) -{ - while (!((size_t)node & 1)) // Keep going until found a subsector - { - node_t *bsp = (node_t *)node; - - DVector2 planePos(FIXED2DBL(bsp->x), FIXED2DBL(bsp->y)); - DVector2 planeNormal = DVector2(FIXED2DBL(-bsp->dy), FIXED2DBL(bsp->dx)); - double planeD = planeNormal | planePos; - - int sideLeft = (left | planeNormal) > planeD; - int sideRight = (right | planeNormal) > planeD; - - if (sideLeft != sideRight) - { - double dotLeft = planeNormal | left; - double dotRight = planeNormal | right; - double t = (planeD - dotLeft) / (dotRight - dotLeft); - - DVector2 mid = left * (1.0 - t) + right * t; - double tmid = t1 * (1.0 - t) + t2 * t; - - AddSprite(thread, thing, sortDistance, mid, right, tmid, t2, bsp->children[sideRight]); - right = mid; - t2 = tmid; - } - node = bsp->children[sideLeft]; - } - - subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); - - if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff) - thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, (float)t1, (float)t2, CurrentViewpoint->StencilValue)); -} - -void RenderPolyScene::AddModel(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 pos) -{ - if (PolyRenderer::Instance()->Level->nodes.Size() == 0) - { - subsector_t *sub = &PolyRenderer::Instance()->Level->subsectors[0]; - if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff) - thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, 0.0f, 1.0f, CurrentViewpoint->StencilValue)); - } - else - { - void *node = PolyRenderer::Instance()->Level->HeadNode(); - - while (!((size_t)node & 1)) // Keep going until found a subsector - { - node_t *bsp = (node_t *)node; - - DVector2 planePos(FIXED2DBL(bsp->x), FIXED2DBL(bsp->y)); - DVector2 planeNormal = DVector2(FIXED2DBL(-bsp->dy), FIXED2DBL(bsp->dx)); - double planeD = planeNormal | planePos; - - int side = (pos | planeNormal) > planeD; - node = bsp->children[side]; - } - - subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); - - if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff) - thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, 0.0f, 1.0f, CurrentViewpoint->StencilValue)); - } -} - -void RenderPolyScene::RenderLine(PolyRenderThread *thread, subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth) -{ - // Tell automap we saw this - if (!PolyRenderer::Instance()->DontMapLines && line->linedef) - { - line->linedef->flags |= ML_MAPPED; - sub->flags |= SSECMF_DRAWN; - } - - // Render 3D floor sides - if (line->sidedef && line->backsector && line->backsector->e && line->backsector->e->XFloor.ffloors.Size()) - { - for (unsigned int i = 0; i < line->backsector->e->XFloor.ffloors.Size(); i++) - { - F3DFloor *fakeFloor = line->backsector->e->XFloor.ffloors[i]; - RenderPolyWall::Render3DFloorLine(thread, line, frontsector, subsectorDepth, CurrentViewpoint->StencilValue, fakeFloor, thread->TranslucentObjects); - } - } - - // Render wall, and update culling info if its an occlusion blocker - RenderPolyWall::RenderLine(thread, line, frontsector, subsectorDepth, CurrentViewpoint->StencilValue, thread->TranslucentObjects, thread->LinePortals, CurrentViewpoint->LinePortalsStart, CurrentViewpoint->PortalEnterLine); -} - -void RenderPolyScene::RenderPortals() -{ - PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread(); - - bool enterPortals = CurrentViewpoint->PortalDepth < r_portal_recursions; - - if (enterPortals) - { - for (size_t i = CurrentViewpoint->SectorPortalsStart; i < CurrentViewpoint->SectorPortalsEnd; i++) - thread->SectorPortals[i]->Render(CurrentViewpoint->PortalDepth + 1); - - for (size_t i = CurrentViewpoint->LinePortalsStart; i < CurrentViewpoint->LinePortalsEnd; i++) - thread->LinePortals[i]->Render(CurrentViewpoint->PortalDepth + 1); - } - - Mat4f *transform = thread->FrameMemory->NewObject(CurrentViewpoint->WorldToClip); - PolyTriangleDrawer::SetCullCCW(thread->DrawQueue, !CurrentViewpoint->Mirror); - PolyTriangleDrawer::SetTransform(thread->DrawQueue, transform, nullptr); - - PolyDrawArgs args; - args.SetWriteColor(!enterPortals); - args.SetDepthTest(false); - - if (!enterPortals) // Fill with black - { - bool foggy = false; - args.SetLight(&NormalLight, 255, PolyRenderer::Instance()->Light.WallGlobVis(foggy), true); - args.SetStyle(TriBlendMode::Fill); - args.SetColor(0, 0); - } - - for (size_t i = CurrentViewpoint->SectorPortalsStart; i < CurrentViewpoint->SectorPortalsEnd; i++) - { - const auto &portal = thread->SectorPortals[i]; - args.SetStencilTestValue(enterPortals ? portal->StencilValue + 1 : portal->StencilValue); - args.SetWriteStencil(true, CurrentViewpoint->StencilValue + 1); - for (const auto &verts : portal->Shape) - { - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); - } - } - - for (size_t i = CurrentViewpoint->LinePortalsStart; i < CurrentViewpoint->LinePortalsEnd; i++) - { - const auto &portal = thread->LinePortals[i]; - args.SetStencilTestValue(enterPortals ? portal->StencilValue + 1 : portal->StencilValue); - args.SetWriteStencil(true, CurrentViewpoint->StencilValue + 1); - for (const auto &verts : portal->Shape) - { - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan); - } - } -} - -void RenderPolyScene::RenderTranslucent() -{ - PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread(); - - Mat4f *transform = thread->FrameMemory->NewObject(CurrentViewpoint->WorldToClip); - PolyTriangleDrawer::SetCullCCW(thread->DrawQueue, !CurrentViewpoint->Mirror); - PolyTriangleDrawer::SetTransform(thread->DrawQueue, transform, nullptr); - - PolyMaskedCycles.Clock(); - - // Draw all translucent objects back to front - std::stable_sort( - thread->TranslucentObjects.begin() + CurrentViewpoint->ObjectsStart, - thread->TranslucentObjects.begin() + CurrentViewpoint->ObjectsEnd, - [](auto a, auto b) { return *a < *b; }); - - auto objects = thread->TranslucentObjects.data(); - for (size_t i = CurrentViewpoint->ObjectsEnd; i > CurrentViewpoint->ObjectsStart; i--) - { - PolyTranslucentObject *obj = objects[i - 1]; - obj->Render(thread); - obj->~PolyTranslucentObject(); - } - - PolyMaskedCycles.Unclock(); -} - -///////////////////////////////////////////////////////////////////////////// - -PolyTransferHeights::PolyTransferHeights(subsector_t *sub) : Subsector(sub) -{ - sector_t *sec = sub->sector; - - // If player's view height is underneath fake floor, lower the - // drawn ceiling to be just under the floor height, and replace - // the drawn floor and ceiling textures, and light PolyRenderer::Instance()->Level->, with - // the control sector's. - // - // Similar for ceiling, only reflected. - - // [RH] allow per-plane lighting - FloorLightLevel = sec->GetFloorLight(); - CeilingLightLevel = sec->GetCeilingLight(); - - FakeSide = PolyWaterFakeSide::Center; - - const sector_t *s = sec->GetHeightSec(); - if (s != nullptr) - { - sector_t *heightsec = PolyRenderer::Instance()->Viewpoint.sector->heightsec; - bool underwater = (heightsec && heightsec->floorplane.PointOnSide(PolyRenderer::Instance()->Viewpoint.Pos) <= 0); - bool doorunderwater = false; - int diffTex = (s->MoreFlags & SECMF_CLIPFAKEPLANES); - - // Replace sector being drawn with a copy to be hacked - tempsec = *sec; - - // Replace floor and ceiling height with control sector's heights. - if (diffTex) - { - if (s->floorplane.CopyPlaneIfValid(&tempsec.floorplane, &sec->ceilingplane)) - { - tempsec.SetTexture(sector_t::floor, s->GetTexture(sector_t::floor), false); - } - else if (s->MoreFlags & SECMF_FAKEFLOORONLY) - { - if (underwater) - { - tempsec.Colormap = s->Colormap; - if (!(s->MoreFlags & SECMF_NOFAKELIGHT)) - { - tempsec.lightlevel = s->lightlevel; - - FloorLightLevel = s->GetFloorLight(); - CeilingLightLevel = s->GetCeilingLight(); - } - FakeSide = PolyWaterFakeSide::BelowFloor; - FrontSector = &tempsec; - return; - } - FrontSector = sec; - return; - } - } - else - { - tempsec.floorplane = s->floorplane; - } - - if (!(s->MoreFlags & SECMF_FAKEFLOORONLY)) - { - if (diffTex) - { - if (s->ceilingplane.CopyPlaneIfValid(&tempsec.ceilingplane, &sec->floorplane)) - { - tempsec.SetTexture(sector_t::ceiling, s->GetTexture(sector_t::ceiling), false); - } - } - else - { - tempsec.ceilingplane = s->ceilingplane; - } - } - - double refceilz = s->ceilingplane.ZatPoint(PolyRenderer::Instance()->Viewpoint.Pos); - double orgceilz = sec->ceilingplane.ZatPoint(PolyRenderer::Instance()->Viewpoint.Pos); - - if (underwater || doorunderwater) - { - tempsec.floorplane = sec->floorplane; - tempsec.ceilingplane = s->floorplane; - tempsec.ceilingplane.FlipVert(); - tempsec.ceilingplane.ChangeHeight(-1 / 65536.); - tempsec.Colormap = s->Colormap; - } - - // killough 11/98: prevent sudden light changes from non-water sectors: - if (underwater || doorunderwater) - { - // head-below-floor hack - tempsec.SetTexture(sector_t::floor, diffTex ? sec->GetTexture(sector_t::floor) : s->GetTexture(sector_t::floor), false); - tempsec.planes[sector_t::floor].xform = s->planes[sector_t::floor].xform; - - tempsec.ceilingplane = s->floorplane; - tempsec.ceilingplane.FlipVert(); - tempsec.ceilingplane.ChangeHeight(-1 / 65536.); - if (s->GetTexture(sector_t::ceiling) == skyflatnum) - { - tempsec.floorplane = tempsec.ceilingplane; - tempsec.floorplane.FlipVert(); - tempsec.floorplane.ChangeHeight(+1 / 65536.); - tempsec.SetTexture(sector_t::ceiling, tempsec.GetTexture(sector_t::floor), false); - tempsec.planes[sector_t::ceiling].xform = tempsec.planes[sector_t::floor].xform; - } - else - { - tempsec.SetTexture(sector_t::ceiling, diffTex ? s->GetTexture(sector_t::floor) : s->GetTexture(sector_t::ceiling), false); - tempsec.planes[sector_t::ceiling].xform = s->planes[sector_t::ceiling].xform; - } - - if (!(s->MoreFlags & SECMF_NOFAKELIGHT)) - { - tempsec.lightlevel = s->lightlevel; - - FloorLightLevel = s->GetFloorLight(); - CeilingLightLevel = s->GetCeilingLight(); - } - FakeSide = PolyWaterFakeSide::BelowFloor; - } - else if (heightsec && heightsec->ceilingplane.PointOnSide(PolyRenderer::Instance()->Viewpoint.Pos) <= 0 && orgceilz > refceilz && !(s->MoreFlags & SECMF_FAKEFLOORONLY)) - { - // Above-ceiling hack - tempsec.ceilingplane = s->ceilingplane; - tempsec.floorplane = s->ceilingplane; - tempsec.floorplane.FlipVert(); - tempsec.floorplane.ChangeHeight(+1 / 65536.); - tempsec.Colormap = s->Colormap; - - tempsec.SetTexture(sector_t::ceiling, diffTex ? sec->GetTexture(sector_t::ceiling) : s->GetTexture(sector_t::ceiling), false); - tempsec.SetTexture(sector_t::floor, s->GetTexture(sector_t::ceiling), false); - tempsec.planes[sector_t::ceiling].xform = tempsec.planes[sector_t::floor].xform = s->planes[sector_t::ceiling].xform; - - if (s->GetTexture(sector_t::floor) != skyflatnum) - { - tempsec.ceilingplane = sec->ceilingplane; - tempsec.SetTexture(sector_t::floor, s->GetTexture(sector_t::floor), false); - tempsec.planes[sector_t::floor].xform = s->planes[sector_t::floor].xform; - } - - if (!(s->MoreFlags & SECMF_NOFAKELIGHT)) - { - tempsec.lightlevel = s->lightlevel; - - FloorLightLevel = s->GetFloorLight(); - CeilingLightLevel = s->GetCeilingLight(); - } - FakeSide = PolyWaterFakeSide::AboveCeiling; - } - sec = &tempsec; - } - FrontSector = sec; -} diff --git a/src/rendering/polyrenderer/scene/poly_scene.h b/src/rendering/polyrenderer/scene/poly_scene.h deleted file mode 100644 index 238116c524..0000000000 --- a/src/rendering/polyrenderer/scene/poly_scene.h +++ /dev/null @@ -1,129 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include -#include -#include -#include -#include "doomdata.h" -#include "r_utility.h" -#include "polyrenderer/drawers/poly_triangle.h" -#include "polyrenderer/math/gpu_types.h" -#include "poly_playersprite.h" -#include "poly_cull.h" -#include "poly_sky.h" - -class PolyTranslucentObject -{ -public: - PolyTranslucentObject(uint32_t subsectorDepth = 0, double distanceSquared = 0.0) : subsectorDepth(subsectorDepth), DistanceSquared(distanceSquared) { } - virtual ~PolyTranslucentObject() { } - - virtual void Render(PolyRenderThread *thread) = 0; - - bool operator<(const PolyTranslucentObject &other) const - { - return subsectorDepth != other.subsectorDepth ? subsectorDepth < other.subsectorDepth : DistanceSquared < other.DistanceSquared; - } - - uint32_t subsectorDepth; - double DistanceSquared; -}; - -class PolyDrawSectorPortal; -class PolyDrawLinePortal; -class PolyPortalSegment; - -class PolyPortalViewpoint -{ -public: - Mat4f WorldToView; - Mat4f WorldToClip; - uint32_t StencilValue = 0; - int PortalDepth = 0; - bool Mirror = false; - - line_t *PortalEnterLine = nullptr; - sector_t *PortalEnterSector = nullptr; - - size_t ObjectsStart = 0; - size_t ObjectsEnd = 0; - size_t SectorPortalsStart = 0; - size_t SectorPortalsEnd = 0; - size_t LinePortalsStart = 0; - size_t LinePortalsEnd = 0; -}; - -// Renders everything from a specific viewpoint -class RenderPolyScene -{ -public: - RenderPolyScene(); - ~RenderPolyScene(); - - void Render(PolyPortalViewpoint *viewpoint); - - static const uint32_t SkySubsectorDepth = 0x7fffffff; - - PolyPortalViewpoint *CurrentViewpoint = nullptr; - -private: - void RenderPortals(); - void RenderTranslucent(); - void RenderSectors(); - void RenderSubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth); - void RenderLine(PolyRenderThread *thread, subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth); - void AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right); - void AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node); - void AddModel(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 pos); - - void RenderPolySubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth, sector_t *frontsector); - void RenderPolyNode(PolyRenderThread *thread, void *node, uint32_t subsectorDepth, sector_t *frontsector); - static int PointOnSide(const DVector2 &pos, const node_t *node); - - PolyCull Cull; - PolySkyDome Skydome; -}; - -enum class PolyWaterFakeSide -{ - Center, - BelowFloor, - AboveCeiling -}; - -class PolyTransferHeights -{ -public: - PolyTransferHeights(subsector_t *sub); - - subsector_t *Subsector = nullptr; - sector_t *FrontSector = nullptr; - PolyWaterFakeSide FakeSide = PolyWaterFakeSide::Center; - int FloorLightLevel = 0; - int CeilingLightLevel = 0; - -private: - sector_t tempsec; -}; diff --git a/src/rendering/polyrenderer/scene/poly_sky.cpp b/src/rendering/polyrenderer/scene/poly_sky.cpp deleted file mode 100644 index 7aa9500f2b..0000000000 --- a/src/rendering/polyrenderer/scene/poly_sky.cpp +++ /dev/null @@ -1,429 +0,0 @@ -/* -** Sky dome rendering -** Copyright(C) 2003-2016 Christoph Oelckers -** All rights reserved. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public License -** along with this program. If not, see http:**www.gnu.org/licenses/ -** -** Loosely based on the JDoom sky and the ZDoomGL 0.66.2 sky. -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "sbar.h" -#include "r_data/r_translate.h" -#include "poly_sky.h" -#include "poly_portal.h" -#include "r_sky.h" // for skyflatnum -#include "g_levellocals.h" -#include "polyrenderer/scene/poly_light.h" - -EXTERN_CVAR(Float, skyoffset) -EXTERN_CVAR(Int, r_skymode) - -PolySkyDome::PolySkyDome() -{ - CreateDome(); -} - -void PolySkyDome::Render(PolyRenderThread *thread, const Mat4f &worldToView, const Mat4f &worldToClip) -{ -#ifdef USE_GL_DOME_MATH - Mat4f modelMatrix = GLSkyMath(); -#else - Mat4f modelMatrix = Mat4f::Identity(); - - PolySkySetup frameSetup; - frameSetup.Update(); - - if (frameSetup != mCurrentSetup) - { - // frontcyl = pixels for full 360 degrees, front texture - // backcyl = pixels for full 360 degrees, back texture - // skymid = Y scaled pixel offset - // sky1pos = unscaled X offset, front - // sky2pos = unscaled X offset, back - // frontpos = scaled X pixel offset (fixed point) - // backpos = scaled X pixel offset (fixed point) - // skyflip = flip X direction - - float scaleBaseV = 1.42f; - float offsetBaseV = 0.25f; - - float scaleFrontU = frameSetup.frontcyl / (float)frameSetup.frontskytex->GetWidth(); - float scaleFrontV = (float)frameSetup.frontskytex->GetScale().Y * scaleBaseV; - float offsetFrontU = (float)((frameSetup.frontpos / 65536.0 + frameSetup.frontcyl / 2) / frameSetup.frontskytex->GetWidth()); - float offsetFrontV = (float)((frameSetup.skymid / frameSetup.frontskytex->GetHeight() + offsetBaseV) * scaleBaseV); - - unsigned int count = mVertices.Size(); - for (unsigned int i = 0; i < count; i++) - { - mVertices[i].u = offsetFrontU + mInitialUV[i].X * scaleFrontU; - mVertices[i].v = offsetFrontV + mInitialUV[i].Y * scaleFrontV; - } - - mCurrentSetup = frameSetup; - } -#endif - - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - Mat4f objectToWorld = Mat4f::Translate((float)viewpoint.Pos.X, (float)viewpoint.Pos.Y, (float)viewpoint.Pos.Z) * modelMatrix; - - int rc = mRows + 1; - - PolyTriangleDrawer::SetTransform(thread->DrawQueue, thread->FrameMemory->NewObject(worldToClip * objectToWorld), nullptr); - - PolyDrawArgs args; - args.SetLight(&NormalLight, 255, PolyRenderer::Instance()->Light.WallGlobVis(false), true); - args.SetStencilTestValue(255); - args.SetWriteStencil(true, 1); - args.SetClipPlane(0, PolyClipPlane(0.0f, 0.0f, 0.0f, 1.0f)); - - RenderCapColorRow(thread, args, mCurrentSetup.frontskytex, 0, false); - RenderCapColorRow(thread, args, mCurrentSetup.frontskytex, rc, true); - - args.SetTexture(mCurrentSetup.frontskytex, DefaultRenderStyle()); - - uint32_t topcapcolor = mCurrentSetup.frontskytex->GetSkyCapColor(false); - uint32_t bottomcapcolor = mCurrentSetup.frontskytex->GetSkyCapColor(true); - uint8_t topcapindex = RGB256k.All[((RPART(topcapcolor) >> 2) << 12) | ((GPART(topcapcolor) >> 2) << 6) | (BPART(topcapcolor) >> 2)]; - uint8_t bottomcapindex = RGB256k.All[((RPART(bottomcapcolor) >> 2) << 12) | ((GPART(bottomcapcolor) >> 2) << 6) | (BPART(bottomcapcolor) >> 2)]; - - for (int i = 1; i <= mRows; i++) - { - RenderRow(thread, args, i, topcapcolor, topcapindex); - RenderRow(thread, args, rc + i, bottomcapcolor, bottomcapindex); - } -} - -void PolySkyDome::RenderRow(PolyRenderThread *thread, PolyDrawArgs &args, int row, uint32_t capcolor, uint8_t capcolorindex) -{ - args.SetColor(capcolor, capcolorindex); - args.SetStyle(TriBlendMode::Skycap); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleStrip); -} - -void PolySkyDome::RenderCapColorRow(PolyRenderThread *thread, PolyDrawArgs &args, FSoftwareTexture *skytex, int row, bool bottomCap) -{ - uint32_t solid = skytex->GetSkyCapColor(bottomCap); - uint8_t palsolid = RGB32k.RGB[(RPART(solid) >> 3)][(GPART(solid) >> 3)][(BPART(solid) >> 3)]; - - args.SetColor(solid, palsolid); - args.SetStyle(TriBlendMode::Fill); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleFan); -} - -void PolySkyDome::CreateDome() -{ - mColumns = 16;// 128; - mRows = 4; - CreateSkyHemisphere(false); - CreateSkyHemisphere(true); - mPrimStart.Push(mVertices.Size()); -} - -void PolySkyDome::CreateSkyHemisphere(bool zflip) -{ - int r, c; - - mPrimStart.Push(mVertices.Size()); - - for (c = 0; c < mColumns; c++) - { - SkyVertex(1, zflip ? c : (mColumns - 1 - c), zflip); - } - - // The total number of triangles per hemisphere can be calculated - // as follows: rows * columns * 2 + 2 (for the top cap). - for (r = 0; r < mRows; r++) - { - mPrimStart.Push(mVertices.Size()); - for (c = 0; c <= mColumns; c++) - { - SkyVertex(r + 1 - zflip, c, zflip); - SkyVertex(r + zflip, c, zflip); - } - } -} - -TriVertex PolySkyDome::SetVertexXYZ(float xx, float yy, float zz, float uu, float vv) -{ - TriVertex v; - v.x = xx; - v.y = zz; - v.z = yy; - v.w = 1.0f; - v.u = uu; - v.v = vv; - return v; -} - -void PolySkyDome::SkyVertex(int r, int c, bool zflip) -{ - static const FAngle maxSideAngle = 60.f; - static const float scale = 10000.; - - FAngle topAngle = (c / (float)mColumns * 360.f); - FAngle sideAngle = maxSideAngle * (float)(mRows - r) / (float)mRows; - float height = sideAngle.Sin(); - float realRadius = scale * sideAngle.Cos(); - FVector2 pos = topAngle.ToVector(realRadius); - float z = (!zflip) ? scale * height : -scale * height; - - float u, v; - - // And the texture coordinates. - if (!zflip) // Flipped Y is for the lower hemisphere. - { - u = (-c / (float)mColumns); - v = (r / (float)mRows); - } - else - { - u = (-c / (float)mColumns); - v = 1.0f + ((mRows - r) / (float)mRows); - } - - if (r != 4) z += 300; - - // And finally the vertex. - TriVertex vert; - vert = SetVertexXYZ(-pos.X, z - 1.f, pos.Y, u, v - 0.5f); - mVertices.Push(vert); - mInitialUV.Push({ vert.u, vert.v }); -} - -Mat4f PolySkyDome::GLSkyMath() -{ - PolySkySetup frameSetup; - frameSetup.Update(); - mCurrentSetup = frameSetup; - - float x_offset = 0.0f; - float y_offset = 0.0f; - bool mirror = false; - FSoftwareTexture *tex = mCurrentSetup.frontskytex; - - int texh = 0; - int texw = 0; - - Mat4f modelMatrix = Mat4f::Identity(); - if (tex) - { - texw = tex->GetWidth(); - texh = tex->GetHeight(); - - modelMatrix = Mat4f::Rotate(-180.0f + x_offset, 0.f, 0.f, 1.f); - - float xscale = texw < 1024.f ? floor(1024.f / float(texw)) : 1.f; - float yscale = 1.f; - if (texh <= 128 && (PolyRenderer::Instance()->Level->flags & LEVEL_FORCETILEDSKY)) - { - modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, (-40 + tex->GetSkyOffset() + skyoffset)*skyoffsetfactor); - modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, 1.2f * 1.17f); - yscale = 240.f / texh; - } - else if (texh < 128) - { - // smaller sky textures must be tiled. We restrict it to 128 sky pixels, though - modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, -1250.f); - modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, 128 / 230.f); - yscale = (float)(128 / texh); // intentionally left as integer. - } - else if (texh < 200) - { - modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, -1250.f); - modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, texh / 230.f); - } - else if (texh <= 240) - { - modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, (200 - texh + tex->GetSkyOffset() + skyoffset)*skyoffsetfactor); - modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, 1.f + ((texh - 200.f) / 200.f) * 1.17f); - } - else - { - modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, (-40 + tex->GetSkyOffset() + skyoffset)*skyoffsetfactor); - modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, 1.2f * 1.17f); - yscale = 240.f / texh; - } - - float offsetU = 1.0f; - float offsetV = y_offset / texh; - float scaleU = mirror ? -xscale : xscale; - float scaleV = yscale; - - unsigned int count = mVertices.Size(); - for (unsigned int i = 0; i < count; i++) - { - mVertices[i].u = offsetU + mInitialUV[i].X * scaleU; - mVertices[i].v = offsetV + mInitialUV[i].Y * scaleV; - } - } - - return modelMatrix; -} - -///////////////////////////////////////////////////////////////////////////// - -static FSoftwareTexture *GetSWTex(FTextureID texid, bool allownull = true) -{ - auto tex = TexMan.GetPalettedTexture(texid, true); - if (tex == nullptr) return nullptr; - if (!allownull && !tex->isValid()) return nullptr; - return tex->GetSoftwareTexture(); -} - -void PolySkySetup::Update() -{ - double skytexturemid = 0.0; - double skyscale = 0.0; - float skyiscale = 0.0f; - fixed_t sky1cyl = 0, sky2cyl = 0; - auto Level = PolyRenderer::Instance()->Level; - - auto skytex1 = TexMan.GetPalettedTexture(Level->skytexture1, true); - auto skytex2 = TexMan.GetPalettedTexture(Level->skytexture2, true); - - if (skytex1) - { - FSoftwareTexture *sskytex1 = skytex1->GetSoftwareTexture(); - FSoftwareTexture *sskytex2 = skytex2->GetSoftwareTexture(); - skytexturemid = 0; - int skyheight = skytex1->GetDisplayHeight(); - if (skyheight >= 128 && skyheight < 200) - { - skytexturemid = -28; - } - else if (skyheight > 200) - { - skytexturemid = (200 - skyheight) * sskytex1->GetScale().Y + ((r_skymode == 2 && !(Level->flags & LEVEL_FORCETILEDSKY)) ? skytex1->GetSkyOffset() : 0); - } - - if (viewwidth != 0 && viewheight != 0) - { - skyiscale = float(r_Yaspect / freelookviewheight); - skyscale = freelookviewheight / r_Yaspect; - - skyiscale *= float(PolyRenderer::Instance()->Viewpoint.FieldOfView.Degrees / 90.); - skyscale *= float(90. / PolyRenderer::Instance()->Viewpoint.FieldOfView.Degrees); - } - - if (Level->skystretch) - { - skyscale *= (double)SKYSTRETCH_HEIGHT / skyheight; - skyiscale *= skyheight / (float)SKYSTRETCH_HEIGHT; - skytexturemid *= skyheight / (double)SKYSTRETCH_HEIGHT; - } - - // The standard Doom sky texture is 256 pixels wide, repeated 4 times over 360 degrees, - // giving a total sky width of 1024 pixels. So if the sky texture is no wider than 1024, - // we map it to a cylinder with circumfrence 1024. For larger ones, we use the width of - // the texture as the cylinder's circumfrence. - sky1cyl = MAX(sskytex1->GetWidth(), fixed_t(sskytex1->GetScale().X * 1024)); - sky2cyl = MAX(sskytex2->GetWidth(), fixed_t(sskytex2->GetScale().Y * 1024)); - } - - FTextureID sky1tex, sky2tex; - double frontdpos = 0, backdpos = 0; - - if ((PolyRenderer::Instance()->Level->flags & LEVEL_SWAPSKIES) && !(PolyRenderer::Instance()->Level->flags & LEVEL_DOUBLESKY)) - { - sky1tex = Level->skytexture2; - } - else - { - sky1tex = Level->skytexture1; - } - sky2tex = Level->skytexture2; - skymid = skytexturemid; - skyangle = 0; - - int sectorSky = 0;// sector->sky; - - if (!(sectorSky & PL_SKYFLAT)) - { // use sky1 - sky1: - frontskytex = GetSWTex(sky1tex); - if (PolyRenderer::Instance()->Level->flags & LEVEL_DOUBLESKY) - backskytex = GetSWTex(sky2tex); - else - backskytex = nullptr; - skyflip = false; - frontdpos = Level->sky1pos; - backdpos = Level->sky2pos; - frontcyl = sky1cyl; - backcyl = sky2cyl; - } - else if (sectorSky == PL_SKYFLAT) - { // use sky2 - frontskytex = GetSWTex(sky2tex); - backskytex = nullptr; - frontcyl = sky2cyl; - skyflip = false; - frontdpos = Level->sky2pos; - } - else - { // MBF's linedef-controlled skies - // Sky Linedef - const line_t *l = &PolyRenderer::Instance()->Level->lines[(sectorSky & ~PL_SKYFLAT) - 1]; - - // Sky transferred from first sidedef - const side_t *s = l->sidedef[0]; - int pos; - - // Texture comes from upper texture of reference sidedef - // [RH] If swapping skies, then use the lower sidedef - if (PolyRenderer::Instance()->Level->flags & LEVEL_SWAPSKIES && s->GetTexture(side_t::bottom).isValid()) - { - pos = side_t::bottom; - } - else - { - pos = side_t::top; - } - - frontskytex = GetSWTex(s->GetTexture(pos), false); - if (frontskytex == nullptr) - { // [RH] The blank texture: Use normal sky instead. - goto sky1; - } - backskytex = nullptr; - - // Horizontal offset is turned into an angle offset, - // to allow sky rotation as well as careful positioning. - // However, the offset is scaled very small, so that it - // allows a long-period of sky rotation. - skyangle += FLOAT2FIXED(s->GetTextureXOffset(pos)); - - // Vertical offset allows careful sky positioning. - skymid = s->GetTextureYOffset(pos); - - // We sometimes flip the picture horizontally. - // - // Doom always flipped the picture, so we make it optional, - // to make it easier to use the new feature, while to still - // allow old sky textures to be used. - skyflip = l->args[2] ? false : true; - - int frontxscale = int(frontskytex->GetScale().X * 1024); - frontcyl = MAX(frontskytex->GetWidth(), frontxscale); - } - - frontpos = int(fmod(frontdpos, sky1cyl * 65536.0)); - if (backskytex != nullptr) - { - backpos = int(fmod(backdpos, sky2cyl * 65536.0)); - } -} diff --git a/src/rendering/polyrenderer/scene/poly_sky.h b/src/rendering/polyrenderer/scene/poly_sky.h deleted file mode 100644 index 441086511e..0000000000 --- a/src/rendering/polyrenderer/scene/poly_sky.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -** Sky dome rendering -** Copyright(C) 2003-2016 Christoph Oelckers -** All rights reserved. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public License -** along with this program. If not, see http:**www.gnu.org/licenses/ -** -** Loosely based on the JDoom sky and the ZDoomGL 0.66.2 sky. -*/ - -#pragma once - -#include "polyrenderer/drawers/poly_triangle.h" - -class PolySkySetup -{ -public: - void Update(); - - bool operator==(const PolySkySetup &that) const { return memcmp(this, &that, sizeof(PolySkySetup)) == 0; } - bool operator!=(const PolySkySetup &that) const { return memcmp(this, &that, sizeof(PolySkySetup)) != 0; } - - FSoftwareTexture *frontskytex = nullptr; - FSoftwareTexture *backskytex = nullptr; - bool skyflip = 0; - int frontpos = 0; - int backpos = 0; - fixed_t frontcyl = 0; - fixed_t backcyl = 0; - double skymid = 0.0; - angle_t skyangle = 0; -}; - -class PolySkyDome -{ -public: - PolySkyDome(); - void Render(PolyRenderThread *thread, const Mat4f &worldToView, const Mat4f &worldToClip); - -private: - TArray mInitialUV; - TArray mVertices; - TArray mPrimStart; - int mRows, mColumns; - - void SkyVertex(int r, int c, bool yflip); - void CreateSkyHemisphere(bool zflip); - void CreateDome(); - void RenderRow(PolyRenderThread *thread, PolyDrawArgs &args, int row, uint32_t capcolor, uint8_t capcolorindex); - void RenderCapColorRow(PolyRenderThread *thread, PolyDrawArgs &args, FSoftwareTexture *skytex, int row, bool bottomCap); - - TriVertex SetVertexXYZ(float xx, float yy, float zz, float uu = 0, float vv = 0); - - Mat4f GLSkyMath(); - - PolySkySetup mCurrentSetup; -}; diff --git a/src/rendering/polyrenderer/scene/poly_sprite.cpp b/src/rendering/polyrenderer/scene/poly_sprite.cpp deleted file mode 100644 index 5428f8de63..0000000000 --- a/src/rendering/polyrenderer/scene/poly_sprite.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "sbar.h" -#include "r_data/r_translate.h" -#include "poly_sprite.h" -#include "polyrenderer/poly_renderer.h" -#include "polyrenderer/scene/poly_light.h" -#include "polyrenderer/poly_renderthread.h" -#include "polyrenderer/scene/poly_model.h" -#include "r_data/r_vanillatrans.h" -#include "actorinlines.h" - -EXTERN_CVAR(Float, transsouls) -EXTERN_CVAR(Int, r_drawfuzz) -EXTERN_CVAR (Bool, r_debug_disable_vis_filter) -EXTERN_CVAR(Int, gl_spriteclip) -EXTERN_CVAR(Float, gl_sclipthreshold) -EXTERN_CVAR(Float, gl_sclipfactor) - -extern uint32_t r_renderercaps; -extern double model_distance_cull; - -bool RenderPolySprite::GetLine(AActor *thing, DVector2 &left, DVector2 &right) -{ - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac); - - bool flipTextureX = false; - FSoftwareTexture *tex = GetSpriteTexture(thing, flipTextureX); - if (tex == nullptr) - return false; - - DVector2 spriteScale = thing->Scale; - double thingxscalemul = spriteScale.X / tex->GetScale().X; - double thingyscalemul = spriteScale.Y / tex->GetScale().Y; - - double spriteWidth = thingxscalemul * tex->GetWidth(); - double spriteHeight = thingyscalemul * tex->GetHeight(); - - double offsetX; - if (flipTextureX) - offsetX = (tex->GetWidth() - tex->GetLeftOffsetPo()) * thingxscalemul; - else - offsetX = tex->GetLeftOffsetPo() * thingxscalemul; - - left = DVector2(pos.X - viewpoint.Sin * offsetX, pos.Y + viewpoint.Cos * offsetX); - right = DVector2(left.X + viewpoint.Sin * spriteWidth, left.Y - viewpoint.Cos * spriteWidth); - return true; -} - -void RenderPolySprite::Render(PolyRenderThread *thread, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2) -{ - if (r_modelscene) - { - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - int spritenum = thing->sprite; - bool isPicnumOverride = thing->picnum.isValid(); - FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); - if (modelframe && (thing->Pos() - viewpoint.Pos).LengthSquared() < model_distance_cull) - { - DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac); - PolyRenderModel(thread, PolyRenderer::Instance()->Scene.CurrentViewpoint->WorldToClip, stencilValue, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing); - return; - } - } - - DVector2 line[2]; - if (!GetLine(thing, line[0], line[1])) - return; - - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - DVector3 thingpos = thing->InterpolatedPosition(viewpoint.TicFrac); - - double posZ = thingpos.Z; - - uint32_t spritetype = (thing->renderflags & RF_SPRITETYPEMASK); - - if (spritetype == RF_FACESPRITE) - posZ -= thing->Floorclip; - - if (thing->flags2 & MF2_FLOATBOB) - posZ += thing->GetBobOffset(viewpoint.TicFrac); - - bool flipTextureX = false; - FSoftwareTexture *tex = GetSpriteTexture(thing, flipTextureX); - if (tex == nullptr) - return; - - double thingyscalemul = thing->Scale.Y / tex->GetScale().Y; - double spriteHeight = thingyscalemul * tex->GetHeight(); - - posZ -= (tex->GetHeight() - tex->GetTopOffsetPo()) * thingyscalemul; - posZ = PerformSpriteClipAdjustment(thing, thingpos, spriteHeight, posZ); - - //double depth = 1.0; - //visstyle_t visstyle = GetSpriteVisStyle(thing, depth); - // Rumor has it that AlterWeaponSprite needs to be called with visstyle passed in somewhere around here.. - //R_SetColorMapLight(visstyle.BaseColormap, 0, visstyle.ColormapNum << FRACBITS); - - TriVertex *vertices = thread->FrameMemory->AllocMemory(4); - - bool foggy = false; - int actualextralight = foggy ? 0 : viewpoint.extralight << 4; - - std::pair offsets[4] = - { - { t1, 1.0f }, - { t2, 1.0f }, - { t2, 0.0f }, - { t1, 0.0f }, - }; - - DVector2 points[2] = - { - line[0] * (1.0 - t1) + line[1] * t1, - line[0] * (1.0 - t2) + line[1] * t2 - }; - - for (int i = 0; i < 4; i++) - { - auto &p = (i == 0 || i == 3) ? points[0] : points[1]; - - vertices[i].x = (float)p.X; - vertices[i].y = (float)p.Y; - vertices[i].z = (float)(posZ + spriteHeight * offsets[i].second); - vertices[i].w = 1.0f; - vertices[i].u = (float)offsets[i].first; - vertices[i].v = (float)(1.0f - offsets[i].second); - if (flipTextureX) - vertices[i].u = 1.0f - vertices[i].u; - } - - bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)); - int lightlevel = fullbrightSprite ? 255 : thing->Sector->lightlevel + actualextralight; - - PolyDrawArgs args; - SetDynlight(thing, args); - auto nc = !!(thing->Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING); - args.SetLight(GetSpriteColorTable(sub->sector->Colormap, sub->sector->SpecialColors[sector_t::sprites], nc), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite); args.SetStencilTestValue(stencilValue); - if ((thing->renderflags & RF_ZDOOMTRANS) && r_UseVanillaTransparency) - args.SetStyle(LegacyRenderStyles[STYLE_Normal], 1.0f, thing->fillcolor, thing->Translation, tex, fullbrightSprite); - else - args.SetStyle(thing->RenderStyle, thing->Alpha, thing->fillcolor, thing->Translation, tex, fullbrightSprite); - args.SetDepthTest(true); - args.SetWriteDepth(false); - args.SetWriteStencil(false); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, 4, PolyDrawMode::TriangleFan); -} - -double RenderPolySprite::GetSpriteFloorZ(AActor *thing, const DVector2 &thingpos) -{ - extsector_t::xfloor &x = thing->Sector->e->XFloor; - for (unsigned int i = 0; i < x.ffloors.Size(); i++) - { - F3DFloor *ff = x.ffloors[i]; - double floorh = ff->top.plane->ZatPoint(thingpos); - if (floorh == thing->floorz) - return floorh; - } - - if (thing->Sector->GetHeightSec()) - { - if (thing->flags2&MF2_ONMOBJ && thing->floorz == thing->Sector->heightsec->floorplane.ZatPoint(thingpos)) - { - return thing->floorz; - } - } - - return thing->Sector->floorplane.ZatPoint(thing) - thing->Floorclip; -} - -double RenderPolySprite::GetSpriteCeilingZ(AActor *thing, const DVector2 &thingpos) -{ - extsector_t::xfloor &x = thing->Sector->e->XFloor; - for (unsigned int i = 0; i < x.ffloors.Size(); i++) - { - F3DFloor *ff = x.ffloors[i]; - double ceilingh = ff->bottom.plane->ZatPoint(thingpos); - if (ceilingh == thing->ceilingz) - return ceilingh; - } - - if (thing->Sector->GetHeightSec()) - { - if (thing->flags2&MF2_ONMOBJ && thing->ceilingz == thing->Sector->heightsec->ceilingplane.ZatPoint(thingpos)) - { - return thing->ceilingz; - } - } - - return thing->Sector->ceilingplane.ZatPoint(thingpos); -} - -double RenderPolySprite::PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, double spriteheight, double z2) -{ - int spriteclip = 2; // gl_spriteclip, but use 'always' mode for now - - double z1 = z2 + spriteheight; - - // Tests show that this doesn't look good for many decorations and corpses - uint32_t spritetype = (thing->renderflags & RF_SPRITETYPEMASK); - if (!(spriteheight > 0 && spriteclip > 0 && spritetype == RF_FACESPRITE)) - return z2; - - bool clipthing = (thing->player || thing->flags3&MF3_ISMONSTER || thing->IsKindOf(NAME_Inventory)) && (thing->flags&MF_ICECORPSE || !(thing->flags&MF_CORPSE)); - bool smarterclip = !clipthing && spriteclip == 3; - if (clipthing || spriteclip > 1) - { - double diffb = MIN(z2 - GetSpriteFloorZ(thing, thingpos), 0.0); - - // Adjust sprites clipping into ceiling and adjust clipping adjustment for tall graphics - if (smarterclip) - { - // Reduce slightly clipping adjustment of corpses - if (thing->flags & MF_CORPSE || spriteheight > fabs(diffb)) - { - double ratio = clamp((fabs(diffb) * (double)gl_sclipfactor / (spriteheight + 1)), 0.5, 1.0); - diffb *= ratio; - } - if (!diffb) - { - double difft = MAX(z1 - GetSpriteCeilingZ(thing, thingpos), 0.0); - if (difft >= (double)gl_sclipthreshold) - { - // dumb copy of the above. - if (!(thing->flags3&MF3_ISMONSTER) || (thing->flags&MF_NOGRAVITY) || (thing->flags&MF_CORPSE) || difft > (double)gl_sclipthreshold) - { - difft = 0; - } - } - if (spriteheight > fabs(difft)) - { - double ratio = clamp((fabs(difft) * (double)gl_sclipfactor / (spriteheight + 1)), 0.5, 1.0); - difft *= ratio; - } - z2 -= difft; - } - } - if (diffb <= (0 - (double)gl_sclipthreshold)) // such a large displacement can't be correct! - { - // for living monsters standing on the floor allow a little more. - if (!(thing->flags3&MF3_ISMONSTER) || (thing->flags&MF_NOGRAVITY) || (thing->flags&MF_CORPSE) || diffb < (-1.8*(double)gl_sclipthreshold)) - { - diffb = 0; - } - } - - z2 -= diffb; - } - return z2; -} - -bool RenderPolySprite::IsThingCulled(AActor *thing) -{ - FIntCVar *cvar = thing->GetInfo()->distancecheck; - if (cvar != nullptr && *cvar >= 0) - { - double dist = (thing->Pos() - PolyRenderer::Instance()->Viewpoint.Pos).LengthSquared(); - double check = (double)**cvar; - if (dist >= check * check) - return true; - } - - // Don't waste time projecting sprites that are definitely not visible. - if (thing == nullptr || - (thing->renderflags & RF_INVISIBLE) || - !thing->RenderStyle.IsVisible(thing->Alpha) || - !thing->IsVisibleToPlayer()) - { - return true; - } - - // check renderrequired vs ~r_rendercaps, if anything matches we don't support that feature, - // check renderhidden vs r_rendercaps, if anything matches we do support that feature and should hide it. - if ((!r_debug_disable_vis_filter && !!(thing->RenderRequired & ~r_renderercaps)) || - (!!(thing->RenderHidden & r_renderercaps))) - return true; - - return false; -} - -FSoftwareTexture *RenderPolySprite::GetSpriteTexture(AActor *thing, /*out*/ bool &flipX) -{ - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - flipX = false; - - if (thing->renderflags & RF_FLATSPRITE) - return nullptr; // do not draw flat sprites. - - if (thing->picnum.isValid()) - { - FTexture *ttex = TexMan.GetPalettedTexture(thing->picnum, true); - if (!ttex || !ttex->isValid()) - { - return nullptr; - } - FSoftwareTexture *tex = ttex->GetSoftwareTexture(); - - if (ttex->GetRotations() != 0xFFFF) - { - // choose a different rotation based on player view - spriteframe_t *sprframe = &SpriteFrames[ttex->GetRotations()]; - DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac); - pos.Z += thing->GetBobOffset(viewpoint.TicFrac); - DAngle ang = (pos - viewpoint.Pos).Angle(); - angle_t rot; - if (sprframe->Texture[0] == sprframe->Texture[1]) - { - rot = (ang - thing->Angles.Yaw + 45.0 / 2 * 9).BAMs() >> 28; - } - else - { - rot = (ang - thing->Angles.Yaw + (45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; - } - flipX = (sprframe->Flip & (1 << rot)) != 0; - ttex = TexMan.GetPalettedTexture(sprframe->Texture[rot], false); // Do not animate the rotation - tex = ttex->GetSoftwareTexture(); - if (!ttex || !ttex->isValid()) - { - return nullptr; - } - FSoftwareTexture *tex = ttex->GetSoftwareTexture(); - } - return tex; - } - else - { - // decide which texture to use for the sprite - int spritenum = thing->sprite; - if (spritenum >= (signed)sprites.Size() || spritenum < 0) - return nullptr; - - spritedef_t *sprdef = &sprites[spritenum]; - if (thing->frame >= sprdef->numframes) - { - // If there are no frames at all for this sprite, don't draw it. - return nullptr; - } - else - { - //picnum = SpriteFrames[sprdef->spriteframes + thing->frame].Texture[0]; - // choose a different rotation based on player view - - DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac); - pos.Z += thing->GetBobOffset(viewpoint.TicFrac); - DAngle ang = (pos - viewpoint.Pos).Angle(); - - DAngle sprangle = thing->GetSpriteAngle((pos - viewpoint.Pos).Angle(), viewpoint.TicFrac); - FTextureID tex = sprdef->GetSpriteFrame(thing->frame, -1, sprangle, &flipX); - if (!tex.isValid()) return nullptr; - return TexMan.GetPalettedTexture(tex, false)->GetSoftwareTexture(); - } - } -} - -void RenderPolySprite::SetDynlight(AActor *thing, PolyDrawArgs &args) -{ - bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)); - if (fullbrightSprite || !r_dynlights) - { - args.SetDynLightColor(0); - return; - } - - float lit_red = 0; - float lit_green = 0; - float lit_blue = 0; - auto node = thing->section->lighthead; - while (node != nullptr) - { - FDynamicLight *light = node->lightsource; - if (light->ShouldLightActor(thing)) - { - float lx = (float)(light->X() - thing->X()); - float ly = (float)(light->Y() - thing->Y()); - float lz = (float)(light->Z() - thing->Center()); - float LdotL = lx * lx + ly * ly + lz * lz; - float radius = node->lightsource->GetRadius(); - if (radius * radius >= LdotL) - { - float distance = sqrt(LdotL); - float attenuation = 1.0f - distance / radius; - if (attenuation > 0.0f) - { - float red = light->GetRed() * (1.0f / 255.0f); - float green = light->GetGreen() * (1.0f / 255.0f); - float blue = light->GetBlue() * (1.0f / 255.0f); - /*if (light->IsSubtractive()) - { - float bright = FVector3(lr, lg, lb).Length(); - FVector3 lightColor(lr, lg, lb); - red = (bright - lr) * -1; - green = (bright - lg) * -1; - blue = (bright - lb) * -1; - }*/ - - lit_red += red * attenuation; - lit_green += green * attenuation; - lit_blue += blue * attenuation; - } - } - } - node = node->nextLight; - } - lit_red = clamp(lit_red * 255.0f, 0.0f, 255.0f); - lit_green = clamp(lit_green * 255.0f, 0.0f, 255.0f); - lit_blue = clamp(lit_blue * 255.0f, 0.0f, 255.0f); - args.SetDynLightColor((((uint32_t)lit_red) << 16) | (((uint32_t)lit_green) << 8) | ((uint32_t)lit_blue)); -} diff --git a/src/rendering/polyrenderer/scene/poly_sprite.h b/src/rendering/polyrenderer/scene/poly_sprite.h deleted file mode 100644 index 7997228d68..0000000000 --- a/src/rendering/polyrenderer/scene/poly_sprite.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include "polyrenderer/drawers/poly_triangle.h" - -class RenderPolySprite -{ -public: - void Render(PolyRenderThread *thread, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2); - - static bool GetLine(AActor *thing, DVector2 &left, DVector2 &right); - static bool IsThingCulled(AActor *thing); - static FSoftwareTexture *GetSpriteTexture(AActor *thing, /*out*/ bool &flipX); - -private: - static double PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, double spriteheight, double z); - static double GetSpriteFloorZ(AActor *thing, const DVector2 &thingpos); - static double GetSpriteCeilingZ(AActor *thing, const DVector2 &thingpos); - static void SetDynlight(AActor *thing, PolyDrawArgs &args); -}; - -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(PolyRenderThread *thread) override - { - if ((thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) - { - RenderPolyWallSprite wallspr; - wallspr.Render(thread, thing, sub, StencilValue + 1); - } - else - { - RenderPolySprite spr; - spr.Render(thread, 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/rendering/polyrenderer/scene/poly_wall.cpp b/src/rendering/polyrenderer/scene/poly_wall.cpp deleted file mode 100644 index 9d04b64a7d..0000000000 --- a/src/rendering/polyrenderer/scene/poly_wall.cpp +++ /dev/null @@ -1,721 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "doomstat.h" -#include "doomdata.h" -#include "p_lnspec.h" -#include "sbar.h" -#include "r_data/r_translate.h" -#include "poly_wall.h" -#include "poly_decal.h" -#include "polyrenderer/poly_renderer.h" -#include "r_sky.h" -#include "polyrenderer/scene/poly_light.h" -#include "polyrenderer/poly_renderthread.h" -#include "g_levellocals.h" -#include "a_dynlight.h" - -EXTERN_CVAR(Bool, r_drawmirrors) -EXTERN_CVAR(Bool, r_fogboundary) - -bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals, size_t linePortalsStart, line_t *portalEnterLine) -{ - double frontceilz1 = frontsector->ceilingplane.ZatPoint(line->v1); - double frontfloorz1 = frontsector->floorplane.ZatPoint(line->v1); - double frontceilz2 = frontsector->ceilingplane.ZatPoint(line->v2); - double frontfloorz2 = frontsector->floorplane.ZatPoint(line->v2); - double topTexZ = frontsector->GetPlaneTexZ(sector_t::ceiling); - double bottomTexZ = frontsector->GetPlaneTexZ(sector_t::floor); - - PolyDrawLinePortal *polyportal = nullptr; - if (line->backsector == nullptr && line->linedef && line->sidedef == line->linedef->sidedef[0] && (line->linedef->special == Line_Mirror && r_drawmirrors)) - { - if (portalEnterLine == line->linedef) - { - return false; - } - - linePortals.push_back(std::unique_ptr(new PolyDrawLinePortal(line->linedef))); - polyportal = linePortals.back().get(); - } - else if (line->linedef && line->linedef->isVisualPortal() && line->sidedef == line->linedef->sidedef[0]) - { - if (portalEnterLine == line->linedef) - { - return false; - } - - FLinePortal *portal = line->linedef->getPortal(); - for (size_t i = linePortalsStart; i < linePortals.size(); i++) - { - if (linePortals[i]->Portal == portal) // To do: what other criteria do we need to check for? - { - polyportal = linePortals[i].get(); - break; - } - } - if (!polyportal) - { - linePortals.push_back(std::unique_ptr(new PolyDrawLinePortal(portal))); - polyportal = linePortals.back().get(); - } - } - - RenderPolyWall wall; - wall.LineSeg = line; - wall.Line = line->linedef; - wall.Side = line->sidedef; - wall.LineSegLine = line->linedef; - wall.Masked = false; - wall.SubsectorDepth = subsectorDepth; - wall.StencilValue = stencilValue; - wall.SectorLightLevel = frontsector->lightlevel; - - if (line->backsector == nullptr) - { - if (line->sidedef) - { - wall.SetCoords(line->v1->fPos(), line->v2->fPos(), frontceilz1, frontfloorz1, frontceilz2, frontfloorz2); - wall.TopTexZ = topTexZ; - wall.BottomTexZ = bottomTexZ; - wall.Wallpart = side_t::mid; - wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector)); - wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid); - wall.Polyportal = polyportal; - wall.Render(thread); - return true; - } - } - else if (line->PartnerSeg && line->PartnerSeg->Subsector) - { - PolyTransferHeights fakeback(line->PartnerSeg->Subsector); - sector_t *backsector = fakeback.FrontSector; - - double backceilz1 = backsector->ceilingplane.ZatPoint(line->v1); - double backfloorz1 = backsector->floorplane.ZatPoint(line->v1); - double backceilz2 = backsector->ceilingplane.ZatPoint(line->v2); - double backfloorz2 = backsector->floorplane.ZatPoint(line->v2); - - double topceilz1 = frontceilz1; - double topceilz2 = frontceilz2; - double topfloorz1 = MAX(MIN(backceilz1, frontceilz1), frontfloorz1); - double topfloorz2 = MAX(MIN(backceilz2, frontceilz2), frontfloorz2); - double bottomceilz1 = MIN(MAX(frontfloorz1, backfloorz1), frontceilz1); - double bottomceilz2 = MIN(MAX(frontfloorz2, backfloorz2), frontceilz2); - double bottomfloorz1 = frontfloorz1; - double bottomfloorz2 = frontfloorz2; - double middleceilz1 = topfloorz1; - double middleceilz2 = topfloorz2; - double middlefloorz1 = MIN(bottomceilz1, middleceilz1); - double middlefloorz2 = MIN(bottomceilz2, middleceilz2); - - bool bothSkyCeiling = frontsector->GetTexture(sector_t::ceiling) == skyflatnum && backsector->GetTexture(sector_t::ceiling) == skyflatnum; - bool bothSkyFloor = frontsector->GetTexture(sector_t::floor) == skyflatnum && backsector->GetTexture(sector_t::floor) == skyflatnum; - - if ((topceilz1 > topfloorz1 || topceilz2 > topfloorz2) && line->sidedef && !bothSkyCeiling) - { - wall.SetCoords(line->v1->fPos(), line->v2->fPos(), topceilz1, topfloorz1, topceilz2, topfloorz2); - wall.TopTexZ = topTexZ; - wall.BottomTexZ = MIN(MIN(backceilz1, frontceilz1), MIN(backceilz2, frontceilz2)); - wall.Wallpart = side_t::top; - wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector)); - wall.Texture = GetTexture(wall.Line, wall.Side, side_t::top); - wall.Render(thread); - } - - if ((bottomfloorz1 < bottomceilz1 || bottomfloorz2 < bottomceilz2) && line->sidedef && !bothSkyFloor) - { - wall.SetCoords(line->v1->fPos(), line->v2->fPos(), bottomceilz1, bottomfloorz1, bottomceilz2, bottomfloorz2); - wall.TopTexZ = MAX(MAX(frontfloorz1, backfloorz1), MAX(frontfloorz2, backfloorz2)); - wall.BottomTexZ = bottomTexZ; - wall.UnpeggedCeil1 = topceilz1; - wall.UnpeggedCeil2 = topceilz2; - wall.Wallpart = side_t::bottom; - wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector)); - wall.Texture = GetTexture(wall.Line, wall.Side, side_t::bottom); - wall.Render(thread); - } - - if (line->sidedef) - { - wall.SetCoords(line->v1->fPos(), line->v2->fPos(), middleceilz1, middlefloorz1, middleceilz2, middlefloorz2); - wall.TopTexZ = MAX(middleceilz1, middleceilz2); - wall.BottomTexZ = MIN(middlefloorz1, middlefloorz2); - wall.Wallpart = side_t::mid; - wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector)); - wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid); - wall.Masked = true; - wall.Additive = !!(wall.Line->flags & ML_ADDTRANS); - wall.Alpha = wall.Line->alpha; - wall.FogBoundary = IsFogBoundary(frontsector, backsector); - - FTexture *midtex = TexMan.GetPalettedTexture(line->sidedef->GetTexture(side_t::mid), true); - if ((midtex && midtex->isValid()) || wall.FogBoundary) - translucentWallsOutput.push_back(thread->FrameMemory->NewObject(wall)); - - if (polyportal) - { - wall.Polyportal = polyportal; - wall.Render(thread); - } - } - } - return polyportal != nullptr; -} - -bool RenderPolyWall::IsFogBoundary(sector_t *front, sector_t *back) -{ - return r_fogboundary && PolyCameraLight::Instance()->FixedColormap() == nullptr && front->Colormap.FadeColor && - front->Colormap.FadeColor != back->Colormap.FadeColor && - (front->GetTexture(sector_t::ceiling) != skyflatnum || back->GetTexture(sector_t::ceiling) != skyflatnum); -} - -void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput) -{ - if (!(fakeFloor->flags & FF_EXISTS)) return; - if (!(fakeFloor->flags & FF_RENDERPLANES)) return; - if (!fakeFloor->model) return; - if (fakeFloor->alpha == 0) return; - - double frontceilz1 = fakeFloor->top.plane->ZatPoint(line->v1); - double frontfloorz1 = fakeFloor->bottom.plane->ZatPoint(line->v1); - double frontceilz2 = fakeFloor->top.plane->ZatPoint(line->v2); - double frontfloorz2 = fakeFloor->bottom.plane->ZatPoint(line->v2); - double topTexZ = fakeFloor->model->GetPlaneTexZ(sector_t::ceiling); - double bottomTexZ = fakeFloor->model->GetPlaneTexZ(sector_t::floor); - - if (frontceilz1 <= frontfloorz1 || frontceilz2 <= frontfloorz2) - return; - - if (fakeFloor->flags & FF_SWIMMABLE) // Only draw swimmable boundary if not swimmable on both sides - { - DVector2 c = (line->v1->fPos() + line->v2->fPos()) * 0.5; - double cz = (frontceilz1 + frontceilz2 + frontfloorz1 + frontfloorz2) * 0.25; - for (unsigned i = 0; i < frontsector->e->XFloor.ffloors.Size(); i++) - { - F3DFloor *frontFloor = frontsector->e->XFloor.ffloors[i]; - if (!(frontFloor->flags & FF_EXISTS)) continue; - if (!(frontFloor->flags & FF_RENDERPLANES)) continue; - if (!frontFloor->model) continue; - if (frontFloor->alpha == 0) continue; - if (frontFloor->top.plane->ZatPoint(c) >= cz && frontFloor->bottom.plane->ZatPoint(c) <= cz && (frontFloor->flags & FF_SWIMMABLE)) - { - return; - } - } - } - - RenderPolyWall wall; - wall.LineSeg = line; - wall.LineSegLine = line->linedef; - wall.Line = fakeFloor->master; - wall.Side = fakeFloor->master->sidedef[0]; - wall.Additive = !!(fakeFloor->flags & FF_ADDITIVETRANS); - if (!wall.Additive && fakeFloor->alpha == 255) - { - wall.Masked = false; - wall.Alpha = 1.0; - } - else - { - wall.Masked = true; - wall.Alpha = fakeFloor->alpha / 255.0; - } - wall.SubsectorDepth = subsectorDepth; - wall.StencilValue = stencilValue; - wall.SetCoords(line->v1->fPos(), line->v2->fPos(), frontceilz1, frontfloorz1, frontceilz2, frontfloorz2); - wall.TopTexZ = topTexZ; - wall.BottomTexZ = bottomTexZ; - wall.Wallpart = side_t::mid; - wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector)); - if (fakeFloor->flags & FF_UPPERTEXTURE) - wall.Texture = GetTexture(line->linedef, line->sidedef, side_t::top); - else if (fakeFloor->flags & FF_LOWERTEXTURE) - wall.Texture = GetTexture(line->linedef, line->sidedef, side_t::bottom); - else - wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid); - - if (frontsector->e->XFloor.lightlist.Size()) - { - lightlist_t *light = P_GetPlaneLight(frontsector, fakeFloor->top.plane, true); - wall.Colormap = GetColorTable(light->extra_colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector)); - wall.SectorLightLevel = *light->p_lightlevel; - } - else - { - - wall.SectorLightLevel = frontsector->lightlevel; - } - - if (!wall.Masked) - wall.Render(thread); - else - translucentWallsOutput.push_back(thread->FrameMemory->NewObject(wall)); -} - -void RenderPolyWall::SetCoords(const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2) -{ - this->v1 = v1; - this->v2 = v2; - this->ceil1 = ceil1; - this->floor1 = floor1; - this->ceil2 = ceil2; - this->floor2 = floor2; -} - -void RenderPolyWall::Render(PolyRenderThread *thread) -{ - bool foggy = false; - if (!Texture && !Polyportal && !FogBoundary) - return; - - TriVertex *vertices = thread->FrameMemory->AllocMemory(4); - - vertices[0].x = (float)v1.X; - vertices[0].y = (float)v1.Y; - vertices[0].z = (float)ceil1; - vertices[0].w = 1.0f; - - vertices[1].x = (float)v2.X; - vertices[1].y = (float)v2.Y; - vertices[1].z = (float)ceil2; - vertices[1].w = 1.0f; - - vertices[2].x = (float)v2.X; - vertices[2].y = (float)v2.Y; - vertices[2].z = (float)floor2; - vertices[2].w = 1.0f; - - vertices[3].x = (float)v1.X; - vertices[3].y = (float)v1.Y; - vertices[3].z = (float)floor1; - vertices[3].w = 1.0f; - - if (Texture) - { - PolyWallTextureCoordsU texcoordsU(Texture, LineSeg, LineSegLine, Side, Wallpart); - PolyWallTextureCoordsV texcoordsVLeft(Texture, Line, Side, Wallpart, ceil1, floor1, UnpeggedCeil1, TopTexZ, BottomTexZ); - PolyWallTextureCoordsV texcoordsVRght(Texture, Line, Side, Wallpart, ceil2, floor2, UnpeggedCeil2, TopTexZ, BottomTexZ); - vertices[0].u = (float)texcoordsU.u1; - vertices[0].v = (float)texcoordsVLeft.v1; - vertices[1].u = (float)texcoordsU.u2; - vertices[1].v = (float)texcoordsVRght.v1; - vertices[2].u = (float)texcoordsU.u2; - vertices[2].v = (float)texcoordsVRght.v2; - vertices[3].u = (float)texcoordsU.u1; - vertices[3].v = (float)texcoordsVLeft.v2; - } - else - { - for (int i = 0; i < 4; i++) - { - vertices[i].u = 0.0f; - vertices[i].v = 0.0f; - } - } - - // Masked walls clamp to the 0-1 range (no texture repeat) - if (Masked) - { - bool wrap = (Line->flags & ML_WRAP_MIDTEX) || (Side->Flags & WALLF_WRAP_MIDTEX); - if (!wrap) - { - ClampHeight(vertices[0], vertices[3]); - ClampHeight(vertices[1], vertices[2]); - } - } - - PolyDrawArgs args; - args.SetLight(Colormap, GetLightLevel(), PolyRenderer::Instance()->Light.WallGlobVis(foggy), false); - if (Texture && !Polyportal) - args.SetTexture(Texture, DefaultRenderStyle()); - - SetDynLights(thread, args); - - if (FogBoundary) - { - args.SetStencilTestValue(StencilValue + 1); - args.SetStyle(TriBlendMode::FogBoundary); - args.SetColor(0xffffffff, 254); - args.SetDepthTest(true); - args.SetWriteDepth(true); - args.SetWriteStencil(false); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, 4, PolyDrawMode::TriangleFan); - if (!Texture) - return; - } - - if (Polyportal) - { - args.SetStencilTestValue(StencilValue); - args.SetWriteStencil(true, Polyportal->StencilValue); - args.SetWriteColor(false); - args.SetWriteDepth(false); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, 4, PolyDrawMode::TriangleFan); - Polyportal->Shape.push_back({ vertices, 4 }); - } - else if (!Masked) - { - args.SetStencilTestValue(StencilValue); - args.SetWriteStencil(true, StencilValue + 1); - args.SetStyle(TriBlendMode::Opaque); - DrawStripes(thread, args, vertices); - } - else - { - double a = MIN(Alpha, 1.0); - if (Additive) - args.SetStyle(TriBlendMode::Add, a); - else if (a < 1.0) - args.SetStyle(TriBlendMode::Translucent, a); - else - args.SetStyle(TriBlendMode::Normal); - - args.SetStencilTestValue(StencilValue + 1); - args.SetDepthTest(true); - args.SetWriteDepth(true); - args.SetWriteStencil(false); - DrawStripes(thread, args, vertices); - } - - RenderPolyDecal::RenderWallDecals(thread, LineSeg, StencilValue + 1); -} - -void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args) -{ - if (!r_dynlights) - { - args.SetLights(nullptr, 0); - return; - } - - FLightNode *light_list = (LineSeg && LineSeg->sidedef) ? LineSeg->sidedef->lighthead : nullptr; - - auto cameraLight = PolyCameraLight::Instance(); - if ((cameraLight->FixedLightLevel() >= 0) || (cameraLight->FixedColormap() != nullptr)) - { - args.SetLights(nullptr, 0); // [SP] Don't draw dynlights if invul/lightamp active - return; - } - - // Calculate max lights that can touch the wall so we can allocate memory for the list - int max_lights = 0; - FLightNode *cur_node = light_list; - while (cur_node) - { - if (cur_node->lightsource->IsActive()) - max_lights++; - cur_node = cur_node->nextLight; - } - - if (max_lights == 0) - { - args.SetLights(nullptr, 0); - return; - } - - int dc_num_lights = 0; - PolyLight *dc_lights = thread->FrameMemory->AllocMemory(max_lights); - - // Setup lights - cur_node = light_list; - while (cur_node) - { - if (cur_node->lightsource->IsActive()) - { - bool is_point_light = cur_node->lightsource->IsAttenuated(); - - // To do: cull lights not touching wall - - uint32_t red = cur_node->lightsource->GetRed(); - uint32_t green = cur_node->lightsource->GetGreen(); - uint32_t blue = cur_node->lightsource->GetBlue(); - - auto &light = dc_lights[dc_num_lights++]; - light.x = (float)cur_node->lightsource->X(); - light.y = (float)cur_node->lightsource->Y(); - light.z = (float)cur_node->lightsource->Z(); - light.radius = 256.0f / cur_node->lightsource->GetRadius(); - light.color = (red << 16) | (green << 8) | blue; - if (is_point_light) - light.radius = -light.radius; - } - - cur_node = cur_node->nextLight; - } - - args.SetLights(dc_lights, dc_num_lights); - - // Face normal: - float dx = (float)(v2.X - v1.X); - float dy = (float)(v2.Y - v1.Y); - float nx = dy; - float ny = -dx; - float lensqr = nx * nx + ny * ny; - float rcplen = 1.0f / sqrt(lensqr); - nx *= rcplen; - ny *= rcplen; - args.SetNormal({ nx, ny, 0.0f }); -} - -void RenderPolyWall::DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices) -{ - const auto &lightlist = Line->frontsector->e->XFloor.lightlist; - if (lightlist.Size() > 0) - { - PolyClipPlane topPlane; - - for (unsigned int i = 0; i < lightlist.Size(); i++) - { - lightlist_t *lit = &lightlist[i]; - - DVector3 normal = lit->plane.Normal(); - double d = lit->plane.fD(); - if (normal.Z < 0.0) - { - normal = -normal; - d = -d; - } - - PolyClipPlane bottomPlane = { (float)normal.X, (float)normal.Y, (float)normal.Z, (float)d }; - - args.SetClipPlane(1, topPlane); - args.SetClipPlane(2, bottomPlane); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, 4, PolyDrawMode::TriangleFan); - - FDynamicColormap *basecolormap = GetColorTable(lit->extra_colormap, Line->frontsector->SpecialColors[sector_t::walltop]); - - bool foggy = false; - int lightlevel; - PolyCameraLight *cameraLight = PolyCameraLight::Instance(); - if (cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) - { - lightlevel = 255; - } - else - { - int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4; - lightlevel = clamp(Side->GetLightLevel(foggy, *lit->p_lightlevel) + actualextralight, 0, 255); - } - args.SetLight(basecolormap, lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), false); - - topPlane = { (float)-normal.X, (float)-normal.Y, (float)-normal.Z, (float)-d }; - } - - args.SetClipPlane(1, topPlane); - args.SetClipPlane(2, PolyClipPlane()); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, 4, PolyDrawMode::TriangleFan); - } - else - { - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, 4, PolyDrawMode::TriangleFan); - } -} - -void RenderPolyWall::ClampHeight(TriVertex &v1, TriVertex &v2) -{ - float top = v1.z; - float bottom = v2.z; - float texv1 = v1.v; - float texv2 = v2.v; - float delta = (texv2 - texv1); - - float t1 = texv1 < 0.0f ? -texv1 / delta : 0.0f; - float t2 = texv2 > 1.0f ? (1.0f - texv1) / delta : 1.0f; - float inv_t1 = 1.0f - t1; - float inv_t2 = 1.0f - t2; - - v1.z = top * inv_t1 + bottom * t1; - v1.v = texv1 * inv_t1 + texv2 * t1; - - v2.z = top * inv_t2 + bottom * t2; - v2.v = texv1 * inv_t2 + texv2 * t2; -} - -FSoftwareTexture *RenderPolyWall::GetTexture(const line_t *line, const side_t *side, side_t::ETexpart texpart) -{ - FTexture *tex = TexMan.GetPalettedTexture(side->GetTexture(texpart), true); - if (tex == nullptr || !tex->isValid()) - { - // Mapping error. Doom floodfills this with a plane. - // This code doesn't do that, but at least it uses the "right" texture.. - - if (line && line->backsector && line->sidedef[0] == side) - { - if (texpart == side_t::top) - tex = TexMan.GetPalettedTexture(line->backsector->GetTexture(sector_t::ceiling), true); - else if (texpart == side_t::bottom) - tex = TexMan.GetPalettedTexture(line->backsector->GetTexture(sector_t::floor), true); - } - if (line && line->backsector && line->sidedef[1] == side) - { - if (texpart == side_t::top) - tex = TexMan.GetPalettedTexture(line->frontsector->GetTexture(sector_t::ceiling), true); - else if (texpart == side_t::bottom) - tex = TexMan.GetPalettedTexture(line->frontsector->GetTexture(sector_t::floor), true); - } - - if (tex == nullptr || !tex->isValid()) - return nullptr; - } - return tex? tex->GetSoftwareTexture() : nullptr; -} - -int RenderPolyWall::GetLightLevel() -{ - PolyCameraLight *cameraLight = PolyCameraLight::Instance(); - if (cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap()) - { - return 255; - } - else - { - bool foggy = false; - int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4; - return clamp(Side->GetLightLevel(foggy, SectorLightLevel) + actualextralight, 0, 255); - } -} - -///////////////////////////////////////////////////////////////////////////// - -PolyWallTextureCoordsU::PolyWallTextureCoordsU(FSoftwareTexture *tex, const seg_t *lineseg, const line_t *line, const side_t *side, side_t::ETexpart wallpart) -{ - // Calculate the U texture coordinate for the line - double lineu1 = side->GetTextureXOffset(wallpart); - double lineu2 = side->GetTextureXOffset(wallpart) + line->sidedef[0]->TexelLength * side->GetTextureXScale(wallpart); - lineu1 *= tex->GetScale().X / tex->GetWidth(); - lineu2 *= tex->GetScale().X / tex->GetWidth(); - - // Calculate where we are on the lineseg - double t1, t2; - if (fabs(line->delta.X) > fabs(line->delta.Y)) - { - t1 = (lineseg->v1->fX() - line->v1->fX()) / line->delta.X; - t2 = (lineseg->v2->fX() - line->v1->fX()) / line->delta.X; - } - else - { - t1 = (lineseg->v1->fY() - line->v1->fY()) / line->delta.Y; - t2 = (lineseg->v2->fY() - line->v1->fY()) / line->delta.Y; - } - - // Check if lineseg is the backside of the line - if (t2 < t1) - { - std::swap(lineu1, lineu2); - } - - // Calculate texture coordinates for the lineseg - u1 = (1.0 - t1) * lineu1 + t1 * lineu2; - u2 = (1.0 - t2) * lineu1 + t2 * lineu2; -} - -///////////////////////////////////////////////////////////////////////////// - -PolyWallTextureCoordsV::PolyWallTextureCoordsV(FSoftwareTexture *tex, const line_t *line, const side_t *side, side_t::ETexpart wallpart, double topz, double bottomz, double unpeggedceil, double topTexZ, double bottomTexZ) -{ - double yoffset = side->GetTextureYOffset(wallpart); - if (tex->useWorldPanning(line->GetLevel())) - yoffset *= side->GetTextureYScale(wallpart) * tex->GetScale().Y; - - switch (wallpart) - { - default: - case side_t::mid: - CalcVMidPart(tex, line, side, topTexZ, bottomTexZ, yoffset); - break; - case side_t::top: - CalcVTopPart(tex, line, side, topTexZ, bottomTexZ, yoffset); - break; - case side_t::bottom: - CalcVBottomPart(tex, line, side, topTexZ, bottomTexZ, unpeggedceil, yoffset); - break; - } - - v1 *= tex->GetScale().Y / tex->GetHeight(); - v2 *= tex->GetScale().Y / tex->GetHeight(); - - double texZHeight = (bottomTexZ - topTexZ); - if (texZHeight > 0.0f || texZHeight < -0.0f) - { - double t1 = (topz - topTexZ) / texZHeight; - double t2 = (bottomz - topTexZ) / texZHeight; - double vorig1 = v1; - double vorig2 = v2; - v1 = vorig1 * (1.0f - t1) + vorig2 * t1; - v2 = vorig1 * (1.0f - t2) + vorig2 * t2; - } -} - -void PolyWallTextureCoordsV::CalcVTopPart(FSoftwareTexture *tex, const line_t *line, const side_t *side, double topz, double bottomz, double yoffset) -{ - bool pegged = (line->flags & ML_DONTPEGTOP) == 0; - if (pegged) // bottom to top - { - double texHeight = tex->GetHeight() / tex->GetScale().Y; - v1 = (topz - bottomz) * side->GetTextureYScale(side_t::top) - yoffset; - v2 = -yoffset; - v1 = texHeight - v1; - v2 = texHeight - v2; - } - else // top to bottom - { - v1 = yoffset; - v2 = (topz - bottomz) * side->GetTextureYScale(side_t::top) + yoffset; - } -} - -void PolyWallTextureCoordsV::CalcVMidPart(FSoftwareTexture *tex, const line_t *line, const side_t *side, double topz, double bottomz, double yoffset) -{ - bool pegged = (line->flags & ML_DONTPEGBOTTOM) == 0; - if (pegged) // top to bottom - { - v1 = yoffset; - v2 = (topz - bottomz) * side->GetTextureYScale(side_t::mid) + yoffset; - } - else // bottom to top - { - double texHeight = tex->GetHeight() / tex->GetScale().Y; - v1 = yoffset - (topz - bottomz) * side->GetTextureYScale(side_t::mid); - v2 = yoffset; - v1 = texHeight + v1; - v2 = texHeight + v2; - } -} - -void PolyWallTextureCoordsV::CalcVBottomPart(FSoftwareTexture *tex, const line_t *line, const side_t *side, double topz, double bottomz, double unpeggedceil, double yoffset) -{ - bool pegged = (line->flags & ML_DONTPEGBOTTOM) == 0; - if (pegged) // top to bottom - { - v1 = yoffset; - v2 = yoffset + (topz - bottomz) * side->GetTextureYScale(side_t::bottom); - } - else - { - v1 = yoffset + (unpeggedceil - topz) * side->GetTextureYScale(side_t::bottom); - v2 = yoffset + (unpeggedceil - bottomz) * side->GetTextureYScale(side_t::bottom); - } -} diff --git a/src/rendering/polyrenderer/scene/poly_wall.h b/src/rendering/polyrenderer/scene/poly_wall.h deleted file mode 100644 index 03850b0fcc..0000000000 --- a/src/rendering/polyrenderer/scene/poly_wall.h +++ /dev/null @@ -1,110 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include "polyrenderer/drawers/poly_triangle.h" - -class PolyTranslucentObject; -class PolyDrawLinePortal; -class PolyCull; - -class RenderPolyWall -{ -public: - static bool RenderLine(PolyRenderThread *thread, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector &translucentWallsOutput, std::vector> &linePortals, size_t linePortalsStart, line_t *portalEnterLine); - static void Render3DFloorLine(PolyRenderThread *thread, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector &translucentWallsOutput); - - void SetCoords(const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2); - void Render(PolyRenderThread *thread); - - DVector2 v1; - DVector2 v2; - double ceil1 = 0.0; - double floor1 = 0.0; - double ceil2 = 0.0; - double floor2 = 0.0; - - const seg_t *LineSeg = nullptr; - const line_t *LineSegLine = nullptr; - const line_t *Line = nullptr; - const side_t *Side = nullptr; - FSoftwareTexture *Texture = nullptr; - side_t::ETexpart Wallpart = side_t::mid; - double TopTexZ = 0.0; - double BottomTexZ = 0.0; - double UnpeggedCeil1 = 0.0; - double UnpeggedCeil2 = 0.0; - FSWColormap *Colormap = nullptr; - int SectorLightLevel = 0; - bool Masked = false; - bool Additive = false; - double Alpha = 1.0; - bool FogBoundary = false; - uint32_t SubsectorDepth = 0; - uint32_t StencilValue = 0; - PolyDrawLinePortal *Polyportal = nullptr; - -private: - void ClampHeight(TriVertex &v1, TriVertex &v2); - int GetLightLevel(); - void DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices); - - void SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args); - - static bool IsFogBoundary(sector_t *front, sector_t *back); - static FSoftwareTexture *GetTexture(const line_t *Line, const side_t *Side, side_t::ETexpart texpart); -}; - -class PolyWallTextureCoordsU -{ -public: - PolyWallTextureCoordsU(FSoftwareTexture *tex, const seg_t *lineseg, const line_t *linesegline, const side_t *side, side_t::ETexpart wallpart); - - double u1, u2; -}; - -class PolyWallTextureCoordsV -{ -public: - PolyWallTextureCoordsV(FSoftwareTexture *tex, const line_t *line, const side_t *side, side_t::ETexpart wallpart, double topz, double bottomz, double unpeggedceil, double topTexZ, double bottomTexZ); - - double v1, v2; - -private: - void CalcVTopPart(FSoftwareTexture *tex, const line_t *line, const side_t *side, double topz, double bottomz, double yoffset); - void CalcVMidPart(FSoftwareTexture *tex, const line_t *line, const side_t *side, double topz, double bottomz, double yoffset); - void CalcVBottomPart(FSoftwareTexture *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(PolyRenderThread *thread) override - { - wall.Render(thread); - } - - RenderPolyWall wall; -}; diff --git a/src/rendering/polyrenderer/scene/poly_wallsprite.cpp b/src/rendering/polyrenderer/scene/poly_wallsprite.cpp deleted file mode 100644 index d826186dbe..0000000000 --- a/src/rendering/polyrenderer/scene/poly_wallsprite.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" -#include "sbar.h" -#include "r_data/r_translate.h" -#include "poly_wallsprite.h" -#include "polyrenderer/poly_renderer.h" -#include "polyrenderer/scene/poly_light.h" -#include "polyrenderer/poly_renderthread.h" - -void RenderPolyWallSprite::Render(PolyRenderThread *thread, AActor *thing, subsector_t *sub, uint32_t stencilValue) -{ - if (RenderPolySprite::IsThingCulled(thing)) - return; - - const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac); - pos.Z += thing->GetBobOffset(viewpoint.TicFrac); - - bool flipTextureX = false; - FSoftwareTexture *tex = RenderPolySprite::GetSpriteTexture(thing, flipTextureX); - if (tex == nullptr) - return; - - DVector2 spriteScale = thing->Scale; - double thingxscalemul = spriteScale.X / tex->GetScale().X; - double thingyscalemul = spriteScale.Y / tex->GetScale().Y; - double spriteHeight = thingyscalemul * tex->GetHeight(); - - DAngle ang = thing->Angles.Yaw + 90; - double angcos = ang.Cos(); - double angsin = ang.Sin(); - - // Determine left and right edges of sprite. The sprite's angle is its normal, - // so the edges are 90 degrees each side of it. - double x2 = tex->GetScaledWidth() * spriteScale.X; - double x1 = tex->GetScaledLeftOffsetPo() * spriteScale.X; - DVector2 left, right; - left.X = pos.X - x1 * angcos; - left.Y = pos.Y - x1 * angsin; - right.X = left.X + x2 * angcos; - right.Y = left.Y + x2 * angsin; - - //int scaled_to = tex->GetScaledTopOffset(); - //int scaled_bo = scaled_to - tex->GetScaledHeight(); - //gzt = pos.Z + scale.Y * scaled_to; - //gzb = pos.Z + scale.Y * scaled_bo; - - DVector2 points[2] = { left, right }; - - TriVertex *vertices = thread->FrameMemory->AllocMemory(4); - - bool foggy = false; - int actualextralight = foggy ? 0 : viewpoint.extralight << 4; - - std::pair offsets[4] = - { - { 0.0f, 1.0f }, - { 1.0f, 1.0f }, - { 1.0f, 0.0f }, - { 0.0f, 0.0f }, - }; - - for (int i = 0; i < 4; i++) - { - auto &p = (i == 0 || i == 3) ? points[0] : points[1]; - - vertices[i].x = (float)p.X; - vertices[i].y = (float)p.Y; - vertices[i].z = (float)(pos.Z + spriteHeight * offsets[i].second); - vertices[i].w = 1.0f; - vertices[i].u = (float)(offsets[i].first * tex->GetScale().X); - vertices[i].v = (float)((1.0f - offsets[i].second) * tex->GetScale().Y); - if (flipTextureX) - vertices[i].u = 1.0f - vertices[i].u; - } - - bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)); - int lightlevel = fullbrightSprite ? 255 : thing->Sector->lightlevel + actualextralight; - - PolyDrawArgs args; - auto nc = !!(thing->Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING); - args.SetLight(GetSpriteColorTable(sub->sector->Colormap, sub->sector->SpecialColors[sector_t::sprites], nc), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), fullbrightSprite); args.SetStencilTestValue(stencilValue); - args.SetTexture(tex, thing->RenderStyle); - args.SetDepthTest(true); - args.SetWriteDepth(false); - args.SetWriteStencil(false); - args.SetStyle(TriBlendMode::Normal); - PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, 4, PolyDrawMode::TriangleFan); -} diff --git a/src/rendering/polyrenderer/scene/poly_wallsprite.h b/src/rendering/polyrenderer/scene/poly_wallsprite.h deleted file mode 100644 index d50223f114..0000000000 --- a/src/rendering/polyrenderer/scene/poly_wallsprite.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -** -*/ - -#pragma once - -#include "polyrenderer/drawers/poly_triangle.h" - -class RenderPolyWallSprite -{ -public: - void Render(PolyRenderThread *thread, AActor *thing, subsector_t *sub, uint32_t stencilValue); -}; diff --git a/src/rendering/swrenderer/drawers/r_draw.cpp b/src/rendering/swrenderer/drawers/r_draw.cpp index 4d20ca6824..42d9d6c073 100644 --- a/src/rendering/swrenderer/drawers/r_draw.cpp +++ b/src/rendering/swrenderer/drawers/r_draw.cpp @@ -51,6 +51,7 @@ #include "r_draw_pal.h" #include "r_thread.h" #include "swrenderer/scene/r_light.h" +#include "polyrenderer/drawers/poly_buffer.h" CVAR(Bool, r_dynlights, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); CVAR(Bool, r_fuzzscale, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); diff --git a/src/rendering/swrenderer/drawers/r_thread.cpp b/src/rendering/swrenderer/drawers/r_thread.cpp index d5b9124fd3..5f1b8c6355 100644 --- a/src/rendering/swrenderer/drawers/r_thread.cpp +++ b/src/rendering/swrenderer/drawers/r_thread.cpp @@ -33,6 +33,7 @@ #include "r_thread.h" #include "swrenderer/r_memory.h" #include "swrenderer/r_renderthread.h" +#include "polyrenderer/drawers/poly_triangle.h" #include #ifdef WIN32 diff --git a/src/rendering/swrenderer/r_swrenderer.cpp b/src/rendering/swrenderer/r_swrenderer.cpp index c2536e3d20..f0d2830d37 100644 --- a/src/rendering/swrenderer/r_swrenderer.cpp +++ b/src/rendering/swrenderer/r_swrenderer.cpp @@ -48,7 +48,6 @@ #include "textures/textures.h" #include "r_data/voxels.h" #include "drawers/r_draw_rgba.h" -#include "polyrenderer/poly_renderer.h" #include "p_setup.h" #include "g_levellocals.h" #include "image.h" @@ -185,22 +184,11 @@ void FSoftwareRenderer::Precache(uint8_t *texhitlist, TMap & void FSoftwareRenderer::RenderView(player_t *player, DCanvas *target, void *videobuffer, int bufferpitch) { - if (V_IsPolyRenderer()) - { - PolyRenderer::Instance()->Viewpoint = r_viewpoint; - PolyRenderer::Instance()->Viewwindow = r_viewwindow; - PolyRenderer::Instance()->RenderView(player, target, videobuffer, bufferpitch); - r_viewpoint = PolyRenderer::Instance()->Viewpoint; - r_viewwindow = PolyRenderer::Instance()->Viewwindow; - } - else - { - mScene.MainThread()->Viewport->viewpoint = r_viewpoint; - mScene.MainThread()->Viewport->viewwindow = r_viewwindow; - mScene.RenderView(player, target, videobuffer, bufferpitch); - r_viewpoint = mScene.MainThread()->Viewport->viewpoint; - r_viewwindow = mScene.MainThread()->Viewport->viewwindow; - } + mScene.MainThread()->Viewport->viewpoint = r_viewpoint; + mScene.MainThread()->Viewport->viewwindow = r_viewwindow; + mScene.RenderView(player, target, videobuffer, bufferpitch); + r_viewpoint = mScene.MainThread()->Viewport->viewpoint; + r_viewwindow = mScene.MainThread()->Viewport->viewwindow; r_viewpoint.ViewLevel->canvasTextureInfo.UpdateAll([&](AActor *camera, FCanvasTexture *camtex, double fov) { @@ -215,43 +203,22 @@ void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int wi DCanvas pic(width, height, false); // Take a snapshot of the player's view - if (V_IsPolyRenderer()) - { - PolyRenderer::Instance()->Viewpoint = r_viewpoint; - PolyRenderer::Instance()->Viewwindow = r_viewwindow; - PolyRenderer::Instance()->RenderViewToCanvas(player->mo, &pic, 0, 0, width, height, true); - r_viewpoint = PolyRenderer::Instance()->Viewpoint; - r_viewwindow = PolyRenderer::Instance()->Viewwindow; - } - else - { - mScene.MainThread()->Viewport->viewpoint = r_viewpoint; - mScene.MainThread()->Viewport->viewwindow = r_viewwindow; - mScene.RenderViewToCanvas(player->mo, &pic, 0, 0, width, height); - r_viewpoint = mScene.MainThread()->Viewport->viewpoint; - r_viewwindow = mScene.MainThread()->Viewport->viewwindow; - } + mScene.MainThread()->Viewport->viewpoint = r_viewpoint; + mScene.MainThread()->Viewport->viewwindow = r_viewwindow; + mScene.RenderViewToCanvas(player->mo, &pic, 0, 0, width, height); + r_viewpoint = mScene.MainThread()->Viewport->viewpoint; + r_viewwindow = mScene.MainThread()->Viewport->viewwindow; + DoWriteSavePic(file, SS_PAL, pic.GetPixels(), width, height, r_viewpoint.sector, false); } void FSoftwareRenderer::DrawRemainingPlayerSprites() { - if (!V_IsPolyRenderer()) - { - mScene.MainThread()->Viewport->viewpoint = r_viewpoint; - mScene.MainThread()->Viewport->viewwindow = r_viewwindow; - mScene.MainThread()->PlayerSprites->RenderRemaining(); - r_viewpoint = mScene.MainThread()->Viewport->viewpoint; - r_viewwindow = mScene.MainThread()->Viewport->viewwindow; - } - else - { - PolyRenderer::Instance()->Viewpoint = r_viewpoint; - PolyRenderer::Instance()->Viewwindow = r_viewwindow; - PolyRenderer::Instance()->RenderRemainingPlayerSprites(); - r_viewpoint = PolyRenderer::Instance()->Viewpoint; - r_viewwindow = PolyRenderer::Instance()->Viewwindow; - } + mScene.MainThread()->Viewport->viewpoint = r_viewpoint; + mScene.MainThread()->Viewport->viewwindow = r_viewwindow; + mScene.MainThread()->PlayerSprites->RenderRemaining(); + r_viewpoint = mScene.MainThread()->Viewport->viewpoint; + r_viewwindow = mScene.MainThread()->Viewport->viewwindow; } void FSoftwareRenderer::SetClearColor(int color) @@ -261,9 +228,9 @@ void FSoftwareRenderer::SetClearColor(int color) void FSoftwareRenderer::RenderTextureView (FCanvasTexture *camtex, AActor *viewpoint, double fov) { - auto renderTarget = V_IsPolyRenderer() ? PolyRenderer::Instance()->RenderTarget : mScene.MainThread()->Viewport->RenderTarget; - auto &cameraViewpoint = V_IsPolyRenderer() ? PolyRenderer::Instance()->Viewpoint : mScene.MainThread()->Viewport->viewpoint; - auto &cameraViewwindow = V_IsPolyRenderer() ? PolyRenderer::Instance()->Viewwindow : mScene.MainThread()->Viewport->viewwindow; + auto renderTarget = mScene.MainThread()->Viewport->RenderTarget; + auto &cameraViewpoint = mScene.MainThread()->Viewport->viewpoint; + auto &cameraViewwindow = mScene.MainThread()->Viewport->viewwindow; // Grab global state shared with rest of zdoom cameraViewpoint = r_viewpoint; @@ -280,10 +247,7 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *camtex, AActor *viewp DAngle savedfov = cameraViewpoint.FieldOfView; R_SetFOV (cameraViewpoint, fov); - if (V_IsPolyRenderer()) - PolyRenderer::Instance()->RenderViewToCanvas(viewpoint, Canvas, 0, 0, tex->GetWidth(), tex->GetHeight(), camtex->bFirstUpdate); - else - mScene.RenderViewToCanvas(viewpoint, Canvas, 0, 0, tex->GetWidth(), tex->GetHeight(), camtex->bFirstUpdate); + mScene.RenderViewToCanvas(viewpoint, Canvas, 0, 0, tex->GetWidth(), tex->GetHeight(), camtex->bFirstUpdate); R_SetFOV (cameraViewpoint, savedfov); diff --git a/src/rendering/swrenderer/scene/r_light.h b/src/rendering/swrenderer/scene/r_light.h index 7714527e73..d14c73b556 100644 --- a/src/rendering/swrenderer/scene/r_light.h +++ b/src/rendering/swrenderer/scene/r_light.h @@ -86,6 +86,7 @@ namespace swrenderer double FlatPlaneVis(int screenY, double planeheight, bool foggy, RenderViewport *viewport) const { return FlatPlaneGlobVis(foggy) / planeheight * fabs(viewport->CenterY - screenY); } double SlopePlaneGlobVis(bool foggy) const { return (NoLightFade && !foggy) ? 0.0f : TiltVisibility; } + double SpriteGlobVis(bool foggy) const { return (NoLightFade && !foggy) ? 0.0f : WallVisibility; } static fixed_t LightLevelToShade(int lightlevel, bool foggy, RenderViewport *viewport) { return LightLevelToShadeImpl(viewport, lightlevel + ActualExtraLight(foggy, viewport), foggy); } @@ -93,7 +94,6 @@ namespace swrenderer private: double WallGlobVis(bool foggy) const { return (NoLightFade && !foggy) ? 0.0f : WallVisibility; } - double SpriteGlobVis(bool foggy) const { return (NoLightFade && !foggy) ? 0.0f : WallVisibility; } double FlatPlaneGlobVis(bool foggy) const { return (NoLightFade && !foggy) ? 0.0f : FloorVisibility; } static fixed_t LightLevelToShadeImpl(RenderViewport *viewport, int lightlevel, bool foggy); diff --git a/src/rendering/swrenderer/things/r_model.cpp b/src/rendering/swrenderer/things/r_model.cpp index 824b4be90b..079b451990 100644 --- a/src/rendering/swrenderer/things/r_model.cpp +++ b/src/rendering/swrenderer/things/r_model.cpp @@ -83,10 +83,10 @@ namespace swrenderer return; bool foggy = false; - int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4; + int actualextralight = foggy ? 0 : thread->Viewport->viewpoint.extralight << 4; bool fullbrightSprite = ((actor->renderflags & RF_FULLBRIGHT) || (actor->flags5 & MF5_BRIGHT)); renderer.lightlevel = fullbrightSprite ? 255 : actor->Sector->lightlevel + actualextralight; - renderer.visibility = PolyRenderer::Instance()->Light.SpriteGlobVis(foggy); + renderer.visibility = thread->Light->SpriteGlobVis(foggy); renderer.fillcolor = actor->fillcolor; renderer.Translation = actor->Translation; @@ -128,10 +128,10 @@ namespace swrenderer return; bool foggy = false; - int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4; + int actualextralight = foggy ? 0 : thread->Viewport->viewpoint.extralight << 4; bool fullbrightSprite = isBright(psp); renderer.lightlevel = fullbrightSprite ? 255 : playermo->Sector->lightlevel + actualextralight; - renderer.visibility = PolyRenderer::Instance()->Light.SpriteGlobVis(foggy); + renderer.visibility = thread->Light->SpriteGlobVis(foggy); PalEntry ThingColor = (playermo->RenderStyle.Flags & STYLEF_ColorIsFixed) ? playermo->fillcolor : 0xffffff; ThingColor.a = 255; @@ -354,7 +354,8 @@ namespace swrenderer { PolyDrawArgs args; auto nc = !!(sector->Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING); - args.SetLight(GetSpriteColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], nc), lightlevel, visibility, fullbrightSprite); args.SetLights(Lights, NumLights); + args.SetLight(GetSpriteColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], nc), lightlevel, visibility, fullbrightSprite); + args.SetLights(Lights, NumLights); args.SetNormal(FVector3(0.0f, 0.0f, 0.0f)); args.SetStyle(RenderStyle, RenderAlpha, fillcolor, Translation, SkinTexture->GetSoftwareTexture(), fullbrightSprite); args.SetDepthTest(true); @@ -371,7 +372,8 @@ namespace swrenderer { PolyDrawArgs args; auto nc = !!(sector->Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING); - args.SetLight(GetSpriteColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], nc), lightlevel, visibility, fullbrightSprite); args.SetLights(Lights, NumLights); + args.SetLight(GetSpriteColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], nc), lightlevel, visibility, fullbrightSprite); + args.SetLights(Lights, NumLights); args.SetNormal(FVector3(0.0f, 0.0f, 0.0f)); args.SetStyle(RenderStyle, RenderAlpha, fillcolor, Translation, SkinTexture->GetSoftwareTexture(), fullbrightSprite); args.SetDepthTest(true); diff --git a/src/rendering/swrenderer/viewport/r_viewport.h b/src/rendering/swrenderer/viewport/r_viewport.h index 87d14761dd..10a6657324 100644 --- a/src/rendering/swrenderer/viewport/r_viewport.h +++ b/src/rendering/swrenderer/viewport/r_viewport.h @@ -5,6 +5,7 @@ #include #include "v_video.h" #include "r_defs.h" +#include "r_utility.h" #include "actorinlines.h" #include "polyrenderer/math/gpu_types.h"