From 0eda298db2e4aadac9248d8e9f5e1a6035ce39cc Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 22 May 2019 06:29:52 +0200 Subject: [PATCH 01/60] - create a renderer backend based on softpoly's drawers --- src/CMakeLists.txt | 13 +- src/gamedata/textures/textures.h | 2 + .../polyrenderer/backend/poly_buffers.cpp | 131 ++++ .../polyrenderer/backend/poly_buffers.h | 72 +++ .../polyrenderer/backend/poly_framebuffer.cpp | 558 ++++++++++++++++++ .../polyrenderer/backend/poly_framebuffer.h | 75 +++ .../polyrenderer/backend/poly_hwtexture.cpp | 131 ++++ .../polyrenderer/backend/poly_hwtexture.h | 45 ++ .../polyrenderer/backend/poly_renderstate.cpp | 178 ++++++ .../polyrenderer/backend/poly_renderstate.h | 50 ++ .../polyrenderer/drawers/poly_draw_args.h | 4 + .../polyrenderer/drawers/poly_triangle.h | 1 + .../polyrenderer/drawers/screen_triangle.cpp | 2 +- .../polyrenderer/drawers/screen_triangle.h | 1 + src/rendering/polyrenderer/math/gpu_types.cpp | 2 +- src/rendering/polyrenderer/math/gpu_types.h | 2 +- src/v_video.cpp | 4 +- src/v_video.h | 2 +- src/win32/hardware.cpp | 9 +- src/win32/win32polyvideo.cpp | 23 + src/win32/win32polyvideo.h | 21 + 21 files changed, 1317 insertions(+), 9 deletions(-) create mode 100644 src/rendering/polyrenderer/backend/poly_buffers.cpp create mode 100644 src/rendering/polyrenderer/backend/poly_buffers.h create mode 100644 src/rendering/polyrenderer/backend/poly_framebuffer.cpp create mode 100644 src/rendering/polyrenderer/backend/poly_framebuffer.h create mode 100644 src/rendering/polyrenderer/backend/poly_hwtexture.cpp create mode 100644 src/rendering/polyrenderer/backend/poly_hwtexture.h create mode 100644 src/rendering/polyrenderer/backend/poly_renderstate.cpp create mode 100644 src/rendering/polyrenderer/backend/poly_renderstate.h create mode 100644 src/win32/win32polyvideo.cpp create mode 100644 src/win32/win32polyvideo.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 463ac9092..384306ed8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -510,7 +510,8 @@ set( PLAT_WIN32_SOURCES win32/gl_sysfb.cpp win32/base_sysfb.cpp win32/win32basevideo.cpp - win32/win32glvideo.cpp) + win32/win32glvideo.cpp + win32/win32polyvideo.cpp) if (HAVE_VULKAN) set (PLAT_WIN32_SOURCES ${PLAT_WIN32_SOURCES} win32/win32vulkanvideo.cpp ) @@ -713,6 +714,7 @@ file( GLOB HEADER_FILES rendering/polyrenderer/math/*.h rendering/polyrenderer/drawers/*.h rendering/polyrenderer/scene/*.h + rendering/polyrenderer/backend/*.h rendering/hwrenderer/data/*.h rendering/hwrenderer/dynlights/*.h rendering/hwrenderer/models/*.h @@ -927,6 +929,14 @@ if (HAVE_VULKAN) set (FASTMATH_SOURCES ${FASTMATH_SOURCES} ${VULKAN_SOURCES}) endif() +set (POLYBACKEND_SOURCES + rendering/polyrenderer/backend/poly_framebuffer.cpp + rendering/polyrenderer/backend/poly_buffers.cpp + rendering/polyrenderer/backend/poly_hwtexture.cpp + rendering/polyrenderer/backend/poly_renderstate.cpp +) +set (FASTMATH_SOURCES ${FASTMATH_SOURCES} ${POLYBACKEND_SOURCES}) + set (PCH_SOURCES am_map.cpp b_bot.cpp @@ -1555,6 +1565,7 @@ source_group("Rendering\\Poly Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOU 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/.+") source_group("Render Interface" FILES r_defs.h r_renderer.h r_sky.cpp r_sky.h r_state.h r_utility.cpp r_utility.h) diff --git a/src/gamedata/textures/textures.h b/src/gamedata/textures/textures.h index 6f5e649fd..5b12de327 100644 --- a/src/gamedata/textures/textures.h +++ b/src/gamedata/textures/textures.h @@ -294,9 +294,11 @@ class FTexture friend class FMaterial; friend class OpenGLRenderer::FGLRenderState; // For now this needs access to some fields in ApplyMaterial. This should be rerouted through the Material class friend class VkRenderState; + friend class PolyRenderState; friend struct FTexCoordInfo; friend class OpenGLRenderer::FHardwareTexture; friend class VkHardwareTexture; + friend class PolyHardwareTexture; friend class FMultiPatchTexture; friend class FSkyBox; friend class FBrightmapTexture; diff --git a/src/rendering/polyrenderer/backend/poly_buffers.cpp b/src/rendering/polyrenderer/backend/poly_buffers.cpp new file mode 100644 index 000000000..7ca4d1768 --- /dev/null +++ b/src/rendering/polyrenderer/backend/poly_buffers.cpp @@ -0,0 +1,131 @@ + +#include "poly_buffers.h" +#include "poly_framebuffer.h" +#include "poly_renderstate.h" +#include "doomerrors.h" + +PolyBuffer *PolyBuffer::First = nullptr; + +PolyBuffer::PolyBuffer() +{ + Next = First; + First = this; + if (Next) Next->Prev = this; +} + +PolyBuffer::~PolyBuffer() +{ + if (Next) Next->Prev = Prev; + if (Prev) Prev->Next = Next; + else First = Next; +} + +void PolyBuffer::ResetAll() +{ + for (PolyBuffer *cur = PolyBuffer::First; cur; cur = cur->Next) + cur->Reset(); +} + +void PolyBuffer::Reset() +{ +} + +void PolyBuffer::SetData(size_t size, const void *data, bool staticdata) +{ + mData.resize(size); + map = mData.data(); + if (data) + memcpy(map, data, size); + buffersize = size; +} + +void PolyBuffer::SetSubData(size_t offset, size_t size, const void *data) +{ + memcpy(static_cast(map) + offset, data, size); +} + +void PolyBuffer::Resize(size_t newsize) +{ + mData.resize(newsize); + buffersize = newsize; + map = mData.data(); +} + +void PolyBuffer::Map() +{ +} + +void PolyBuffer::Unmap() +{ +} + +void *PolyBuffer::Lock(unsigned int size) +{ + return map; +} + +void PolyBuffer::Unlock() +{ +} + +///////////////////////////////////////////////////////////////////////////// + +void PolyVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) +{ + for (int j = 0; j < numAttributes; j++) + { + mOffsets[attrs[j].location] = attrs[j].offset; + } + mStride = stride; +} + +void PolyVertexBuffer::CopyVertices(TriVertex *dst, int count, int index) +{ + size_t stride = mStride; + size_t offsetVertex = mOffsets[VATTR_VERTEX]; + size_t offsetTexcoord = mOffsets[VATTR_TEXCOORD]; + uint8_t *vertex = static_cast(map) + stride * index; + + for (int i = 0; i < count; i++) + { + dst[i].x = *reinterpret_cast(vertex + offsetVertex); + dst[i].y = *reinterpret_cast(vertex + offsetVertex + 4); + dst[i].z = *reinterpret_cast(vertex + offsetVertex + 8); + dst[i].w = 1.0f; + dst[i].v = *reinterpret_cast(vertex + offsetTexcoord); + dst[i].u = *reinterpret_cast(vertex + offsetTexcoord + 4); + vertex += stride; + } +} + +void PolyVertexBuffer::CopyIndexed(TriVertex *dst, uint32_t *elements, int count, int index) +{ + size_t stride = mStride; + size_t offsetVertex = mOffsets[VATTR_VERTEX]; + size_t offsetTexcoord = mOffsets[VATTR_TEXCOORD]; + uint8_t *vertices = static_cast(map); + + elements += index; + for (int i = 0; i < count; i++) + { + uint8_t *vertex = vertices + stride * elements[i]; + dst[i].x = *reinterpret_cast(vertex + offsetVertex); + dst[i].y = *reinterpret_cast(vertex + offsetVertex + 4); + dst[i].z = *reinterpret_cast(vertex + offsetVertex + 8); + dst[i].w = 1.0f; + dst[i].v = *reinterpret_cast(vertex + offsetTexcoord); + dst[i].u = *reinterpret_cast(vertex + offsetTexcoord + 4); + } +} + +///////////////////////////////////////////////////////////////////////////// + +void PolyDataBuffer::BindRange(size_t start, size_t length) +{ + GetPolyFrameBuffer()->GetRenderState()->Bind(this, (uint32_t)start, (uint32_t)length); +} + +void PolyDataBuffer::BindBase() +{ + GetPolyFrameBuffer()->GetRenderState()->Bind(this, 0, (uint32_t)buffersize); +} diff --git a/src/rendering/polyrenderer/backend/poly_buffers.h b/src/rendering/polyrenderer/backend/poly_buffers.h new file mode 100644 index 000000000..49375c7d0 --- /dev/null +++ b/src/rendering/polyrenderer/backend/poly_buffers.h @@ -0,0 +1,72 @@ +#pragma once + +#include "hwrenderer/data/buffers.h" +#include "utility/tarray.h" +#include + +#ifdef _MSC_VER +// silence bogus warning C4250: 'PolyVertexBuffer': inherits 'PolyBuffer::PolyBuffer::SetData' via dominance +// According to internet infos, the warning is erroneously emitted in this case. +#pragma warning(disable:4250) +#endif + +struct TriVertex; + +class PolyBuffer : virtual public IBuffer +{ +public: + PolyBuffer(); + ~PolyBuffer(); + + static void ResetAll(); + void Reset(); + + void SetData(size_t size, const void *data, bool staticdata) override; + void SetSubData(size_t offset, size_t size, const void *data) override; + void Resize(size_t newsize) override; + + void Map() override; + void Unmap() override; + + void *Lock(unsigned int size) override; + void Unlock() override; + +private: + static PolyBuffer *First; + PolyBuffer *Prev = nullptr; + PolyBuffer *Next = nullptr; + std::vector mData; +}; + +class PolyVertexBuffer : public IVertexBuffer, public PolyBuffer +{ +public: + PolyVertexBuffer() { } + void SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) override; + + void CopyVertices(TriVertex *dst, int count, int index); + void CopyIndexed(TriVertex *dst, uint32_t *elements, int count, int index); + +private: + size_t mOffsets[VATTR_MAX] = {}; + size_t mStride = 0; +}; + +class PolyIndexBuffer : public IIndexBuffer, public PolyBuffer +{ +public: + PolyIndexBuffer() { } +}; + +class PolyDataBuffer : public IDataBuffer, public PolyBuffer +{ +public: + PolyDataBuffer(int bindingpoint, bool ssbo, bool needresize) : bindingpoint(bindingpoint) + { + } + + void BindRange(size_t start, size_t length) override; + void BindBase() override; + + int bindingpoint; +}; diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp new file mode 100644 index 000000000..0a261462d --- /dev/null +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -0,0 +1,558 @@ + +#include "v_video.h" +#include "m_png.h" +#include "templates.h" +#include "r_videoscale.h" +#include "actor.h" +#include "i_time.h" +#include "g_game.h" +#include "gamedata/fonts/v_text.h" + +#include "hwrenderer/utility/hw_clock.h" +#include "hwrenderer/utility/hw_vrmodes.h" +#include "hwrenderer/utility/hw_cvars.h" +#include "hwrenderer/models/hw_models.h" +#include "hwrenderer/scene/hw_skydome.h" +#include "hwrenderer/scene/hw_fakeflat.h" +#include "hwrenderer/scene/hw_drawinfo.h" +#include "hwrenderer/scene/hw_portal.h" +#include "hwrenderer/data/hw_viewpointbuffer.h" +#include "hwrenderer/data/flatvertices.h" +#include "hwrenderer/data/shaderuniforms.h" +#include "hwrenderer/dynlights/hw_lightbuffer.h" +#include "hwrenderer/postprocessing/hw_postprocess.h" + +#include "swrenderer/r_swscene.h" + +#include "poly_framebuffer.h" +#include "poly_buffers.h" +#include "poly_renderstate.h" +#include "poly_hwtexture.h" +#include "doomerrors.h" + +void Draw2D(F2DDrawer *drawer, FRenderState &state); +void DoWriteSavePic(FileWriter *file, ESSType ssformat, uint8_t *scr, int width, int height, sector_t *viewsector, bool upsidedown); + +EXTERN_CVAR(Bool, r_drawvoxels) +EXTERN_CVAR(Int, gl_tonemap) +EXTERN_CVAR(Int, screenblocks) +EXTERN_CVAR(Bool, cl_capfps) +EXTERN_CVAR(Bool, gl_no_skyclear) + +extern bool NoInterpolateView; +extern int rendered_commandbuffers; +extern int current_rendered_commandbuffers; + +extern bool gpuStatActive; +extern bool keepGpuStatActive; +extern FString gpuStatOutput; + +#ifdef WIN32 +void I_PresentPolyImage(int w, int h, const void *pixels); +#else +void I_PresentPolyImage(int w, int h, const void *pixels) { } +#endif + +PolyFrameBuffer::PolyFrameBuffer(void *hMonitor, bool fullscreen) : Super(hMonitor, fullscreen) +{ +} + +PolyFrameBuffer::~PolyFrameBuffer() +{ + // screen is already null at this point, but PolyHardwareTexture::ResetAll needs it during clean up. Is there a better way we can do this? + auto tmp = screen; + screen = this; + + PolyHardwareTexture::ResetAll(); + PolyBuffer::ResetAll(); + PPResource::ResetAll(); + + delete mVertexData; + delete mSkyData; + delete mViewpoints; + delete mLights; + mShadowMap.Reset(); + + screen = tmp; +} + +void PolyFrameBuffer::InitializeState() +{ + gl_vendorstring = "Poly"; + hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE; + glslversion = 4.50f; + uniformblockalignment = 1; + maxuniformblock = 0x7fffffff; + + mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight()); + mSkyData = new FSkyVertexBuffer; + mViewpoints = new GLViewpointBuffer; + mLights = new FLightBuffer(); + + mRenderState.reset(new PolyRenderState()); + + CheckCanvas(); + + PolyTriangleDrawer::SetTransform(GetDrawCommands(), GetFrameMemory()->NewObject(Mat4f::Identity()), nullptr); +} + +void PolyFrameBuffer::CheckCanvas() +{ + if (!mCanvas || mCanvas->GetWidth() != GetWidth() || mCanvas->GetHeight() != GetHeight()) + { + DrawerThreads::WaitForWorkers(); + + mCanvas.reset(new DCanvas(0, 0, true)); + mCanvas->Resize(GetWidth(), GetHeight(), false); + + PolyTriangleDrawer::SetViewport(GetDrawCommands(), 0, 0, mCanvas->GetWidth(), mCanvas->GetHeight(), mCanvas.get()); + } +} + +const DrawerCommandQueuePtr &PolyFrameBuffer::GetDrawCommands() +{ + if (!mDrawCommands) + mDrawCommands = std::make_shared(&mFrameMemory); + return mDrawCommands; +} + +void PolyFrameBuffer::FlushDrawCommands() +{ + if (mDrawCommands) + { + DrawerThreads::Execute(mDrawCommands); + mDrawCommands.reset(); + } +} + +void PolyFrameBuffer::Update() +{ + twoD.Reset(); + Flush3D.Reset(); + + Flush3D.Clock(); + + Draw2D(); + Clear2D(); + + Flush3D.Unclock(); + + FlushDrawCommands(); + DrawerThreads::WaitForWorkers(); + mFrameMemory.Clear(); + + if (mCanvas && GetClientWidth() == mCanvas->GetWidth() && GetClientHeight() == mCanvas->GetHeight()) + { + I_PresentPolyImage(mCanvas->GetWidth(), mCanvas->GetHeight(), mCanvas->GetPixels()); + } + + CheckCanvas(); + PolyTriangleDrawer::SetTransform(GetDrawCommands(), GetFrameMemory()->NewObject(Mat4f::Identity()), nullptr); + + Super::Update(); +} + + +void PolyFrameBuffer::WriteSavePic(player_t *player, FileWriter *file, int width, int height) +{ + if (!V_IsHardwareRenderer()) + { + Super::WriteSavePic(player, file, width, height); + } + else + { + } +} + +sector_t *PolyFrameBuffer::RenderView(player_t *player) +{ + // To do: this is virtually identical to FGLRenderer::RenderView and should be merged. + + mRenderState->SetVertexBuffer(screen->mVertexData); + screen->mVertexData->Reset(); + + sector_t *retsec; + if (!V_IsHardwareRenderer()) + { + if (!swdrawer) swdrawer.reset(new SWSceneDrawer); + retsec = swdrawer->RenderView(player); + } + else + { + hw_ClearFakeFlat(); + + iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0; + + checkBenchActive(); + + // reset statistics counters + ResetProfilingData(); + + // Get this before everything else + if (cl_capfps || r_NoInterpolate) r_viewpoint.TicFrac = 1.; + else r_viewpoint.TicFrac = I_GetTimeFrac(); + + screen->mLights->Clear(); + screen->mViewpoints->Clear(); + + // NoInterpolateView should have no bearing on camera textures, but needs to be preserved for the main view below. + bool saved_niv = NoInterpolateView; + NoInterpolateView = false; + + // Shader start time does not need to be handled per level. Just use the one from the camera to render from. + GetRenderState()->CheckTimer(player->camera->Level->ShaderStartTime); + // prepare all camera textures that have been used in the last frame. + // This must be done for all levels, not just the primary one! + for (auto Level : AllLevels()) + { + Level->canvasTextureInfo.UpdateAll([&](AActor *camera, FCanvasTexture *camtex, double fov) + { + RenderTextureView(camtex, camera, fov); + }); + } + NoInterpolateView = saved_niv; + + // now render the main view + float fovratio; + float ratio = r_viewwindow.WidescreenRatio; + if (r_viewwindow.WidescreenRatio >= 1.3f) + { + fovratio = 1.333333f; + } + else + { + fovratio = ratio; + } + + retsec = RenderViewpoint(r_viewpoint, player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true); + } + All.Unclock(); + return retsec; +} + +sector_t *PolyFrameBuffer::RenderViewpoint(FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen) +{ + // To do: this is virtually identical to FGLRenderer::RenderViewpoint and should be merged. + + R_SetupFrame(mainvp, r_viewwindow, camera); + + if (mainview && toscreen) + UpdateShadowMap(); + + // Update the attenuation flag of all light defaults for each viewpoint. + // This function will only do something if the setting differs. + FLightDefaults::SetAttenuationForLevel(!!(camera->Level->flags3 & LEVEL3_ATTENUATE)); + + // Render (potentially) multiple views for stereo 3d + // Fixme. The view offsetting should be done with a static table and not require setup of the entire render state for the mode. + auto vrmode = VRMode::GetVRMode(mainview && toscreen); + for (int eye_ix = 0; eye_ix < vrmode->mEyeCount; ++eye_ix) + { + const auto &eye = vrmode->mEyes[eye_ix]; + screen->SetViewportRects(bounds); + + if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao + { + //mRenderState->SetRenderTarget(GetBuffers()->SceneColor.View.get(), GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), Poly_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); + bool useSSAO = (gl_ssao != 0); + GetRenderState()->SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS); + GetRenderState()->EnableDrawBuffers(GetRenderState()->GetPassDrawBufferCount()); + } + + auto di = HWDrawInfo::StartDrawInfo(mainvp.ViewLevel, nullptr, mainvp, nullptr); + auto &vp = di->Viewpoint; + + di->Set3DViewport(*GetRenderState()); + di->SetViewArea(); + auto cm = di->SetFullbrightFlags(mainview ? vp.camera->player : nullptr); + di->Viewpoint.FieldOfView = fov; // Set the real FOV for the current scene (it's not necessarily the same as the global setting in r_viewpoint) + + // Stereo mode specific perspective projection + di->VPUniforms.mProjectionMatrix = eye.GetProjection(fov, ratio, fovratio); + // Stereo mode specific viewpoint adjustment + vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees); + di->SetupView(*GetRenderState(), vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false); + + // std::function until this can be done better in a cross-API fashion. + di->ProcessScene(toscreen, [&](HWDrawInfo *di, int mode) { + DrawScene(di, mode); + }); + + if (mainview) + { + PostProcess.Clock(); + if (toscreen) di->EndDrawScene(mainvp.sector, *GetRenderState()); // do not call this for camera textures. + + if (GetRenderState()->GetPassType() == GBUFFER_PASS) // Turn off ssao draw buffers + { + GetRenderState()->SetPassType(NORMAL_PASS); + GetRenderState()->EnableDrawBuffers(1); + } + + //mPostprocess->BlitSceneToPostprocess(); // Copy the resulting scene to the current post process texture + + PostProcessScene(cm, [&]() { di->DrawEndScene2D(mainvp.sector, *GetRenderState()); }); + + PostProcess.Unclock(); + } + di->EndDrawInfo(); + +#if 0 + if (vrmode->mEyeCount > 1) + mBuffers->BlitToEyeTexture(eye_ix); +#endif + } + + return mainvp.sector; +} + +void PolyFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV) +{ +#if 0 + // This doesn't need to clear the fake flat cache. It can be shared between camera textures and the main view of a scene. + FMaterial *mat = FMaterial::ValidateTexture(tex, false); + auto BaseLayer = static_cast(mat->GetLayer(0, 0)); + + int width = mat->TextureWidth(); + int height = mat->TextureHeight(); + PolyTextureImage *image = BaseLayer->GetImage(tex, 0, 0); + PolyTextureImage *depthStencil = BaseLayer->GetDepthStencil(tex); + + mRenderState->EndRenderPass(); + + PolyImageTransition barrier0; + barrier0.addImage(image, Poly_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); + barrier0.execute(GetDrawCommands()); + + mRenderState->SetRenderTarget(image->View.get(), depthStencil->View.get(), image->Image->width, image->Image->height, Poly_FORMAT_R8G8B8A8_UNORM, Poly_SAMPLE_COUNT_1_BIT); + + IntRect bounds; + bounds.left = bounds.top = 0; + bounds.width = MIN(mat->GetWidth(), image->Image->width); + bounds.height = MIN(mat->GetHeight(), image->Image->height); + + FRenderViewpoint texvp; + RenderViewpoint(texvp, Viewpoint, &bounds, FOV, (float)width / height, (float)width / height, false, false); + + mRenderState->EndRenderPass(); + + PolyImageTransition barrier1; + barrier1.addImage(image, Poly_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); + barrier1.execute(GetDrawCommands()); + + mRenderState->SetRenderTarget(GetBuffers()->SceneColor.View.get(), GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), Poly_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); + + tex->SetUpdated(true); +#endif +} + +void PolyFrameBuffer::DrawScene(HWDrawInfo *di, int drawmode) +{ + // To do: this is virtually identical to FGLRenderer::DrawScene and should be merged. + + static int recursion = 0; + static int ssao_portals_available = 0; + const auto &vp = di->Viewpoint; + + bool applySSAO = false; + if (drawmode == DM_MAINVIEW) + { + ssao_portals_available = gl_ssao_portals; + applySSAO = true; + } + else if (drawmode == DM_OFFSCREEN) + { + ssao_portals_available = 0; + } + else if (drawmode == DM_PORTAL && ssao_portals_available > 0) + { + applySSAO = true; + ssao_portals_available--; + } + + if (vp.camera != nullptr) + { + ActorRenderFlags savedflags = vp.camera->renderflags; + di->CreateScene(drawmode == DM_MAINVIEW); + vp.camera->renderflags = savedflags; + } + else + { + di->CreateScene(false); + } + + GetRenderState()->SetDepthMask(true); + if (!gl_no_skyclear) screen->mPortalState->RenderFirstSkyPortal(recursion, di, *GetRenderState()); + + di->RenderScene(*GetRenderState()); + + if (applySSAO && GetRenderState()->GetPassType() == GBUFFER_PASS) + { + //mPostprocess->AmbientOccludeScene(di->VPUniforms.mProjectionMatrix.get()[5]); + //screen->mViewpoints->Bind(*GetRenderState(), di->vpIndex); + } + + // Handle all portals after rendering the opaque objects but before + // doing all translucent stuff + recursion++; + screen->mPortalState->EndFrame(di, *GetRenderState()); + recursion--; + di->RenderTranslucent(*GetRenderState()); +} + +void PolyFrameBuffer::PostProcessScene(int fixedcm, const std::function &afterBloomDrawEndScene2D) +{ + afterBloomDrawEndScene2D(); +} + +uint32_t PolyFrameBuffer::GetCaps() +{ + if (!V_IsHardwareRenderer()) + return Super::GetCaps(); + + // describe our basic feature set + ActorRenderFeatureFlags FlagSet = RFF_FLATSPRITES | RFF_MODELS | RFF_SLOPE3DFLOORS | + RFF_TILTPITCH | RFF_ROLLSPRITES | RFF_POLYGONAL | RFF_MATSHADER | RFF_POSTSHADER | RFF_BRIGHTMAP; + if (r_drawvoxels) + FlagSet |= RFF_VOXELS; + + if (gl_tonemap != 5) // not running palette tonemap shader + FlagSet |= RFF_TRUECOLOR; + + return (uint32_t)FlagSet; +} + +void PolyFrameBuffer::SetVSync(bool vsync) +{ + // This is handled in PolySwapChain::AcquireImage. +} + +void PolyFrameBuffer::CleanForRestart() +{ + // force recreation of the SW scene drawer to ensure it gets a new set of resources. + swdrawer.reset(); +} + +void PolyFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) +{ + auto tex = mat->tex; + if (tex->isSWCanvas()) return; + + // Textures that are already scaled in the texture lump will not get replaced by hires textures. + int flags = mat->isExpanded() ? CTF_Expand : (gl_texture_usehires && !tex->isScaled()) ? CTF_CheckHires : 0; + auto base = static_cast(mat->GetLayer(0, translation)); + + base->Precache(mat, translation, flags); +} + +IHardwareTexture *PolyFrameBuffer::CreateHardwareTexture() +{ + return new PolyHardwareTexture(); +} + +FModelRenderer *PolyFrameBuffer::CreateModelRenderer(int mli) +{ + return new FHWModelRenderer(nullptr, *GetRenderState(), mli); +} + +IVertexBuffer *PolyFrameBuffer::CreateVertexBuffer() +{ + return new PolyVertexBuffer(); +} + +IIndexBuffer *PolyFrameBuffer::CreateIndexBuffer() +{ + return new PolyIndexBuffer(); +} + +IDataBuffer *PolyFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) +{ + return new PolyDataBuffer(bindingpoint, ssbo, needsresize); +} + +void PolyFrameBuffer::SetTextureFilterMode() +{ + TextureFilterChanged(); +} + +void PolyFrameBuffer::TextureFilterChanged() +{ +} + +void PolyFrameBuffer::StartPrecaching() +{ +} + +void PolyFrameBuffer::BlurScene(float amount) +{ +} + +void PolyFrameBuffer::UpdatePalette() +{ +} + +FTexture *PolyFrameBuffer::WipeStartScreen() +{ + const auto &viewport = screen->mScreenViewport; + auto tex = new FWrapperTexture(viewport.width, viewport.height, 1); + auto systex = static_cast(tex->GetSystemTexture()); + + systex->CreateWipeTexture(viewport.width, viewport.height, "WipeStartScreen"); + + return tex; +} + +FTexture *PolyFrameBuffer::WipeEndScreen() +{ + Draw2D(); + Clear2D(); + + const auto &viewport = screen->mScreenViewport; + auto tex = new FWrapperTexture(viewport.width, viewport.height, 1); + auto systex = static_cast(tex->GetSystemTexture()); + + systex->CreateWipeTexture(viewport.width, viewport.height, "WipeEndScreen"); + + return tex; +} + +TArray PolyFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) +{ + int w = SCREENWIDTH; + int h = SCREENHEIGHT; + + IntRect box; + box.left = 0; + box.top = 0; + box.width = w; + box.height = h; + //mPostprocess->DrawPresentTexture(box, true, true); + + TArray ScreenshotBuffer(w * h * 3, true); + //CopyScreenToBuffer(w, h, ScreenshotBuffer.Data()); + + pitch = w * 3; + color_type = SS_RGB; + gamma = 1.0f; + return ScreenshotBuffer; +} + +void PolyFrameBuffer::BeginFrame() +{ + SetViewportRects(nullptr); + CheckCanvas(); +} + +void PolyFrameBuffer::Draw2D() +{ + ::Draw2D(&m2DDrawer, *mRenderState); +} + +unsigned int PolyFrameBuffer::GetLightBufferBlockSize() const +{ + return mLights->GetBlockSize(); +} + +void PolyFrameBuffer::UpdateShadowMap() +{ +} diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.h b/src/rendering/polyrenderer/backend/poly_framebuffer.h new file mode 100644 index 000000000..3e05d01a2 --- /dev/null +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.h @@ -0,0 +1,75 @@ +#pragma once + +#include "gl_sysfb.h" +#include "rendering/swrenderer/r_memory.h" +#include "rendering/swrenderer/drawers/r_thread.h" +#include "rendering/polyrenderer/drawers/poly_triangle.h" + +struct FRenderViewpoint; +class PolyDataBuffer; +class PolyRenderState; +class SWSceneDrawer; + +class PolyFrameBuffer : public SystemBaseFrameBuffer +{ + typedef SystemBaseFrameBuffer Super; + +public: + RenderMemory *GetFrameMemory() { return &mFrameMemory; } + PolyRenderState *GetRenderState() { return mRenderState.get(); } + const DrawerCommandQueuePtr &GetDrawCommands(); + void FlushDrawCommands(); + + unsigned int GetLightBufferBlockSize() const; + + std::unique_ptr swdrawer; + + PolyFrameBuffer(void *hMonitor, bool fullscreen); + ~PolyFrameBuffer(); + + void Update(); + + void InitializeState() override; + + void CleanForRestart() override; + void PrecacheMaterial(FMaterial *mat, int translation) override; + void UpdatePalette() override; + uint32_t GetCaps() override; + void WriteSavePic(player_t *player, FileWriter *file, int width, int height) override; + sector_t *RenderView(player_t *player) override; + void SetTextureFilterMode() override; + void TextureFilterChanged() override; + void StartPrecaching() override; + void BeginFrame() override; + void BlurScene(float amount) override; + void PostProcessScene(int fixedcm, const std::function &afterBloomDrawEndScene2D) override; + + IHardwareTexture *CreateHardwareTexture() override; + FModelRenderer *CreateModelRenderer(int mli) override; + IVertexBuffer *CreateVertexBuffer() override; + IIndexBuffer *CreateIndexBuffer() override; + IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override; + + FTexture *WipeStartScreen() override; + FTexture *WipeEndScreen() override; + + TArray GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) override; + + void SetVSync(bool vsync) override; + void Draw2D() override; + +private: + sector_t *RenderViewpoint(FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); + void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV); + void DrawScene(HWDrawInfo *di, int drawmode); + void UpdateShadowMap(); + + void CheckCanvas(); + + std::unique_ptr mRenderState; + std::unique_ptr mCanvas; + std::shared_ptr mDrawCommands; + RenderMemory mFrameMemory; +}; + +inline PolyFrameBuffer *GetPolyFrameBuffer() { return static_cast(screen); } diff --git a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp new file mode 100644 index 000000000..9302738be --- /dev/null +++ b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp @@ -0,0 +1,131 @@ + +#include "templates.h" +#include "c_cvars.h" +#include "r_data/colormaps.h" +#include "hwrenderer/textures/hw_material.h" +#include "hwrenderer/utility/hw_cvars.h" +#include "hwrenderer/scene/hw_renderstate.h" +#include "poly_framebuffer.h" +#include "poly_hwtexture.h" + +PolyHardwareTexture *PolyHardwareTexture::First = nullptr; + +PolyHardwareTexture::PolyHardwareTexture() +{ + Next = First; + First = this; + if (Next) Next->Prev = this; +} + +PolyHardwareTexture::~PolyHardwareTexture() +{ + if (Next) Next->Prev = Prev; + if (Prev) Prev->Next = Next; + else First = Next; + + Reset(); +} + +void PolyHardwareTexture::ResetAll() +{ + for (PolyHardwareTexture *cur = PolyHardwareTexture::First; cur; cur = cur->Next) + cur->Reset(); +} + +void PolyHardwareTexture::Reset() +{ +} + +void PolyHardwareTexture::Precache(FMaterial *mat, int translation, int flags) +{ +#if 0 + int numLayers = mat->GetLayers(); + GetImage(mat->tex, translation, flags); + for (int i = 1; i < numLayers; i++) + { + FTexture *layer; + auto systex = static_cast(mat->GetLayer(i, 0, &layer)); + systex->GetImage(layer, 0, mat->isExpanded() ? CTF_Expand : 0); + } +#endif +} + +DCanvas *PolyHardwareTexture::GetImage(const FMaterialState &state) +{ + if (!mCanvas) + { + FMaterial *mat = state.mMaterial; + FTexture *tex = state.mMaterial->tex; + int clampmode = state.mClampMode; + int translation = state.mTranslation; + + if (tex->UseType == ETextureType::SWCanvas) clampmode = CLAMP_NOFILTER; + if (tex->isHardwareCanvas()) clampmode = CLAMP_CAMTEX; + else if ((tex->isWarped() || tex->shaderindex >= FIRST_USER_SHADER) && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE; + + // Textures that are already scaled in the texture lump will not get replaced by hires textures. + int flags = state.mMaterial->isExpanded() ? CTF_Expand : (gl_texture_usehires && !tex->isScaled() && clampmode <= CLAMP_XY) ? CTF_CheckHires : 0; + + if (tex->isHardwareCanvas()) static_cast(tex)->NeedUpdate(); + + CreateImage(tex, translation, flags); + } + + return mCanvas.get(); +} + +void PolyHardwareTexture::AllocateBuffer(int w, int h, int texelsize) +{ + if (!mCanvas || mCanvas->GetWidth() != w || mCanvas->GetHeight() != h) + { + mCanvas.reset(new DCanvas(0, 0, texelsize == 4)); + mCanvas->Resize(w, h, false); + } +} + +uint8_t *PolyHardwareTexture::MapBuffer() +{ + return mCanvas->GetPixels(); +} + +unsigned int PolyHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, const char *name) +{ + return 0; +} + +void PolyHardwareTexture::CreateWipeTexture(int w, int h, const char *name) +{ + if (!mCanvas || mCanvas->GetWidth() != w || mCanvas->GetHeight() != h) + { + mCanvas.reset(new DCanvas(0, 0, true)); + mCanvas->Resize(w, h, false); + } +} + +void PolyHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) +{ + mCanvas.reset(new DCanvas(0, 0, true)); + + if (!tex->isHardwareCanvas()) + { + if (translation <= 0) + { + translation = -translation; + } + else + { + auto remap = TranslationToTable(translation); + translation = remap == nullptr ? 0 : remap->GetUniqueIndex(); + } + + FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData); + mCanvas->Resize(texbuffer.mWidth, texbuffer.mHeight, false); + memcpy(mCanvas->GetPixels(), texbuffer.mBuffer, texbuffer.mWidth * texbuffer.mHeight * 4); + } + else + { + int w = tex->GetWidth(); + int h = tex->GetHeight(); + mCanvas->Resize(w, h, false); + } +} diff --git a/src/rendering/polyrenderer/backend/poly_hwtexture.h b/src/rendering/polyrenderer/backend/poly_hwtexture.h new file mode 100644 index 000000000..84d1147bf --- /dev/null +++ b/src/rendering/polyrenderer/backend/poly_hwtexture.h @@ -0,0 +1,45 @@ +#pragma once + +#ifdef LoadImage +#undef LoadImage +#endif + +#define SHADED_TEXTURE -1 +#define DIRECT_PALETTE -2 + +#include "tarray.h" +#include "hwrenderer/textures/hw_ihwtexture.h" +#include "volk/volk.h" + +struct FMaterialState; +class PolyBuffer; + +class PolyHardwareTexture : public IHardwareTexture +{ +public: + PolyHardwareTexture(); + ~PolyHardwareTexture(); + + static void ResetAll(); + void Reset(); + + void Precache(FMaterial *mat, int translation, int flags); + + DCanvas *GetImage(const FMaterialState &state); + + // Software renderer stuff + void AllocateBuffer(int w, int h, int texelsize) override; + uint8_t *MapBuffer() override; + unsigned int CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, const char *name) override; + + // Wipe screen + void CreateWipeTexture(int w, int h, const char *name); + +private: + void CreateImage(FTexture *tex, int translation, int flags); + + static PolyHardwareTexture *First; + PolyHardwareTexture *Prev = nullptr; + PolyHardwareTexture *Next = nullptr; + std::unique_ptr mCanvas; +}; diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp new file mode 100644 index 000000000..527f3e433 --- /dev/null +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -0,0 +1,178 @@ + +#include "polyrenderer/backend/poly_renderstate.h" +#include "polyrenderer/backend/poly_framebuffer.h" +#include "polyrenderer/backend/poly_hwtexture.h" +#include "templates.h" +#include "doomstat.h" +#include "r_data/colormaps.h" +#include "hwrenderer/scene/hw_skydome.h" +#include "hwrenderer/scene/hw_viewpointuniforms.h" +#include "hwrenderer/dynlights/hw_lightbuffer.h" +#include "hwrenderer/utility/hw_cvars.h" +#include "hwrenderer/utility/hw_clock.h" +#include "hwrenderer/data/flatvertices.h" +#include "hwrenderer/data/hw_viewpointbuffer.h" +#include "hwrenderer/data/shaderuniforms.h" + +static PolyDrawMode dtToDrawMode[] = +{ + PolyDrawMode::Triangles, // DT_Points + PolyDrawMode::Triangles, // DT_Lines + PolyDrawMode::Triangles, // DT_Triangles + PolyDrawMode::TriangleFan, // DT_TriangleFan + PolyDrawMode::TriangleStrip, // DT_TriangleStrip +}; + +PolyRenderState::PolyRenderState() +{ + Reset(); +} + +void PolyRenderState::ClearScreen() +{ + screen->mViewpoints->Set2D(*this, SCREENWIDTH, SCREENHEIGHT); + SetColor(0, 0, 0); + Draw(DT_TriangleStrip, FFlatVertexBuffer::FULLSCREEN_INDEX, 4, true); +} + +void PolyRenderState::Draw(int dt, int index, int count, bool apply) +{ + if (apply) + Apply(); + + auto fb = GetPolyFrameBuffer(); + TriVertex *vertices = fb->GetFrameMemory()->AllocMemory(count); + static_cast(mVertexBuffer)->CopyVertices(vertices, count, index); + PolyTriangleDrawer::DrawArray(fb->GetDrawCommands(), args, vertices, count, dtToDrawMode[dt]); +} + +void PolyRenderState::DrawIndexed(int dt, int index, int count, bool apply) +{ + if (apply) + Apply(); + + auto fb = GetPolyFrameBuffer(); + TriVertex *vertices = fb->GetFrameMemory()->AllocMemory(count); + static_cast(mVertexBuffer)->CopyIndexed(vertices, (uint32_t *)mIndexBuffer->Memory(), count, index); + PolyTriangleDrawer::DrawArray(fb->GetDrawCommands(), args, vertices, count, dtToDrawMode[dt]); +} + +bool PolyRenderState::SetDepthClamp(bool on) +{ + bool lastValue = mDepthClamp; + mDepthClamp = on; + return lastValue; +} + +void PolyRenderState::SetDepthMask(bool on) +{ +} + +void PolyRenderState::SetDepthFunc(int func) +{ +} + +void PolyRenderState::SetDepthRange(float min, float max) +{ +} + +void PolyRenderState::SetColorMask(bool r, bool g, bool b, bool a) +{ +} + +void PolyRenderState::SetStencil(int offs, int op, int flags) +{ +} + +void PolyRenderState::SetCulling(int mode) +{ +} + +void PolyRenderState::EnableClipDistance(int num, bool state) +{ +} + +void PolyRenderState::Clear(int targets) +{ +} + +void PolyRenderState::EnableStencil(bool on) +{ +} + +void PolyRenderState::SetScissor(int x, int y, int w, int h) +{ +} + +void PolyRenderState::SetViewport(int x, int y, int w, int h) +{ +} + +void PolyRenderState::EnableDepthTest(bool on) +{ +} + +void PolyRenderState::EnableMultisampling(bool on) +{ +} + +void PolyRenderState::EnableLineSmooth(bool on) +{ +} + +void PolyRenderState::EnableDrawBuffers(int count) +{ +} + +void PolyRenderState::Apply() +{ + drawcalls.Clock(); + + args.SetStencilTest(false); + args.SetDepthTest(false); + args.SetWriteStencil(false); + args.SetWriteDepth(false); + args.SetNoColormap(); + + args.SetColor(MAKEARGB( + static_cast(mStreamData.uVertexColor.W * 255.0f + 0.5f), + static_cast(mStreamData.uVertexColor.X * 255.0f + 0.5f), + static_cast(mStreamData.uVertexColor.Y * 255.0f + 0.5f), + static_cast(mStreamData.uVertexColor.Z * 255.0f + 0.5f)), 0); + + if (mMaterial.mChanged && mMaterial.mMaterial) + { + auto base = static_cast(mMaterial.mMaterial->GetLayer(0, mMaterial.mTranslation)); + if (base) + { + DCanvas *texcanvas = base->GetImage(mMaterial); + args.SetTexture(texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth()); + args.SetStyle(TriBlendMode::Opaque); + } + else + { + args.SetStyle(TriBlendMode::Fill); + } + + mMaterial.mChanged = false; + } + + auto fb = GetPolyFrameBuffer(); + PolyTriangleDrawer::SetTwoSided(fb->GetDrawCommands(), true); + + drawcalls.Unclock(); +} + +void PolyRenderState::Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t length) +{ + if (buffer->bindingpoint == VIEWPOINT_BINDINGPOINT) + { + HWViewpointUniforms *uniforms = reinterpret_cast(static_cast(buffer->Memory()) + offset); + + Mat4f viewToProj = Mat4f::FromValues(uniforms->mProjectionMatrix.get()); + Mat4f worldToView = Mat4f::FromValues(uniforms->mViewMatrix.get()); + + auto fb = GetPolyFrameBuffer(); + PolyTriangleDrawer::SetTransform(fb->GetDrawCommands(), fb->GetFrameMemory()->NewObject(viewToProj * worldToView), nullptr); + } +} diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.h b/src/rendering/polyrenderer/backend/poly_renderstate.h new file mode 100644 index 000000000..84c9c190a --- /dev/null +++ b/src/rendering/polyrenderer/backend/poly_renderstate.h @@ -0,0 +1,50 @@ + +#pragma once + +#include "polyrenderer/backend/poly_buffers.h" +#include "rendering/polyrenderer/drawers/poly_triangle.h" + +#include "name.h" + +#include "hwrenderer/scene/hw_drawstructs.h" +#include "hwrenderer/scene/hw_renderstate.h" +#include "hwrenderer/textures/hw_material.h" + +class PolyRenderPassSetup; + +class PolyRenderState : public FRenderState +{ +public: + PolyRenderState(); + + // Draw commands + void ClearScreen() override; + void Draw(int dt, int index, int count, bool apply = true) override; + void DrawIndexed(int dt, int index, int count, bool apply = true) override; + + // Immediate render state change commands. These only change infrequently and should not clutter the render state. + bool SetDepthClamp(bool on) override; + void SetDepthMask(bool on) override; + void SetDepthFunc(int func) override; + void SetDepthRange(float min, float max) override; + void SetColorMask(bool r, bool g, bool b, bool a) override; + void SetStencil(int offs, int op, int flags = -1) override; + void SetCulling(int mode) override; + void EnableClipDistance(int num, bool state) override; + void Clear(int targets) override; + void EnableStencil(bool on) override; + void SetScissor(int x, int y, int w, int h) override; + void SetViewport(int x, int y, int w, int h) override; + void EnableDepthTest(bool on) override; + void EnableMultisampling(bool on) override; + void EnableLineSmooth(bool on) override; + void EnableDrawBuffers(int count) override; + + void Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t length); + +private: + void Apply(); + + bool mDepthClamp = true; + PolyDrawArgs args; +}; diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.h b/src/rendering/polyrenderer/drawers/poly_draw_args.h index b40e209a2..0c6a6791a 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.h +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.h @@ -70,7 +70,9 @@ public: void SetTexture(FSoftwareTexture *texture, FRenderStyle style); void SetTexture(FSoftwareTexture *texture, uint32_t translationID, FRenderStyle style); void SetLight(FSWColormap *basecolormap, uint32_t lightlevel, double globVis, bool fixed); + void SetNoColormap() { mLight = 255; mFixedLight = true; mLightRed = 256; mLightGreen = 256; mLightBlue = 256; mLightAlpha = 256; mFadeRed = 0; mFadeGreen = 0; mFadeBlue = 0; mFadeAlpha = 0; mDesaturate = 0; mSimpleShade = true; mColormaps = nullptr; } void SetDepthTest(bool enable) { mDepthTest = enable; } + void SetStencilTest(bool enable) { mStencilTest = enable; } void SetStencilTestValue(uint8_t stencilTestValue) { mStencilTestValue = stencilTestValue; } void SetWriteColor(bool enable) { mWriteColor = enable; } void SetWriteStencil(bool enable, uint8_t stencilWriteValue = 0) { mWriteStencil = enable; mStencilWriteValue = stencilWriteValue; } @@ -92,6 +94,7 @@ public: const uint8_t *Translation() const { return mTranslation; } bool WriteStencil() const { return mWriteStencil; } + bool StencilTest() const { return mStencilTest; } uint8_t StencilTestValue() const { return mStencilTestValue; } uint8_t StencilWriteValue() const { return mStencilWriteValue; } @@ -128,6 +131,7 @@ public: private: bool mDepthTest = false; + bool mStencilTest = true; bool mWriteStencil = true; bool mWriteColor = true; bool mWriteDepth = true; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 1ba182a70..50c0f6ad4 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -29,6 +29,7 @@ #include "polyrenderer/drawers/poly_buffer.h" #include "polyrenderer/drawers/poly_draw_args.h" +class DCanvas; class PolyDrawerCommand; class PolyTriangleDrawer diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index c989a94d1..dc6a66c3c 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -143,7 +143,7 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat int opt = 0; if (args->uniforms->DepthTest()) opt |= SWTRI_DepthTest; - /*if (args->uniforms->StencilTest())*/ opt |= SWTRI_StencilTest; + if (args->uniforms->StencilTest()) opt |= SWTRI_StencilTest; if (args->uniforms->WriteColor()) opt |= SWTRI_WriteColor; if (args->uniforms->WriteDepth()) opt |= SWTRI_WriteDepth; if (args->uniforms->WriteStencil()) opt |= SWTRI_WriteStencil; diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.h b/src/rendering/polyrenderer/drawers/screen_triangle.h index e99260a3f..66ae24f65 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.h +++ b/src/rendering/polyrenderer/drawers/screen_triangle.h @@ -24,6 +24,7 @@ #include #include +#include "r_data/renderstyle.h" class FString; class PolyDrawArgs; diff --git a/src/rendering/polyrenderer/math/gpu_types.cpp b/src/rendering/polyrenderer/math/gpu_types.cpp index 3e3d8182a..7ec8dc331 100644 --- a/src/rendering/polyrenderer/math/gpu_types.cpp +++ b/src/rendering/polyrenderer/math/gpu_types.cpp @@ -42,7 +42,7 @@ Mat4f Mat4f::Identity() return m; } -Mat4f Mat4f::FromValues(float *matrix) +Mat4f Mat4f::FromValues(const float *matrix) { Mat4f m; memcpy(m.Matrix, matrix, sizeof(m.Matrix)); diff --git a/src/rendering/polyrenderer/math/gpu_types.h b/src/rendering/polyrenderer/math/gpu_types.h index 0a0c261dd..6892be46e 100644 --- a/src/rendering/polyrenderer/math/gpu_types.h +++ b/src/rendering/polyrenderer/math/gpu_types.h @@ -115,7 +115,7 @@ class Mat4f public: static Mat4f Null(); static Mat4f Identity(); - static Mat4f FromValues(float *matrix); + static Mat4f FromValues(const float *matrix); static Mat4f Transpose(const Mat4f &matrix); static Mat4f Translate(float x, float y, float z); static Mat4f Scale(float x, float y, float z); diff --git a/src/v_video.cpp b/src/v_video.cpp index 9df371477..e198d9efd 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -210,7 +210,7 @@ DCanvas::~DCanvas () // //========================================================================== -void DCanvas::Resize(int width, int height) +void DCanvas::Resize(int width, int height, bool optimizepitch) { Width = width; Height = height; @@ -221,7 +221,7 @@ void DCanvas::Resize(int width, int height) // longer than the width. The values used here are all based on // empirical evidence. - if (width <= 640) + if (width <= 640 || !optimizepitch) { // For low resolutions, just keep the pitch the same as the width. // Some speedup can be seen using the technique below, but the speedup diff --git a/src/v_video.h b/src/v_video.h index 4c0597c4f..af6283a5c 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -326,7 +326,7 @@ class DCanvas public: DCanvas (int width, int height, bool bgra); ~DCanvas (); - void Resize(int width, int height); + void Resize(int width, int height, bool optimizepitch = true); // Member variable access inline uint8_t *GetPixels () const { return Pixels.Data(); } diff --git a/src/win32/hardware.cpp b/src/win32/hardware.cpp index 7f101112c..467550a36 100644 --- a/src/win32/hardware.cpp +++ b/src/win32/hardware.cpp @@ -44,6 +44,7 @@ #include "m_argv.h" #include "version.h" #include "win32glvideo.h" +#include "win32polyvideo.h" #ifdef HAVE_VULKAN #include "win32vulkanvideo.h" #endif @@ -129,8 +130,12 @@ void I_InitGraphics () // are the active app. Huh? } + if (vid_enablevulkan == 2) + { + Video = new Win32PolyVideo(); + } #ifdef HAVE_VULKAN - if (vid_enablevulkan == 1) + else if (vid_enablevulkan == 1) { // first try Vulkan, if that fails OpenGL try @@ -143,8 +148,8 @@ void I_InitGraphics () Video = new Win32GLVideo(); } } - else #endif + else { Video = new Win32GLVideo(); } diff --git a/src/win32/win32polyvideo.cpp b/src/win32/win32polyvideo.cpp new file mode 100644 index 000000000..faf6c937a --- /dev/null +++ b/src/win32/win32polyvideo.cpp @@ -0,0 +1,23 @@ + +#include +#include "hardware.h" +#include + +extern HWND Window; + +void I_PresentPolyImage(int w, int h, const void *pixels) +{ + BITMAPV5HEADER info = {}; + info.bV5Size = sizeof(BITMAPV5HEADER); + info.bV5Width = w; + info.bV5Height = -h; + info.bV5Planes = 1; + info.bV5BitCount = 32; + info.bV5Compression = BI_RGB; + info.bV5SizeImage = 0; + info.bV5CSType = LCS_WINDOWS_COLOR_SPACE; + + HDC dc = GetDC(Window); + SetDIBitsToDevice(dc, 0, 0, w, h, 0, 0, 0, h, pixels, (const BITMAPINFO *)&info, DIB_RGB_COLORS); + ReleaseDC(Window, dc); +} diff --git a/src/win32/win32polyvideo.h b/src/win32/win32polyvideo.h new file mode 100644 index 000000000..e1ad6d503 --- /dev/null +++ b/src/win32/win32polyvideo.h @@ -0,0 +1,21 @@ +#pragma once + +#include "win32basevideo.h" +#include "c_cvars.h" +#include "rendering/polyrenderer/backend/poly_framebuffer.h" + +EXTERN_CVAR(Bool, fullscreen) + +class Win32PolyVideo : public Win32BaseVideo +{ +public: + void Shutdown() override + { + } + + DFrameBuffer *CreateFrameBuffer() override + { + auto fb = new PolyFrameBuffer(m_hMonitor, fullscreen); + return fb; + } +}; From 48d2d423f6c07b0accd4b0ce2f32216a9b3ad456 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 22 May 2019 17:16:07 +0200 Subject: [PATCH 02/60] - remove softpoly scene drawer --- src/CMakeLists.txt | 17 - .../polyrenderer/drawers/poly_draw_args.cpp | 11 +- .../polyrenderer/drawers/poly_draw_args.h | 2 + .../polyrenderer/drawers/poly_triangle.cpp | 3 +- .../polyrenderer/drawers/poly_triangle.h | 2 + .../polyrenderer/drawers/screen_triangle.cpp | 4 + .../polyrenderer/drawers/screen_triangle.h | 3 + src/rendering/polyrenderer/poly_all.cpp | 15 - src/rendering/polyrenderer/poly_renderer.cpp | 262 ------- src/rendering/polyrenderer/poly_renderer.h | 79 -- .../polyrenderer/poly_renderthread.cpp | 268 ------- .../polyrenderer/poly_renderthread.h | 102 --- .../polyrenderer/scene/poly_cull.cpp | 421 ---------- src/rendering/polyrenderer/scene/poly_cull.h | 86 --- .../polyrenderer/scene/poly_decal.cpp | 284 ------- src/rendering/polyrenderer/scene/poly_decal.h | 38 - .../polyrenderer/scene/poly_light.cpp | 49 -- src/rendering/polyrenderer/scene/poly_light.h | 52 -- .../polyrenderer/scene/poly_model.cpp | 321 -------- src/rendering/polyrenderer/scene/poly_model.h | 93 --- .../polyrenderer/scene/poly_particle.cpp | 117 --- .../polyrenderer/scene/poly_particle.h | 57 -- .../polyrenderer/scene/poly_plane.cpp | 565 -------------- src/rendering/polyrenderer/scene/poly_plane.h | 106 --- .../polyrenderer/scene/poly_playersprite.cpp | 548 ------------- .../polyrenderer/scene/poly_playersprite.h | 106 --- .../polyrenderer/scene/poly_portal.cpp | 258 ------- .../polyrenderer/scene/poly_portal.h | 84 -- .../polyrenderer/scene/poly_scene.cpp | 594 --------------- src/rendering/polyrenderer/scene/poly_scene.h | 129 ---- src/rendering/polyrenderer/scene/poly_sky.cpp | 429 ----------- src/rendering/polyrenderer/scene/poly_sky.h | 68 -- .../polyrenderer/scene/poly_sprite.cpp | 432 ----------- .../polyrenderer/scene/poly_sprite.h | 67 -- .../polyrenderer/scene/poly_wall.cpp | 721 ------------------ src/rendering/polyrenderer/scene/poly_wall.h | 110 --- .../polyrenderer/scene/poly_wallsprite.cpp | 112 --- .../polyrenderer/scene/poly_wallsprite.h | 31 - src/rendering/swrenderer/drawers/r_draw.cpp | 1 + src/rendering/swrenderer/drawers/r_thread.cpp | 1 + src/rendering/swrenderer/r_swrenderer.cpp | 76 +- src/rendering/swrenderer/scene/r_light.h | 2 +- src/rendering/swrenderer/things/r_model.cpp | 14 +- .../swrenderer/viewport/r_viewport.h | 1 + 44 files changed, 48 insertions(+), 6693 deletions(-) delete mode 100644 src/rendering/polyrenderer/poly_renderer.cpp delete mode 100644 src/rendering/polyrenderer/poly_renderer.h delete mode 100644 src/rendering/polyrenderer/poly_renderthread.cpp delete mode 100644 src/rendering/polyrenderer/poly_renderthread.h delete mode 100644 src/rendering/polyrenderer/scene/poly_cull.cpp delete mode 100644 src/rendering/polyrenderer/scene/poly_cull.h delete mode 100644 src/rendering/polyrenderer/scene/poly_decal.cpp delete mode 100644 src/rendering/polyrenderer/scene/poly_decal.h delete mode 100644 src/rendering/polyrenderer/scene/poly_light.cpp delete mode 100644 src/rendering/polyrenderer/scene/poly_light.h delete mode 100644 src/rendering/polyrenderer/scene/poly_model.cpp delete mode 100644 src/rendering/polyrenderer/scene/poly_model.h delete mode 100644 src/rendering/polyrenderer/scene/poly_particle.cpp delete mode 100644 src/rendering/polyrenderer/scene/poly_particle.h delete mode 100644 src/rendering/polyrenderer/scene/poly_plane.cpp delete mode 100644 src/rendering/polyrenderer/scene/poly_plane.h delete mode 100644 src/rendering/polyrenderer/scene/poly_playersprite.cpp delete mode 100644 src/rendering/polyrenderer/scene/poly_playersprite.h delete mode 100644 src/rendering/polyrenderer/scene/poly_portal.cpp delete mode 100644 src/rendering/polyrenderer/scene/poly_portal.h delete mode 100644 src/rendering/polyrenderer/scene/poly_scene.cpp delete mode 100644 src/rendering/polyrenderer/scene/poly_scene.h delete mode 100644 src/rendering/polyrenderer/scene/poly_sky.cpp delete mode 100644 src/rendering/polyrenderer/scene/poly_sky.h delete mode 100644 src/rendering/polyrenderer/scene/poly_sprite.cpp delete mode 100644 src/rendering/polyrenderer/scene/poly_sprite.h delete mode 100644 src/rendering/polyrenderer/scene/poly_wall.cpp delete mode 100644 src/rendering/polyrenderer/scene/poly_wall.h delete mode 100644 src/rendering/polyrenderer/scene/poly_wallsprite.cpp delete mode 100644 src/rendering/polyrenderer/scene/poly_wallsprite.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 384306ed8..978b32759 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 fe5dd1e8d..50e8a82ae 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 0c6a6791a..83df64421 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 9fd779cdc..53676532a 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 50c0f6ad4..99a54585e 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 dc6a66c3c..45656e35e 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 66ae24f65..cee3975a3 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 29b3c7fe1..0d7295d7f 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 9c3642488..000000000 --- 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 b40f5d44d..000000000 --- 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 7e5c834ca..000000000 --- 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 d6be7db15..000000000 --- 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 1428a5931..000000000 --- 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 81fa19387..000000000 --- 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 54ba76955..000000000 --- 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 5ca597109..000000000 --- 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 e7ebf4c1e..000000000 --- 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 988dc718d..000000000 --- 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 e3bffcb49..000000000 --- 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 bdf6c9423..000000000 --- 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 b8c737407..000000000 --- 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 5d6b46a97..000000000 --- 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 1a1ceb0e0..000000000 --- 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 74c6c7956..000000000 --- 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 3cf04a53d..000000000 --- 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 cba6cda52..000000000 --- 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 c70d659ec..000000000 --- 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 2c37266f6..000000000 --- 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 ec21c0e15..000000000 --- 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 238116c52..000000000 --- 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 7aa9500f2..000000000 --- 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 441086511..000000000 --- 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 5428f8de6..000000000 --- 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 7997228d6..000000000 --- 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 9d04b64a7..000000000 --- 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 03850b0fc..000000000 --- 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 d826186db..000000000 --- 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 d50223f11..000000000 --- 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 4d20ca682..42d9d6c07 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 d5b9124fd..5f1b8c635 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 c2536e3d2..f0d2830d3 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 7714527e7..d14c73b55 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 824b4be90..079b45199 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 87d14761d..10a665732 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" From d724b623d1a34de6f4fc7eded3d835c1c2fd614c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 22 May 2019 17:56:29 +0200 Subject: [PATCH 03/60] - enable the depth buffer - support vid_scalefactor --- .../polyrenderer/backend/poly_framebuffer.cpp | 3 +- .../polyrenderer/backend/poly_renderstate.cpp | 10 ++++-- .../polyrenderer/drawers/poly_triangle.cpp | 35 +++++++++++++++++++ .../polyrenderer/drawers/poly_triangle.h | 13 +++++++ src/win32/win32polyvideo.cpp | 8 ++++- 5 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index 0a261462d..513936d3e 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -105,6 +105,7 @@ void PolyFrameBuffer::CheckCanvas() mCanvas.reset(new DCanvas(0, 0, true)); mCanvas->Resize(GetWidth(), GetHeight(), false); + PolyTriangleDrawer::ResizeBuffers(mCanvas.get()); PolyTriangleDrawer::SetViewport(GetDrawCommands(), 0, 0, mCanvas->GetWidth(), mCanvas->GetHeight(), mCanvas.get()); } } @@ -141,7 +142,7 @@ void PolyFrameBuffer::Update() DrawerThreads::WaitForWorkers(); mFrameMemory.Clear(); - if (mCanvas && GetClientWidth() == mCanvas->GetWidth() && GetClientHeight() == mCanvas->GetHeight()) + if (mCanvas) { I_PresentPolyImage(mCanvas->GetWidth(), mCanvas->GetHeight(), mCanvas->GetPixels()); } diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 527f3e433..60e7a74f9 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -66,6 +66,7 @@ bool PolyRenderState::SetDepthClamp(bool on) void PolyRenderState::SetDepthMask(bool on) { + args.SetWriteDepth(on); } void PolyRenderState::SetDepthFunc(int func) @@ -94,6 +95,12 @@ void PolyRenderState::EnableClipDistance(int num, bool state) void PolyRenderState::Clear(int targets) { + //if (targets & CT_Color) + // PolyTriangleDrawer::ClearColor(GetPolyFrameBuffer()->GetDrawCommands()); + if (targets & CT_Depth) + PolyTriangleDrawer::ClearDepth(GetPolyFrameBuffer()->GetDrawCommands(), 0.0f); + if (targets & CT_Stencil) + PolyTriangleDrawer::ClearStencil(GetPolyFrameBuffer()->GetDrawCommands(), 0); } void PolyRenderState::EnableStencil(bool on) @@ -110,6 +117,7 @@ void PolyRenderState::SetViewport(int x, int y, int w, int h) void PolyRenderState::EnableDepthTest(bool on) { + args.SetDepthTest(on); } void PolyRenderState::EnableMultisampling(bool on) @@ -129,9 +137,7 @@ void PolyRenderState::Apply() drawcalls.Clock(); args.SetStencilTest(false); - args.SetDepthTest(false); args.SetWriteStencil(false); - args.SetWriteDepth(false); args.SetNoColormap(); args.SetColor(MAKEARGB( diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 53676532a..564c0f6f8 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -52,6 +52,11 @@ bool PolyTriangleDrawer::IsBgra() return isBgraRenderTarget; } +void PolyTriangleDrawer::ClearDepth(const DrawerCommandQueuePtr &queue, float value) +{ + queue->Push(value); +} + void PolyTriangleDrawer::ClearStencil(const DrawerCommandQueuePtr &queue, uint8_t value) { queue->Push(value); @@ -118,6 +123,25 @@ void PolyTriangleDrawer::DrawElements(const DrawerCommandQueuePtr &queue, const ///////////////////////////////////////////////////////////////////////////// +void PolyTriangleThreadData::ClearDepth(float value) +{ + auto buffer = PolyZBuffer::Instance(); + int width = buffer->Width(); + int height = buffer->Height(); + float *data = buffer->Values(); + + int skip = skipped_by_thread(0); + int count = count_for_thread(0, height); + + data += skip * width; + for (int i = 0; i < count; i++) + { + for (int x = 0; x < width; x++) + data[x] = value; + data += num_cores * width; + } +} + void PolyTriangleThreadData::ClearStencil(uint8_t value) { auto buffer = PolyStencilBuffer::Instance(); @@ -686,6 +710,17 @@ void PolySetModelVertexShaderCommand::Execute(DrawerThread *thread) ///////////////////////////////////////////////////////////////////////////// +PolyClearDepthCommand::PolyClearDepthCommand(float value) : value(value) +{ +} + +void PolyClearDepthCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->ClearDepth(value); +} + +///////////////////////////////////////////////////////////////////////////// + PolyClearStencilCommand::PolyClearStencilCommand(uint8_t value) : value(value) { } diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 99a54585e..10b17f067 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -36,6 +36,7 @@ class PolyTriangleDrawer { public: static void ResizeBuffers(DCanvas *canvas); + static void ClearDepth(const DrawerCommandQueuePtr &queue, float value); static void ClearStencil(const DrawerCommandQueuePtr &queue, uint8_t value); static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas); static void SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw); @@ -53,6 +54,7 @@ class PolyTriangleThreadData public: PolyTriangleThreadData(int32_t core, int32_t num_cores, int32_t numa_node, int32_t num_numa_nodes, int numa_start_y, int numa_end_y) : core(core), num_cores(num_cores), numa_node(numa_node), num_numa_nodes(num_numa_nodes), numa_start_y(numa_start_y), numa_end_y(numa_end_y) { } + void ClearDepth(float value); void ClearStencil(uint8_t value); void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra); void SetTransform(const Mat4f *objectToClip, const Mat4f *objectToWorld); @@ -195,6 +197,17 @@ private: float interpolationFactor; }; +class PolyClearDepthCommand : public PolyDrawerCommand +{ +public: + PolyClearDepthCommand(float value); + + void Execute(DrawerThread *thread) override; + +private: + float value; +}; + class PolyClearStencilCommand : public PolyDrawerCommand { public: diff --git a/src/win32/win32polyvideo.cpp b/src/win32/win32polyvideo.cpp index faf6c937a..cb7638fdf 100644 --- a/src/win32/win32polyvideo.cpp +++ b/src/win32/win32polyvideo.cpp @@ -17,7 +17,13 @@ void I_PresentPolyImage(int w, int h, const void *pixels) info.bV5SizeImage = 0; info.bV5CSType = LCS_WINDOWS_COLOR_SPACE; + RECT box = {}; + GetClientRect(Window, &box); + HDC dc = GetDC(Window); - SetDIBitsToDevice(dc, 0, 0, w, h, 0, 0, 0, h, pixels, (const BITMAPINFO *)&info, DIB_RGB_COLORS); + if (box.right == w && box.bottom == h) + SetDIBitsToDevice(dc, 0, 0, w, h, 0, 0, 0, h, pixels, (const BITMAPINFO *)&info, DIB_RGB_COLORS); + else + StretchDIBits(dc, 0, 0, box.right, box.bottom, 0, 0, w, h, pixels, (const BITMAPINFO *)&info, DIB_RGB_COLORS, SRCCOPY); ReleaseDC(Window, dc); } From 0cb3605c7026036985aeab2607cd2c6b6543e5ae Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 22 May 2019 21:23:10 +0200 Subject: [PATCH 04/60] - fix null drawers - slightly better renderstyle drawer selection --- .../polyrenderer/backend/poly_framebuffer.h | 1 + .../polyrenderer/backend/poly_renderstate.cpp | 25 +++++++++++++++---- .../polyrenderer/backend/poly_renderstate.h | 4 ++- .../polyrenderer/drawers/screen_triangle.cpp | 8 +++--- .../polyrenderer/drawers/screen_triangle.h | 4 +++ 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.h b/src/rendering/polyrenderer/backend/poly_framebuffer.h index 3e05d01a2..11cff6a2c 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.h +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.h @@ -17,6 +17,7 @@ class PolyFrameBuffer : public SystemBaseFrameBuffer public: RenderMemory *GetFrameMemory() { return &mFrameMemory; } PolyRenderState *GetRenderState() { return mRenderState.get(); } + DCanvas *GetCanvas() { return mCanvas.get(); } const DrawerCommandQueuePtr &GetDrawCommands(); void FlushDrawCommands(); diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 60e7a74f9..bbe19b047 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -13,6 +13,7 @@ #include "hwrenderer/data/flatvertices.h" #include "hwrenderer/data/hw_viewpointbuffer.h" #include "hwrenderer/data/shaderuniforms.h" +#include "swrenderer/r_swcolormaps.h" static PolyDrawMode dtToDrawMode[] = { @@ -79,6 +80,7 @@ void PolyRenderState::SetDepthRange(float min, float max) void PolyRenderState::SetColorMask(bool r, bool g, bool b, bool a) { + args.SetWriteColor(r || g || b || a); } void PolyRenderState::SetStencil(int offs, int op, int flags) @@ -113,6 +115,8 @@ void PolyRenderState::SetScissor(int x, int y, int w, int h) void PolyRenderState::SetViewport(int x, int y, int w, int h) { + auto fb = GetPolyFrameBuffer(); + PolyTriangleDrawer::SetViewport(fb->GetDrawCommands(), x, y, w, h, fb->GetCanvas()); } void PolyRenderState::EnableDepthTest(bool on) @@ -138,7 +142,10 @@ void PolyRenderState::Apply() args.SetStencilTest(false); args.SetWriteStencil(false); - args.SetNoColormap(); + + FColormap cm; + cm.Clear(); + args.SetLight(GetColorTable(cm), (int)(mLightParms[3] * 255.0f), mViewpointUniforms->mGlobVis, true); args.SetColor(MAKEARGB( static_cast(mStreamData.uVertexColor.W * 255.0f + 0.5f), @@ -153,7 +160,15 @@ void PolyRenderState::Apply() { DCanvas *texcanvas = base->GetImage(mMaterial); args.SetTexture(texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth()); - args.SetStyle(TriBlendMode::Opaque); + + if (mRenderStyle == LegacyRenderStyles[STYLE_Normal]) + args.SetStyle(TriBlendMode::Normal); + else if (mRenderStyle == LegacyRenderStyles[STYLE_Add]) + args.SetStyle(TriBlendMode::Add); + else if (mRenderStyle == LegacyRenderStyles[STYLE_Translucent]) + args.SetStyle(TriBlendMode::Translucent); + else + args.SetStyle(TriBlendMode::Opaque); } else { @@ -173,10 +188,10 @@ void PolyRenderState::Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t len { if (buffer->bindingpoint == VIEWPOINT_BINDINGPOINT) { - HWViewpointUniforms *uniforms = reinterpret_cast(static_cast(buffer->Memory()) + offset); + mViewpointUniforms = reinterpret_cast(static_cast(buffer->Memory()) + offset); - Mat4f viewToProj = Mat4f::FromValues(uniforms->mProjectionMatrix.get()); - Mat4f worldToView = Mat4f::FromValues(uniforms->mViewMatrix.get()); + Mat4f viewToProj = Mat4f::FromValues(mViewpointUniforms->mProjectionMatrix.get()); + Mat4f worldToView = Mat4f::FromValues(mViewpointUniforms->mViewMatrix.get()); auto fb = GetPolyFrameBuffer(); PolyTriangleDrawer::SetTransform(fb->GetDrawCommands(), fb->GetFrameMemory()->NewObject(viewToProj * worldToView), nullptr); diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.h b/src/rendering/polyrenderer/backend/poly_renderstate.h index 84c9c190a..7e3676615 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.h +++ b/src/rendering/polyrenderer/backend/poly_renderstate.h @@ -10,7 +10,7 @@ #include "hwrenderer/scene/hw_renderstate.h" #include "hwrenderer/textures/hw_material.h" -class PolyRenderPassSetup; +struct HWViewpointUniforms; class PolyRenderState : public FRenderState { @@ -45,6 +45,8 @@ public: private: void Apply(); + HWViewpointUniforms *mViewpointUniforms = nullptr; + bool mDepthClamp = true; PolyDrawArgs args; }; diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 45656e35e..82b652532 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -2250,10 +2250,10 @@ void(*ScreenTriangle::RectDrawers32[])(const void *, int, int, int, const RectDr void(*ScreenTriangle::TriangleDrawers[])(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread, int16_t *edges, int topY, int bottomY) = { - nullptr, - nullptr, - nullptr, - nullptr, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, &DrawTriangle, &DrawTriangle, &DrawTriangle, diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.h b/src/rendering/polyrenderer/drawers/screen_triangle.h index cee3975a3..613466593 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.h +++ b/src/rendering/polyrenderer/drawers/screen_triangle.h @@ -223,6 +223,10 @@ namespace TriScreenDrawerModes SWTRI_WriteStencil = 16 }; + struct TriangleOpt0 { static const int Flags = 0; }; + struct TriangleOpt1 { static const int Flags = 1; }; + struct TriangleOpt2 { static const int Flags = 2; }; + struct TriangleOpt3 { static const int Flags = 3; }; struct TriangleOpt4 { static const int Flags = 4; }; struct TriangleOpt5 { static const int Flags = 5; }; struct TriangleOpt6 { static const int Flags = 6; }; From b453e159294f7dfdb07fe36c8e61cfbfb38539cb Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 24 May 2019 22:30:14 +0200 Subject: [PATCH 05/60] - adjust PolyTriangleDrawer to closer match what PolyRenderState receives as input --- .../polyrenderer/backend/poly_buffers.cpp | 58 +++---- .../polyrenderer/backend/poly_buffers.h | 6 +- .../polyrenderer/backend/poly_framebuffer.cpp | 1 + .../polyrenderer/backend/poly_framebuffer.h | 5 + .../polyrenderer/backend/poly_renderstate.cpp | 14 +- .../polyrenderer/drawers/poly_buffer.h | 2 - .../polyrenderer/drawers/poly_triangle.cpp | 161 ++++++++++++------ .../polyrenderer/drawers/poly_triangle.h | 101 +++++++++-- src/rendering/swrenderer/things/r_model.cpp | 16 +- src/rendering/swrenderer/things/r_model.h | 2 - 10 files changed, 247 insertions(+), 119 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_buffers.cpp b/src/rendering/polyrenderer/backend/poly_buffers.cpp index 7ca4d1768..fd0ead6ea 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.cpp +++ b/src/rendering/polyrenderer/backend/poly_buffers.cpp @@ -18,6 +18,10 @@ PolyBuffer::~PolyBuffer() if (Next) Next->Prev = Prev; if (Prev) Prev->Next = Next; else First = Next; + + auto fb = GetPolyFrameBuffer(); + if (fb && !mData.empty()) + fb->FrameDeleteList.Buffers.push_back(std::move(mData)); } void PolyBuffer::ResetAll() @@ -79,43 +83,29 @@ void PolyVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t mStride = stride; } -void PolyVertexBuffer::CopyVertices(TriVertex *dst, int count, int index) +ShadedTriVertex PolyVertexBuffer::Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) { - size_t stride = mStride; - size_t offsetVertex = mOffsets[VATTR_VERTEX]; - size_t offsetTexcoord = mOffsets[VATTR_TEXCOORD]; - uint8_t *vertex = static_cast(map) + stride * index; + const uint8_t *vertex = static_cast(vertices) + mStride * index; + const float *attrVertex = reinterpret_cast(vertex + mOffsets[VATTR_VERTEX]); + const float *attrTexcoord = reinterpret_cast(vertex + mOffsets[VATTR_TEXCOORD]); - for (int i = 0; i < count; i++) - { - dst[i].x = *reinterpret_cast(vertex + offsetVertex); - dst[i].y = *reinterpret_cast(vertex + offsetVertex + 4); - dst[i].z = *reinterpret_cast(vertex + offsetVertex + 8); - dst[i].w = 1.0f; - dst[i].v = *reinterpret_cast(vertex + offsetTexcoord); - dst[i].u = *reinterpret_cast(vertex + offsetTexcoord + 4); - vertex += stride; - } -} + Vec4f objpos = Vec4f(attrVertex[0], attrVertex[1], attrVertex[2], 1.0f); + Vec4f clippos = (*thread->objectToClip) * objpos; -void PolyVertexBuffer::CopyIndexed(TriVertex *dst, uint32_t *elements, int count, int index) -{ - size_t stride = mStride; - size_t offsetVertex = mOffsets[VATTR_VERTEX]; - size_t offsetTexcoord = mOffsets[VATTR_TEXCOORD]; - uint8_t *vertices = static_cast(map); - - elements += index; - for (int i = 0; i < count; i++) - { - uint8_t *vertex = vertices + stride * elements[i]; - dst[i].x = *reinterpret_cast(vertex + offsetVertex); - dst[i].y = *reinterpret_cast(vertex + offsetVertex + 4); - dst[i].z = *reinterpret_cast(vertex + offsetVertex + 8); - dst[i].w = 1.0f; - dst[i].v = *reinterpret_cast(vertex + offsetTexcoord); - dst[i].u = *reinterpret_cast(vertex + offsetTexcoord + 4); - } + ShadedTriVertex sv; + sv.u = attrTexcoord[1]; + sv.v = attrTexcoord[0]; + sv.x = clippos.X; + sv.y = clippos.Y; + sv.z = clippos.Z; + sv.w = clippos.W; + sv.worldX = objpos.X; + sv.worldY = objpos.Y; + sv.worldZ = objpos.Z; + sv.clipDistance[0] = 1.0f; + sv.clipDistance[1] = 1.0f; + sv.clipDistance[2] = 1.0f; + return sv; } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/rendering/polyrenderer/backend/poly_buffers.h b/src/rendering/polyrenderer/backend/poly_buffers.h index 49375c7d0..2ad9e11f9 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.h +++ b/src/rendering/polyrenderer/backend/poly_buffers.h @@ -1,6 +1,7 @@ #pragma once #include "hwrenderer/data/buffers.h" +#include "polyrenderer/drawers/poly_triangle.h" #include "utility/tarray.h" #include @@ -38,14 +39,13 @@ private: std::vector mData; }; -class PolyVertexBuffer : public IVertexBuffer, public PolyBuffer +class PolyVertexBuffer : public IVertexBuffer, public PolyBuffer, public PolyVertexShader { public: PolyVertexBuffer() { } void SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) override; - void CopyVertices(TriVertex *dst, int count, int index); - void CopyIndexed(TriVertex *dst, uint32_t *elements, int count, int index); + ShadedTriVertex Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) override; private: size_t mOffsets[VATTR_MAX] = {}; diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index 513936d3e..4131acae9 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -141,6 +141,7 @@ void PolyFrameBuffer::Update() FlushDrawCommands(); DrawerThreads::WaitForWorkers(); mFrameMemory.Clear(); + FrameDeleteList.Buffers.clear(); if (mCanvas) { diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.h b/src/rendering/polyrenderer/backend/poly_framebuffer.h index 11cff6a2c..e56318145 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.h +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.h @@ -59,6 +59,11 @@ public: void SetVSync(bool vsync) override; void Draw2D() override; + struct DeleteList + { + std::vector> Buffers; + } FrameDeleteList; + private: sector_t *RenderViewpoint(FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV); diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index bbe19b047..ea1148d1a 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -41,10 +41,7 @@ void PolyRenderState::Draw(int dt, int index, int count, bool apply) if (apply) Apply(); - auto fb = GetPolyFrameBuffer(); - TriVertex *vertices = fb->GetFrameMemory()->AllocMemory(count); - static_cast(mVertexBuffer)->CopyVertices(vertices, count, index); - PolyTriangleDrawer::DrawArray(fb->GetDrawCommands(), args, vertices, count, dtToDrawMode[dt]); + PolyTriangleDrawer::Draw(GetPolyFrameBuffer()->GetDrawCommands(), index, count, dtToDrawMode[dt]); } void PolyRenderState::DrawIndexed(int dt, int index, int count, bool apply) @@ -52,10 +49,7 @@ void PolyRenderState::DrawIndexed(int dt, int index, int count, bool apply) if (apply) Apply(); - auto fb = GetPolyFrameBuffer(); - TriVertex *vertices = fb->GetFrameMemory()->AllocMemory(count); - static_cast(mVertexBuffer)->CopyIndexed(vertices, (uint32_t *)mIndexBuffer->Memory(), count, index); - PolyTriangleDrawer::DrawArray(fb->GetDrawCommands(), args, vertices, count, dtToDrawMode[dt]); + PolyTriangleDrawer::DrawIndexed(GetPolyFrameBuffer()->GetDrawCommands(), index, count, dtToDrawMode[dt]); } bool PolyRenderState::SetDepthClamp(bool on) @@ -179,7 +173,11 @@ void PolyRenderState::Apply() } auto fb = GetPolyFrameBuffer(); + if (mVertexBuffer) PolyTriangleDrawer::SetVertexBuffer(fb->GetDrawCommands(), mVertexBuffer->Memory()); + if (mIndexBuffer) PolyTriangleDrawer::SetIndexBuffer(fb->GetDrawCommands(), mIndexBuffer->Memory()); + PolyTriangleDrawer::SetVertexShader(fb->GetDrawCommands(), static_cast(mVertexBuffer)); PolyTriangleDrawer::SetTwoSided(fb->GetDrawCommands(), true); + PolyTriangleDrawer::PushConstants(fb->GetDrawCommands(), args); drawcalls.Unclock(); } diff --git a/src/rendering/polyrenderer/drawers/poly_buffer.h b/src/rendering/polyrenderer/drawers/poly_buffer.h index 160aa1067..14ffd5063 100644 --- a/src/rendering/polyrenderer/drawers/poly_buffer.h +++ b/src/rendering/polyrenderer/drawers/poly_buffer.h @@ -24,8 +24,6 @@ #include -struct TriVertex; - class PolyZBuffer { public: diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 564c0f6f8..14d3972e1 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -86,6 +86,11 @@ void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, queue->Push(viewport_x, viewport_y, viewport_width, viewport_height, dest, dest_width, dest_height, dest_pitch, dest_bgra); } +void PolyTriangleDrawer::SetVertexShader(const DrawerCommandQueuePtr &queue, PolyVertexShader *shader) +{ + queue->Push(shader); +} + void PolyTriangleDrawer::SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld) { queue->Push(objectToClip, objectToWorld); @@ -111,14 +116,29 @@ void PolyTriangleDrawer::SetModelVertexShader(const DrawerCommandQueuePtr &queue queue->Push(frame1, frame2, interpolationFactor); } -void PolyTriangleDrawer::DrawArray(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args, const void *vertices, int vcount, PolyDrawMode mode) +void PolyTriangleDrawer::SetVertexBuffer(const DrawerCommandQueuePtr &queue, const void *vertices) { - queue->Push(args, vertices, nullptr, vcount, mode); + queue->Push(vertices); } -void PolyTriangleDrawer::DrawElements(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args, const void *vertices, const unsigned int *elements, int count, PolyDrawMode mode) +void PolyTriangleDrawer::SetIndexBuffer(const DrawerCommandQueuePtr &queue, const void *elements) { - queue->Push(args, vertices, elements, count, mode); + queue->Push(elements); +} + +void PolyTriangleDrawer::PushConstants(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args) +{ + queue->Push(args); +} + +void PolyTriangleDrawer::Draw(const DrawerCommandQueuePtr &queue, int index, int vcount, PolyDrawMode mode) +{ + queue->Push(index, vcount, mode); +} + +void PolyTriangleDrawer::DrawIndexed(const DrawerCommandQueuePtr &queue, int index, int count, PolyDrawMode mode) +{ + queue->Push(index, count, mode); } ///////////////////////////////////////////////////////////////////////////// @@ -181,11 +201,18 @@ void PolyTriangleThreadData::SetTransform(const Mat4f *newObjectToClip, const Ma objectToWorld = newObjectToWorld; } -void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs, const void *vertices, const unsigned int *elements, int vcount, PolyDrawMode drawmode) +void PolyTriangleThreadData::PushConstants(const PolyDrawArgs &args) +{ + drawargs = args; +} + +void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode drawmode) { if (vcount < 3) return; + elements += index; + TriDrawTriangleArgs args; args.uniforms = &drawargs; @@ -195,17 +222,17 @@ void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs, const vo for (int i = 0; i < vcount / 3; i++) { for (int j = 0; j < 3; j++) - vert[j] = ShadeVertex(drawargs, vertices, *(elements++)); + vert[j] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); DrawShadedTriangle(vert, ccw, &args); } } else if (drawmode == PolyDrawMode::TriangleFan) { - vert[0] = ShadeVertex(drawargs, vertices, *(elements++)); - vert[1] = ShadeVertex(drawargs, vertices, *(elements++)); + vert[0] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); + vert[1] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); for (int i = 2; i < vcount; i++) { - vert[2] = ShadeVertex(drawargs, vertices, *(elements++)); + vert[2] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); DrawShadedTriangle(vert, ccw, &args); vert[1] = vert[2]; } @@ -213,11 +240,11 @@ void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs, const vo else // TriangleDrawMode::TriangleStrip { bool toggleccw = ccw; - vert[0] = ShadeVertex(drawargs, vertices, *(elements++)); - vert[1] = ShadeVertex(drawargs, vertices, *(elements++)); + vert[0] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); + vert[1] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); for (int i = 2; i < vcount; i++) { - vert[2] = ShadeVertex(drawargs, vertices, *(elements++)); + vert[2] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); DrawShadedTriangle(vert, toggleccw, &args); vert[0] = vert[1]; vert[1] = vert[2]; @@ -226,7 +253,7 @@ void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs, const vo } } -void PolyTriangleThreadData::DrawArray(const PolyDrawArgs &drawargs, const void *vertices, int vcount, PolyDrawMode drawmode) +void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode) { if (vcount < 3) return; @@ -234,7 +261,7 @@ void PolyTriangleThreadData::DrawArray(const PolyDrawArgs &drawargs, const void TriDrawTriangleArgs args; args.uniforms = &drawargs; - int vinput = 0; + int vinput = index; ShadedTriVertex vert[3]; if (drawmode == PolyDrawMode::Triangles) @@ -242,17 +269,17 @@ void PolyTriangleThreadData::DrawArray(const PolyDrawArgs &drawargs, const void for (int i = 0; i < vcount / 3; i++) { for (int j = 0; j < 3; j++) - vert[j] = ShadeVertex(drawargs, vertices, vinput++); + vert[j] = vertexShader->Shade(this, drawargs, vertices, vinput++); DrawShadedTriangle(vert, ccw, &args); } } else if (drawmode == PolyDrawMode::TriangleFan) { - vert[0] = ShadeVertex(drawargs, vertices, vinput++); - vert[1] = ShadeVertex(drawargs, vertices, vinput++); + vert[0] = vertexShader->Shade(this, drawargs, vertices, vinput++); + vert[1] = vertexShader->Shade(this, drawargs, vertices, vinput++); for (int i = 2; i < vcount; i++) { - vert[2] = ShadeVertex(drawargs, vertices, vinput++); + vert[2] = vertexShader->Shade(this, drawargs, vertices, vinput++); DrawShadedTriangle(vert, ccw, &args); vert[1] = vert[2]; } @@ -260,11 +287,11 @@ void PolyTriangleThreadData::DrawArray(const PolyDrawArgs &drawargs, const void else // TriangleDrawMode::TriangleStrip { bool toggleccw = ccw; - vert[0] = ShadeVertex(drawargs, vertices, vinput++); - vert[1] = ShadeVertex(drawargs, vertices, vinput++); + vert[0] = vertexShader->Shade(this, drawargs, vertices, vinput++); + vert[1] = vertexShader->Shade(this, drawargs, vertices, vinput++); for (int i = 2; i < vcount; i++) { - vert[2] = ShadeVertex(drawargs, vertices, vinput++); + vert[2] = vertexShader->Shade(this, drawargs, vertices, vinput++); DrawShadedTriangle(vert, toggleccw, &args); vert[0] = vert[1]; vert[1] = vert[2]; @@ -273,31 +300,31 @@ void PolyTriangleThreadData::DrawArray(const PolyDrawArgs &drawargs, const void } } -ShadedTriVertex PolyTriangleThreadData::ShadeVertex(const PolyDrawArgs &drawargs, const void *vertices, int index) +ShadedTriVertex PolyTriVertexShader::Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) { ShadedTriVertex sv; Vec4f objpos; - if (modelFrame1 == -1) + if (thread->modelFrame1 == -1) { const TriVertex &v = static_cast(vertices)[index]; objpos = Vec4f(v.x, v.y, v.z, v.w); sv.u = v.u; sv.v = v.v; } - else if (modelFrame1 == modelFrame2 || modelInterpolationFactor == 0.f) + else if (thread->modelFrame1 == thread->modelFrame2 || thread->modelInterpolationFactor == 0.f) { - const FModelVertex &v = static_cast(vertices)[modelFrame1 + index]; + const FModelVertex &v = static_cast(vertices)[thread->modelFrame1 + index]; objpos = Vec4f(v.x, v.y, v.z, 1.0f); sv.u = v.u; sv.v = v.v; } else { - const FModelVertex &v1 = static_cast(vertices)[modelFrame1 + index]; - const FModelVertex &v2 = static_cast(vertices)[modelFrame2 + index]; + const FModelVertex &v1 = static_cast(vertices)[thread->modelFrame1 + index]; + const FModelVertex &v2 = static_cast(vertices)[thread->modelFrame2 + index]; - float frac = modelInterpolationFactor; + float frac = thread->modelInterpolationFactor; float inv_frac = 1.0f - frac; objpos = Vec4f(v1.x * inv_frac + v2.x * frac, v1.y * inv_frac + v2.y * frac, v1.z * inv_frac + v2.z * frac, 1.0f); @@ -306,14 +333,14 @@ ShadedTriVertex PolyTriangleThreadData::ShadeVertex(const PolyDrawArgs &drawargs } // Apply transform to get clip coordinates: - Vec4f clippos = (*objectToClip) * objpos; + Vec4f clippos = (*thread->objectToClip) * objpos; sv.x = clippos.X; sv.y = clippos.Y; sv.z = clippos.Z; sv.w = clippos.W; - if (!objectToWorld) // Identity matrix + if (!thread->objectToWorld) // Identity matrix { sv.worldX = objpos.X; sv.worldY = objpos.Y; @@ -321,7 +348,7 @@ ShadedTriVertex PolyTriangleThreadData::ShadeVertex(const PolyDrawArgs &drawargs } else { - Vec4f worldpos = (*objectToWorld) * objpos; + Vec4f worldpos = (*thread->objectToWorld) * objpos; sv.worldX = worldpos.X; sv.worldY = worldpos.Y; sv.worldZ = worldpos.Z; @@ -655,6 +682,39 @@ PolyTriangleThreadData *PolyTriangleThreadData::Get(DrawerThread *thread) ///////////////////////////////////////////////////////////////////////////// +PolySetVertexBufferCommand::PolySetVertexBufferCommand(const void *vertices) : vertices(vertices) +{ +} + +void PolySetVertexBufferCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->SetVertexBuffer(vertices); +} + +///////////////////////////////////////////////////////////////////////////// + +PolySetIndexBufferCommand::PolySetIndexBufferCommand(const void *indices) : indices(indices) +{ +} + +void PolySetIndexBufferCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->SetIndexBuffer(indices); +} + +///////////////////////////////////////////////////////////////////////////// + +PolySetVertexShaderCommand::PolySetVertexShaderCommand(PolyVertexShader *shader) : shader(shader) +{ +} + +void PolySetVertexShaderCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->SetVertexShader(shader); +} + +///////////////////////////////////////////////////////////////////////////// + PolySetTransformCommand::PolySetTransformCommand(const Mat4f *objectToClip, const Mat4f *objectToWorld) : objectToClip(objectToClip), objectToWorld(objectToWorld) { } @@ -744,32 +804,33 @@ void PolySetViewportCommand::Execute(DrawerThread *thread) ///////////////////////////////////////////////////////////////////////////// -DrawPolyTrianglesCommand::DrawPolyTrianglesCommand(const PolyDrawArgs &args, const void *vertices, const unsigned int *elements, int count, PolyDrawMode mode) : args(args), vertices(vertices), elements(elements), count(count), mode(mode) +PolyPushConstantsCommand::PolyPushConstantsCommand(const PolyDrawArgs &args) : args(args) { } -void DrawPolyTrianglesCommand::Execute(DrawerThread *thread) +void PolyPushConstantsCommand::Execute(DrawerThread *thread) { - if (!elements) - PolyTriangleThreadData::Get(thread)->DrawArray(args, vertices, count, mode); - else - PolyTriangleThreadData::Get(thread)->DrawElements(args, vertices, elements, count, mode); + PolyTriangleThreadData::Get(thread)->PushConstants(args); } ///////////////////////////////////////////////////////////////////////////// -#if 0 -void DrawRectCommand::Execute(DrawerThread *thread) +PolyDrawCommand::PolyDrawCommand(int index, int count, PolyDrawMode mode) : index(index), count(count), mode(mode) { - auto renderTarget = PolyRenderer::Instance()->RenderTarget; - const void *destOrg = renderTarget->GetPixels(); - int destWidth = renderTarget->GetWidth(); - int destHeight = renderTarget->GetHeight(); - int destPitch = renderTarget->GetPitch(); - int blendmode = (int)args.BlendMode(); - if (renderTarget->IsBgra()) - ScreenTriangle::RectDrawers32[blendmode](destOrg, destWidth, destHeight, destPitch, &args, PolyTriangleThreadData::Get(thread)); - else - ScreenTriangle::RectDrawers8[blendmode](destOrg, destWidth, destHeight, destPitch, &args, PolyTriangleThreadData::Get(thread)); } -#endif + +void PolyDrawCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->Draw(index, count, mode); +} + +///////////////////////////////////////////////////////////////////////////// + +PolyDrawIndexedCommand::PolyDrawIndexedCommand(int index, int count, PolyDrawMode mode) : index(index), count(count), mode(mode) +{ +} + +void PolyDrawIndexedCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->DrawIndexed(index, count, mode); +} diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 10b17f067..3751d24c8 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -31,6 +31,7 @@ class DCanvas; class PolyDrawerCommand; +class PolyVertexShader; class PolyTriangleDrawer { @@ -39,16 +40,32 @@ public: static void ClearDepth(const DrawerCommandQueuePtr &queue, float value); static void ClearStencil(const DrawerCommandQueuePtr &queue, uint8_t value); static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas); + static void SetVertexShader(const DrawerCommandQueuePtr &queue, PolyVertexShader *shader); static void SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw); static void SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided); static void SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable); static void SetModelVertexShader(const DrawerCommandQueuePtr &queue, int frame1, int frame2, float interpolationFactor); static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld); - static void DrawArray(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args, const void *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); - static void DrawElements(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args, const void *vertices, const unsigned int *elements, int count, PolyDrawMode mode = PolyDrawMode::Triangles); + static void SetVertexBuffer(const DrawerCommandQueuePtr &queue, const void *vertices); + static void SetIndexBuffer(const DrawerCommandQueuePtr &queue, const void *elements); + static void PushConstants(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args); + static void Draw(const DrawerCommandQueuePtr &queue, int index, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); + static void DrawIndexed(const DrawerCommandQueuePtr &queue, int index, int count, PolyDrawMode mode = PolyDrawMode::Triangles); static bool IsBgra(); }; +class PolyVertexShader +{ +public: + virtual ShadedTriVertex Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) = 0; +}; + +class PolyTriVertexShader : public PolyVertexShader +{ +public: + ShadedTriVertex Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) override; +}; + class PolyTriangleThreadData { public: @@ -62,9 +79,13 @@ public: void SetTwoSided(bool value) { twosided = value; } void SetWeaponScene(bool value) { weaponScene = value; } void SetModelVertexShader(int frame1, int frame2, float interpolationFactor) { modelFrame1 = frame1; modelFrame2 = frame2; modelInterpolationFactor = interpolationFactor; } + void SetVertexShader(PolyVertexShader *shader) { vertexShader = shader; } + void SetVertexBuffer(const void *data) { vertices = data; } + void SetIndexBuffer(const void *data) { elements = (const unsigned int *)data; } - void DrawElements(const PolyDrawArgs &args, const void *vertices, const unsigned int *elements, int count, PolyDrawMode mode); - void DrawArray(const PolyDrawArgs &args, const void *vertices, int vcount, PolyDrawMode mode); + void PushConstants(const PolyDrawArgs &args); + void DrawIndexed(int index, int count, PolyDrawMode mode); + void Draw(int index, int vcount, PolyDrawMode mode); int32_t core; int32_t num_cores; @@ -113,8 +134,12 @@ public: int viewport_y = 0; + PolyDrawArgs drawargs; + + const void *vertices = nullptr; + const unsigned int *elements = nullptr; + private: - ShadedTriVertex ShadeVertex(const PolyDrawArgs &drawargs, const void *vertices, int index); void DrawShadedTriangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args); static bool IsDegenerate(const ShadedTriVertex *vertices); static bool IsFrontfacing(TriDrawTriangleArgs *args); @@ -125,13 +150,18 @@ private: int viewport_height = 0; bool ccw = true; bool twosided = false; +public: const Mat4f *objectToClip = nullptr; const Mat4f *objectToWorld = nullptr; +private: int modelFrame1 = -1; int modelFrame2 = -1; float modelInterpolationFactor = 0.0f; + PolyVertexShader *vertexShader = nullptr; enum { max_additional_vertices = 16 }; + + friend class PolyTriVertexShader; }; class PolyDrawerCommand : public DrawerCommand @@ -139,6 +169,36 @@ class PolyDrawerCommand : public DrawerCommand public: }; +class PolySetVertexBufferCommand : public PolyDrawerCommand +{ +public: + PolySetVertexBufferCommand(const void *vertices); + void Execute(DrawerThread *thread) override; + +private: + const void *vertices; +}; + +class PolySetIndexBufferCommand : public PolyDrawerCommand +{ +public: + PolySetIndexBufferCommand(const void *indices); + void Execute(DrawerThread *thread) override; + +private: + const void *indices; +}; + +class PolySetVertexShaderCommand : public PolyDrawerCommand +{ +public: + PolySetVertexShaderCommand(PolyVertexShader *shader); + void Execute(DrawerThread *thread) override; + +private: + PolyVertexShader *shader; +}; + class PolySetTransformCommand : public PolyDrawerCommand { public: @@ -238,30 +298,39 @@ private: bool dest_bgra; }; -class DrawPolyTrianglesCommand : public PolyDrawerCommand +class PolyPushConstantsCommand : public PolyDrawerCommand { public: - DrawPolyTrianglesCommand(const PolyDrawArgs &args, const void *vertices, const unsigned int *elements, int count, PolyDrawMode mode); + PolyPushConstantsCommand(const PolyDrawArgs &args); void Execute(DrawerThread *thread) override; private: PolyDrawArgs args; - const void *vertices; - const unsigned int *elements; - int count; - PolyDrawMode mode; }; -#if 0 -class DrawRectCommand : public PolyDrawerCommand +class PolyDrawCommand : public PolyDrawerCommand { public: - DrawRectCommand(const RectDrawArgs &args) : args(args) { } + PolyDrawCommand(int index, int count, PolyDrawMode mode); void Execute(DrawerThread *thread) override; private: - RectDrawArgs args; + int index; + int count; + PolyDrawMode mode; +}; + +class PolyDrawIndexedCommand : public PolyDrawerCommand +{ +public: + PolyDrawIndexedCommand(int index, int count, PolyDrawMode mode); + + void Execute(DrawerThread *thread) override; + +private: + int index; + int count; + PolyDrawMode mode; }; -#endif diff --git a/src/rendering/swrenderer/things/r_model.cpp b/src/rendering/swrenderer/things/r_model.cpp index 079b45199..b59170128 100644 --- a/src/rendering/swrenderer/things/r_model.cpp +++ b/src/rendering/swrenderer/things/r_model.cpp @@ -148,6 +148,8 @@ namespace swrenderer SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor, Mat4f *worldToClip, bool mirrorWorldToClip) : Thread(thread), Clip3DFloor(clip3DFloor), WorldToClip(worldToClip), MirrorWorldToClip(mirrorWorldToClip) { + static PolyTriVertexShader shader; + PolyTriangleDrawer::SetVertexShader(thread->DrawQueue, &shader); } void SWModelRenderer::AddLights(AActor *actor) @@ -365,7 +367,8 @@ namespace swrenderer args.SetClipPlane(1, ClipTop); args.SetClipPlane(2, ClipBottom); - PolyTriangleDrawer::DrawArray(Thread->DrawQueue, args, VertexBuffer + start, count); + PolyTriangleDrawer::PushConstants(Thread->DrawQueue, args); + PolyTriangleDrawer::Draw(Thread->DrawQueue, start, count); } void SWModelRenderer::DrawElements(int numIndices, size_t offset) @@ -383,7 +386,8 @@ namespace swrenderer args.SetClipPlane(1, ClipTop); args.SetClipPlane(2, ClipBottom); - PolyTriangleDrawer::DrawElements(Thread->DrawQueue, args, VertexBuffer, IndexBuffer + offset / sizeof(unsigned int), numIndices); + PolyTriangleDrawer::PushConstants(Thread->DrawQueue, args); + PolyTriangleDrawer::DrawIndexed(Thread->DrawQueue, static_cast(offset / sizeof(unsigned int)), numIndices); } ///////////////////////////////////////////////////////////////////////////// @@ -419,8 +423,12 @@ namespace swrenderer void SWModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) { SWModelRenderer *swrenderer = (SWModelRenderer *)renderer; - swrenderer->VertexBuffer = mVertexBuffer.Size() ? &mVertexBuffer[0] : nullptr; - swrenderer->IndexBuffer = mIndexBuffer.Size() ? &mIndexBuffer[0] : nullptr; + + if (mVertexBuffer.Size() > 0) + PolyTriangleDrawer::SetVertexBuffer(swrenderer->Thread->DrawQueue, &mVertexBuffer[0]); + if (mIndexBuffer.Size() > 0) + PolyTriangleDrawer::SetIndexBuffer(swrenderer->Thread->DrawQueue, &mIndexBuffer[0]); + PolyTriangleDrawer::SetModelVertexShader(swrenderer->Thread->DrawQueue, frame1, frame2, swrenderer->InterpolationFactor); } } diff --git a/src/rendering/swrenderer/things/r_model.h b/src/rendering/swrenderer/things/r_model.h index 76509123f..b404c03d1 100644 --- a/src/rendering/swrenderer/things/r_model.h +++ b/src/rendering/swrenderer/things/r_model.h @@ -90,8 +90,6 @@ namespace swrenderer Mat4f ObjectToWorld; PolyClipPlane ClipTop, ClipBottom; FTexture *SkinTexture = nullptr; - unsigned int *IndexBuffer = nullptr; - FModelVertex *VertexBuffer = nullptr; float InterpolationFactor = 0.0; Mat4f *WorldToClip = nullptr; bool MirrorWorldToClip = false; From fbaeb11fbad9860a7cb7e1d2ef26a1f3e9c15ece Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 25 May 2019 01:27:20 +0200 Subject: [PATCH 06/60] - convert main.vp to c++ so softpoly can use it --- .../polyrenderer/drawers/poly_triangle.h | 2 + .../polyrenderer/drawers/poly_vertex_shader.h | 200 ++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 src/rendering/polyrenderer/drawers/poly_vertex_shader.h diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 3751d24c8..10287b696 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -28,6 +28,7 @@ #include "polyrenderer/math/gpu_types.h" #include "polyrenderer/drawers/poly_buffer.h" #include "polyrenderer/drawers/poly_draw_args.h" +#include "polyrenderer/drawers/poly_vertex_shader.h" class DCanvas; class PolyDrawerCommand; @@ -158,6 +159,7 @@ private: int modelFrame2 = -1; float modelInterpolationFactor = 0.0f; PolyVertexShader *vertexShader = nullptr; + PolyMainVertexShader mainVertexShader; enum { max_additional_vertices = 16 }; diff --git a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h new file mode 100644 index 000000000..758b0387c --- /dev/null +++ b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h @@ -0,0 +1,200 @@ + +#pragma once + +#include "polyrenderer/math/gpu_types.h" +#include "hwrenderer/scene/hw_viewpointuniforms.h" +#include "hwrenderer/scene/hw_renderstate.h" + +#ifndef NO_SSE +#include +#endif + +class PolyMainVertexShader +{ +public: + // Input + Vec4f aPosition; + Vec2f aTexCoord; + Vec4f aColor; + Vec4f aVertex2; + Vec4f aNormal; + Vec4f aNormal2; + + // Output + Vec4f gl_Position; + float gl_ClipDistance[5]; + Vec4f vTexCoord; + Vec4f vColor; + Vec4f pixelpos; + Vec3f glowdist; + Vec3f gradientdist; + Vec4f vWorldNormal; + Vec4f vEyeNormal; + + // Defines + bool SIMPLE = false; + bool SPHEREMAP = false; + + // Uniforms + VSMatrix ModelMatrix; + VSMatrix NormalModelMatrix; + VSMatrix TextureMatrix; + StreamData Data; + Vec2f uClipSplit; + HWViewpointUniforms Viewpoint; + + void main() + { + float ClipDistance0, ClipDistance1, ClipDistance2, ClipDistance3, ClipDistance4; + + Vec2f parmTexCoord = aTexCoord; + Vec4f parmPosition = aPosition; + + Vec4f worldcoord; + if (SIMPLE) + worldcoord = mul(ModelMatrix, mix(parmPosition, aVertex2, Data.uInterpolationFactor)); + else + worldcoord = mul(ModelMatrix, parmPosition); + + Vec4f eyeCoordPos = mul(Viewpoint.mViewMatrix, worldcoord); + + vColor = aColor; + + if (!SIMPLE) + { + pixelpos.X = worldcoord.X; + pixelpos.Y = worldcoord.Y; + pixelpos.Z = worldcoord.Z; + pixelpos.W = -eyeCoordPos.Z / eyeCoordPos.W; + + if (Data.uGlowTopColor.W > 0 || Data.uGlowBottomColor.W > 0) + { + float topatpoint = (Data.uGlowTopPlane.W + Data.uGlowTopPlane.X * worldcoord.X + Data.uGlowTopPlane.Y * worldcoord.Z) * Data.uGlowTopPlane.Z; + float bottomatpoint = (Data.uGlowBottomPlane.W + Data.uGlowBottomPlane.X * worldcoord.X + Data.uGlowBottomPlane.Y * worldcoord.Z) * Data.uGlowBottomPlane.Z; + glowdist.X = topatpoint - worldcoord.Y; + glowdist.Y = worldcoord.Y - bottomatpoint; + glowdist.Z = clamp(glowdist.X / (topatpoint - bottomatpoint), 0.0f, 1.0f); + } + + if (Data.uObjectColor2.a != 0) + { + float topatpoint = (Data.uGradientTopPlane.W + Data.uGradientTopPlane.X * worldcoord.X + Data.uGradientTopPlane.Y * worldcoord.Z) * Data.uGradientTopPlane.Z; + float bottomatpoint = (Data.uGradientBottomPlane.W + Data.uGradientBottomPlane.X * worldcoord.X + Data.uGradientBottomPlane.Y * worldcoord.Z) * Data.uGradientBottomPlane.Z; + gradientdist.X = topatpoint - worldcoord.Y; + gradientdist.Y = worldcoord.Y - bottomatpoint; + gradientdist.Z = clamp(gradientdist.X / (topatpoint - bottomatpoint), 0.0f, 1.0f); + } + + if (Data.uSplitBottomPlane.Z != 0.0f) + { + ClipDistance3 = ((Data.uSplitTopPlane.W + Data.uSplitTopPlane.X * worldcoord.X + Data.uSplitTopPlane.Y * worldcoord.Z) * Data.uSplitTopPlane.Z) - worldcoord.Y; + ClipDistance4 = worldcoord.Y - ((Data.uSplitBottomPlane.W + Data.uSplitBottomPlane.X * worldcoord.X + Data.uSplitBottomPlane.Y * worldcoord.Z) * Data.uSplitBottomPlane.Z); + } + + vWorldNormal = mul(NormalModelMatrix, Vec4f(normalize(mix3(aNormal, aNormal2, Data.uInterpolationFactor)), 1.0f)); + vEyeNormal = mul(Viewpoint.mNormalViewMatrix, vWorldNormal); + } + + if (!SPHEREMAP) + { + vTexCoord = mul(TextureMatrix, Vec4f(parmTexCoord, 0.0f, 1.0f)); + } + else + { + Vec3f u = normalize3(eyeCoordPos); + Vec3f n = normalize3(mul(Viewpoint.mNormalViewMatrix, Vec4f(parmTexCoord.X, 0.0f, parmTexCoord.Y, 0.0f))); + Vec3f r = reflect(u, n); + float m = 2.0f * sqrt(r.X*r.X + r.Y*r.Y + (r.Z + 1.0f)*(r.Z + 1.0f)); + vTexCoord.X = r.X / m + 0.5f; + vTexCoord.Y = r.Y / m + 0.5f; + } + + gl_Position = mul(Viewpoint.mProjectionMatrix, eyeCoordPos); + + if (Viewpoint.mClipHeightDirection != 0.0f) // clip planes used for reflective flats + { + ClipDistance0 = (worldcoord.Y - Viewpoint.mClipHeight) * Viewpoint.mClipHeightDirection; + } + else if (Viewpoint.mClipLine.X > -1000000.0f) // and for line portals - this will never be active at the same time as the reflective planes clipping so it can use the same hardware clip plane. + { + ClipDistance0 = -((worldcoord.Z - Viewpoint.mClipLine.Y) * Viewpoint.mClipLine.Z + (Viewpoint.mClipLine.X - worldcoord.X) * Viewpoint.mClipLine.W) + 1.0f / 32768.0f; // allow a tiny bit of imprecisions for colinear linedefs. + } + else + { + ClipDistance0 = 1.0f; + } + + // clip planes used for translucency splitting + ClipDistance1 = worldcoord.Y - uClipSplit.X; + ClipDistance2 = uClipSplit.Y - worldcoord.Y; + + if (Data.uSplitTopPlane == FVector4(0.0f, 0.0f, 0.0f, 0.0f)) + { + ClipDistance3 = 1.0f; + ClipDistance4 = 1.0f; + } + + gl_ClipDistance[0] = ClipDistance0; + gl_ClipDistance[1] = ClipDistance1; + gl_ClipDistance[2] = ClipDistance2; + gl_ClipDistance[3] = ClipDistance3; + gl_ClipDistance[4] = ClipDistance4; + } + +private: + static Vec3f normalize(const Vec3f &a) + { + float rcplen = 1.0f / sqrt(a.X * a.X + a.Y * a.Y + a.Z * a.Z); + return Vec3f(a.X * rcplen, a.Y * rcplen, a.Z * rcplen); + } + + static Vec3f normalize3(const Vec4f &a) + { + float rcplen = 1.0f / sqrt(a.X * a.X + a.Y * a.Y + a.Z * a.Z); + return Vec3f(a.X * rcplen, a.Y * rcplen, a.Z * rcplen); + } + + static Vec4f mix(const Vec4f &a, const Vec4f &b, float t) + { + float invt = 1.0f - t; + return Vec4f(a.X * invt + b.X * t, a.Y * invt + b.Y * t, a.Z * invt + b.Z * t, a.W * invt + b.W * t); + } + + static Vec3f mix3(const Vec4f &a, const Vec4f &b, float t) + { + float invt = 1.0f - t; + return Vec3f(a.X * invt + b.X * t, a.Y * invt + b.Y * t, a.Z * invt + b.Z * t); + } + + static Vec3f reflect(const Vec3f &u, const Vec3f &n) + { + float d = 2.0f * (n.X * u.X + n.Y * u.Y + n.Z * u.Z); + return Vec3f(u.X - d * n.X, u.Y - d * n.Y, u.Z - d * n.Z); + } + + static Vec4f mul(const VSMatrix &mat, const Vec4f &v) + { + const float *m = mat.get(); + + Vec4f result; +#ifdef NO_SSE + result.X = m[0 * 4 + 0] * v.X + m[1 * 4 + 0] * v.Y + m[2 * 4 + 0] * v.Z + m[3 * 4 + 0] * v.W; + result.Y = m[0 * 4 + 1] * v.X + m[1 * 4 + 1] * v.Y + m[2 * 4 + 1] * v.Z + m[3 * 4 + 1] * v.W; + result.Z = m[0 * 4 + 2] * v.X + m[1 * 4 + 2] * v.Y + m[2 * 4 + 2] * v.Z + m[3 * 4 + 2] * v.W; + result.W = m[0 * 4 + 3] * v.X + m[1 * 4 + 3] * v.Y + m[2 * 4 + 3] * v.Z + m[3 * 4 + 3] * v.W; +#else + __m128 m0 = _mm_loadu_ps(m); + __m128 m1 = _mm_loadu_ps(m + 4); + __m128 m2 = _mm_loadu_ps(m + 8); + __m128 m3 = _mm_loadu_ps(m + 12); + __m128 mv = _mm_loadu_ps(&v.X); + m0 = _mm_mul_ps(m0, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(0, 0, 0, 0))); + m1 = _mm_mul_ps(m1, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(1, 1, 1, 1))); + m2 = _mm_mul_ps(m2, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(2, 2, 2, 2))); + m3 = _mm_mul_ps(m3, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(3, 3, 3, 3))); + mv = _mm_add_ps(_mm_add_ps(_mm_add_ps(m0, m1), m2), m3); + _mm_storeu_ps(&result.X, mv); +#endif + return result; + } +}; From 3a3de13abdd055ed66b77c2833cd020c5f6a9613 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 26 May 2019 01:00:36 +0200 Subject: [PATCH 07/60] - hook up main.vp and the data it uses for input --- .../polyrenderer/backend/poly_buffers.cpp | 21 +- .../polyrenderer/backend/poly_buffers.h | 4 +- .../polyrenderer/backend/poly_renderstate.cpp | 63 +++- .../polyrenderer/backend/poly_renderstate.h | 10 + .../polyrenderer/drawers/poly_triangle.cpp | 317 ++++++++++-------- .../polyrenderer/drawers/poly_triangle.h | 98 ++++-- .../polyrenderer/drawers/poly_vertex_shader.h | 111 ++++-- .../polyrenderer/drawers/screen_triangle.cpp | 4 +- .../polyrenderer/drawers/screen_triangle.h | 9 +- src/rendering/swrenderer/things/r_model.cpp | 4 +- 10 files changed, 411 insertions(+), 230 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_buffers.cpp b/src/rendering/polyrenderer/backend/poly_buffers.cpp index fd0ead6ea..e186b7a71 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.cpp +++ b/src/rendering/polyrenderer/backend/poly_buffers.cpp @@ -83,29 +83,14 @@ void PolyVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t mStride = stride; } -ShadedTriVertex PolyVertexBuffer::Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) +void PolyVertexBuffer::Load(PolyTriangleThreadData *thread, const void *vertices, int index) { const uint8_t *vertex = static_cast(vertices) + mStride * index; const float *attrVertex = reinterpret_cast(vertex + mOffsets[VATTR_VERTEX]); const float *attrTexcoord = reinterpret_cast(vertex + mOffsets[VATTR_TEXCOORD]); - Vec4f objpos = Vec4f(attrVertex[0], attrVertex[1], attrVertex[2], 1.0f); - Vec4f clippos = (*thread->objectToClip) * objpos; - - ShadedTriVertex sv; - sv.u = attrTexcoord[1]; - sv.v = attrTexcoord[0]; - sv.x = clippos.X; - sv.y = clippos.Y; - sv.z = clippos.Z; - sv.w = clippos.W; - sv.worldX = objpos.X; - sv.worldY = objpos.Y; - sv.worldZ = objpos.Z; - sv.clipDistance[0] = 1.0f; - sv.clipDistance[1] = 1.0f; - sv.clipDistance[2] = 1.0f; - return sv; + thread->mainVertexShader.aPosition = { attrVertex[0], attrVertex[1], attrVertex[2], 1.0f }; + thread->mainVertexShader.aTexCoord = { attrTexcoord[0], attrTexcoord[1] }; } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/rendering/polyrenderer/backend/poly_buffers.h b/src/rendering/polyrenderer/backend/poly_buffers.h index 2ad9e11f9..b4e183194 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.h +++ b/src/rendering/polyrenderer/backend/poly_buffers.h @@ -39,13 +39,13 @@ private: std::vector mData; }; -class PolyVertexBuffer : public IVertexBuffer, public PolyBuffer, public PolyVertexShader +class PolyVertexBuffer : public IVertexBuffer, public PolyBuffer, public PolyInputAssembly { public: PolyVertexBuffer() { } void SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) override; - ShadedTriVertex Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) override; + void Load(PolyTriangleThreadData *thread, const void *vertices, int index) override; private: size_t mOffsets[VATTR_MAX] = {}; diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index ea1148d1a..6b99db945 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -26,6 +26,7 @@ static PolyDrawMode dtToDrawMode[] = PolyRenderState::PolyRenderState() { + mIdentityMatrix.loadIdentity(); Reset(); } @@ -175,23 +176,71 @@ void PolyRenderState::Apply() auto fb = GetPolyFrameBuffer(); if (mVertexBuffer) PolyTriangleDrawer::SetVertexBuffer(fb->GetDrawCommands(), mVertexBuffer->Memory()); if (mIndexBuffer) PolyTriangleDrawer::SetIndexBuffer(fb->GetDrawCommands(), mIndexBuffer->Memory()); - PolyTriangleDrawer::SetVertexShader(fb->GetDrawCommands(), static_cast(mVertexBuffer)); + PolyTriangleDrawer::SetInputAssembly(fb->GetDrawCommands(), static_cast(mVertexBuffer)); + + ApplyMatrices(); + + PolyTriangleDrawer::PushStreamData(fb->GetDrawCommands(), mStreamData, { mClipSplit[0], mClipSplit[1] }); + PolyTriangleDrawer::SetTwoSided(fb->GetDrawCommands(), true); PolyTriangleDrawer::PushConstants(fb->GetDrawCommands(), args); drawcalls.Unclock(); } +template +static void BufferedSet(bool &modified, T &dst, const T &src) +{ + if (dst == src) + return; + dst = src; + modified = true; +} + +static void BufferedSet(bool &modified, VSMatrix &dst, const VSMatrix &src) +{ + if (memcmp(dst.get(), src.get(), sizeof(FLOATTYPE) * 16) == 0) + return; + dst = src; + modified = true; +} + +void PolyRenderState::ApplyMatrices() +{ + bool modified = mFirstMatrixApply; + if (mTextureMatrixEnabled) + { + BufferedSet(modified, mMatrices.TextureMatrix, mTextureMatrix); + } + else + { + BufferedSet(modified, mMatrices.TextureMatrix, mIdentityMatrix); + } + + if (mModelMatrixEnabled) + { + BufferedSet(modified, mMatrices.ModelMatrix, mModelMatrix); + if (modified) + mMatrices.NormalModelMatrix.computeNormalMatrix(mModelMatrix); + } + else + { + BufferedSet(modified, mMatrices.ModelMatrix, mIdentityMatrix); + BufferedSet(modified, mMatrices.NormalModelMatrix, mIdentityMatrix); + } + + if (modified) + { + mFirstMatrixApply = false; + PolyTriangleDrawer::PushMatrices(GetPolyFrameBuffer()->GetDrawCommands(), mMatrices.ModelMatrix, mMatrices.NormalModelMatrix, mMatrices.TextureMatrix); + } +} + void PolyRenderState::Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t length) { if (buffer->bindingpoint == VIEWPOINT_BINDINGPOINT) { mViewpointUniforms = reinterpret_cast(static_cast(buffer->Memory()) + offset); - - Mat4f viewToProj = Mat4f::FromValues(mViewpointUniforms->mProjectionMatrix.get()); - Mat4f worldToView = Mat4f::FromValues(mViewpointUniforms->mViewMatrix.get()); - - auto fb = GetPolyFrameBuffer(); - PolyTriangleDrawer::SetTransform(fb->GetDrawCommands(), fb->GetFrameMemory()->NewObject(viewToProj * worldToView), nullptr); + PolyTriangleDrawer::SetViewpointUniforms(GetPolyFrameBuffer()->GetDrawCommands(), mViewpointUniforms); } } diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.h b/src/rendering/polyrenderer/backend/poly_renderstate.h index 7e3676615..ab3637783 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.h +++ b/src/rendering/polyrenderer/backend/poly_renderstate.h @@ -44,6 +44,16 @@ public: private: void Apply(); + void ApplyMatrices(); + + struct Matrices + { + VSMatrix ModelMatrix; + VSMatrix NormalModelMatrix; + VSMatrix TextureMatrix; + } mMatrices; + VSMatrix mIdentityMatrix; + bool mFirstMatrixApply = true; HWViewpointUniforms *mViewpointUniforms = nullptr; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 14d3972e1..dbde652d9 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -86,9 +86,9 @@ void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, queue->Push(viewport_x, viewport_y, viewport_width, viewport_height, dest, dest_width, dest_height, dest_pitch, dest_bgra); } -void PolyTriangleDrawer::SetVertexShader(const DrawerCommandQueuePtr &queue, PolyVertexShader *shader) +void PolyTriangleDrawer::SetInputAssembly(const DrawerCommandQueuePtr &queue, PolyInputAssembly *input) { - queue->Push(shader); + queue->Push(input); } void PolyTriangleDrawer::SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld) @@ -131,6 +131,21 @@ void PolyTriangleDrawer::PushConstants(const DrawerCommandQueuePtr &queue, const queue->Push(args); } +void PolyTriangleDrawer::PushStreamData(const DrawerCommandQueuePtr &queue, const StreamData &data, const Vec2f &uClipSplit) +{ + queue->Push(data, uClipSplit); +} + +void PolyTriangleDrawer::PushMatrices(const DrawerCommandQueuePtr &queue, const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) +{ + queue->Push(modelMatrix, normalModelMatrix, textureMatrix); +} + +void PolyTriangleDrawer::SetViewpointUniforms(const DrawerCommandQueuePtr &queue, const HWViewpointUniforms *uniforms) +{ + queue->Push(uniforms); +} + void PolyTriangleDrawer::Draw(const DrawerCommandQueuePtr &queue, int index, int vcount, PolyDrawMode mode) { queue->Push(index, vcount, mode); @@ -197,8 +212,8 @@ void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, ui void PolyTriangleThreadData::SetTransform(const Mat4f *newObjectToClip, const Mat4f *newObjectToWorld) { - objectToClip = newObjectToClip; - objectToWorld = newObjectToWorld; + swVertexShader.objectToClip = newObjectToClip; + swVertexShader.objectToWorld = newObjectToWorld; } void PolyTriangleThreadData::PushConstants(const PolyDrawArgs &args) @@ -206,6 +221,24 @@ void PolyTriangleThreadData::PushConstants(const PolyDrawArgs &args) drawargs = args; } +void PolyTriangleThreadData::PushStreamData(const StreamData &data, const Vec2f &uClipSplit) +{ + mainVertexShader.Data = data; + mainVertexShader.uClipSplit = uClipSplit; +} + +void PolyTriangleThreadData::PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) +{ + mainVertexShader.ModelMatrix = modelMatrix; + mainVertexShader.NormalModelMatrix = normalModelMatrix; + mainVertexShader.TextureMatrix = textureMatrix; +} + +void PolyTriangleThreadData::SetViewpointUniforms(const HWViewpointUniforms *uniforms) +{ + mainVertexShader.Viewpoint = uniforms; +} + void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode drawmode) { if (vcount < 3) @@ -216,38 +249,41 @@ void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode dra TriDrawTriangleArgs args; args.uniforms = &drawargs; - ShadedTriVertex vert[3]; + ShadedTriVertex vertbuffer[3]; + ShadedTriVertex *vert[3] = { &vertbuffer[0], &vertbuffer[1], &vertbuffer[2] }; if (drawmode == PolyDrawMode::Triangles) { for (int i = 0; i < vcount / 3; i++) { for (int j = 0; j < 3; j++) - vert[j] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); + *vert[j] = ShadeVertex(*(elements++)); DrawShadedTriangle(vert, ccw, &args); } } else if (drawmode == PolyDrawMode::TriangleFan) { - vert[0] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); - vert[1] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); + *vert[0] = ShadeVertex(*(elements++)); + *vert[1] = ShadeVertex(*(elements++)); for (int i = 2; i < vcount; i++) { - vert[2] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); + *vert[2] = ShadeVertex(*(elements++)); DrawShadedTriangle(vert, ccw, &args); - vert[1] = vert[2]; + std::swap(vert[1], vert[2]); } } else // TriangleDrawMode::TriangleStrip { bool toggleccw = ccw; - vert[0] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); - vert[1] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); + *vert[0] = ShadeVertex(*(elements++)); + *vert[1] = ShadeVertex(*(elements++)); for (int i = 2; i < vcount; i++) { - vert[2] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); + *vert[2] = ShadeVertex(*(elements++)); DrawShadedTriangle(vert, toggleccw, &args); + ShadedTriVertex *vtmp = vert[0]; vert[0] = vert[1]; vert[1] = vert[2]; + vert[2] = vtmp; toggleccw = !toggleccw; } } @@ -263,116 +299,89 @@ void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode) int vinput = index; - ShadedTriVertex vert[3]; + ShadedTriVertex vertbuffer[3]; + ShadedTriVertex *vert[3] = { &vertbuffer[0], &vertbuffer[1], &vertbuffer[2] }; if (drawmode == PolyDrawMode::Triangles) { for (int i = 0; i < vcount / 3; i++) { for (int j = 0; j < 3; j++) - vert[j] = vertexShader->Shade(this, drawargs, vertices, vinput++); + *vert[j] = ShadeVertex(vinput++); DrawShadedTriangle(vert, ccw, &args); } } else if (drawmode == PolyDrawMode::TriangleFan) { - vert[0] = vertexShader->Shade(this, drawargs, vertices, vinput++); - vert[1] = vertexShader->Shade(this, drawargs, vertices, vinput++); + *vert[0] = ShadeVertex(vinput++); + *vert[1] = ShadeVertex(vinput++); for (int i = 2; i < vcount; i++) { - vert[2] = vertexShader->Shade(this, drawargs, vertices, vinput++); + *vert[2] = ShadeVertex(vinput++); DrawShadedTriangle(vert, ccw, &args); - vert[1] = vert[2]; + std::swap(vert[1], vert[2]); } } else // TriangleDrawMode::TriangleStrip { bool toggleccw = ccw; - vert[0] = vertexShader->Shade(this, drawargs, vertices, vinput++); - vert[1] = vertexShader->Shade(this, drawargs, vertices, vinput++); + *vert[0] = ShadeVertex(vinput++); + *vert[1] = ShadeVertex(vinput++); for (int i = 2; i < vcount; i++) { - vert[2] = vertexShader->Shade(this, drawargs, vertices, vinput++); + *vert[2] = ShadeVertex(vinput++); DrawShadedTriangle(vert, toggleccw, &args); + ShadedTriVertex *vtmp = vert[0]; vert[0] = vert[1]; vert[1] = vert[2]; + vert[2] = vtmp; toggleccw = !toggleccw; } } } -ShadedTriVertex PolyTriVertexShader::Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) +ShadedTriVertex PolyTriangleThreadData::ShadeVertex(int index) { - ShadedTriVertex sv; - Vec4f objpos; + inputAssembly->Load(this, vertices, index); + mainVertexShader.main(); + return mainVertexShader; +} +void PolySWInputAssembly::Load(PolyTriangleThreadData *thread, const void *vertices, int index) +{ if (thread->modelFrame1 == -1) { - const TriVertex &v = static_cast(vertices)[index]; - objpos = Vec4f(v.x, v.y, v.z, v.w); - sv.u = v.u; - sv.v = v.v; - } - else if (thread->modelFrame1 == thread->modelFrame2 || thread->modelInterpolationFactor == 0.f) - { - const FModelVertex &v = static_cast(vertices)[thread->modelFrame1 + index]; - objpos = Vec4f(v.x, v.y, v.z, 1.0f); - sv.u = v.u; - sv.v = v.v; + thread->swVertexShader.v1 = static_cast(vertices)[index]; } else { const FModelVertex &v1 = static_cast(vertices)[thread->modelFrame1 + index]; const FModelVertex &v2 = static_cast(vertices)[thread->modelFrame2 + index]; - float frac = thread->modelInterpolationFactor; - float inv_frac = 1.0f - frac; + thread->swVertexShader.v1.x = v1.x; + thread->swVertexShader.v1.y = v1.y; + thread->swVertexShader.v1.z = v1.z; + thread->swVertexShader.v1.w = 1.0f; + thread->swVertexShader.v1.u = v1.u; + thread->swVertexShader.v1.v = v1.v; - objpos = Vec4f(v1.x * inv_frac + v2.x * frac, v1.y * inv_frac + v2.y * frac, v1.z * inv_frac + v2.z * frac, 1.0f); - sv.u = v1.u; - sv.v = v1.v; + thread->swVertexShader.v2.x = v2.x; + thread->swVertexShader.v2.y = v2.y; + thread->swVertexShader.v2.z = v2.z; + thread->swVertexShader.v2.w = 1.0f; + thread->swVertexShader.v2.u = v2.u; + thread->swVertexShader.v2.v = v2.v; } - - // Apply transform to get clip coordinates: - Vec4f clippos = (*thread->objectToClip) * objpos; - - sv.x = clippos.X; - sv.y = clippos.Y; - sv.z = clippos.Z; - sv.w = clippos.W; - - if (!thread->objectToWorld) // Identity matrix - { - sv.worldX = objpos.X; - sv.worldY = objpos.Y; - sv.worldZ = objpos.Z; - } - else - { - Vec4f worldpos = (*thread->objectToWorld) * objpos; - sv.worldX = worldpos.X; - sv.worldY = worldpos.Y; - sv.worldZ = worldpos.Z; - } - - // Calculate gl_ClipDistance[i] - for (int i = 0; i < 3; i++) - { - const auto &clipPlane = drawargs.ClipPlane(i); - sv.clipDistance[i] = objpos.X * clipPlane.A + objpos.Y * clipPlane.B + objpos.Z * clipPlane.C + objpos.W * clipPlane.D; - } - - return sv; } -bool PolyTriangleThreadData::IsDegenerate(const ShadedTriVertex *vert) +bool PolyTriangleThreadData::IsDegenerate(const ShadedTriVertex *const* vert) { // A degenerate triangle has a zero cross product for two of its sides. - float ax = vert[1].x - vert[0].x; - float ay = vert[1].y - vert[0].y; - float az = vert[1].w - vert[0].w; - float bx = vert[2].x - vert[0].x; - float by = vert[2].y - vert[0].y; - float bz = vert[2].w - vert[0].w; + float ax = vert[1]->gl_Position.X - vert[0]->gl_Position.X; + float ay = vert[1]->gl_Position.Y - vert[0]->gl_Position.Y; + float az = vert[1]->gl_Position.W - vert[0]->gl_Position.W; + float bx = vert[2]->gl_Position.X - vert[0]->gl_Position.X; + float by = vert[2]->gl_Position.Y - vert[0]->gl_Position.Y; + float bz = vert[2]->gl_Position.W - vert[0]->gl_Position.W; float crossx = ay * bz - az * by; float crossy = az * bx - ax * bz; float crossz = ax * by - ay * bx; @@ -389,15 +398,35 @@ bool PolyTriangleThreadData::IsFrontfacing(TriDrawTriangleArgs *args) return a <= 0.0f; } -void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *vert, bool ccw, TriDrawTriangleArgs *args) +void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* vert, bool ccw, TriDrawTriangleArgs *args) { // Reject triangle if degenerate if (IsDegenerate(vert)) return; // Cull, clip and generate additional vertices as needed - ShadedTriVertex clippedvert[max_additional_vertices]; - int numclipvert = ClipEdge(vert, clippedvert); + ScreenTriVertex clippedvert[max_additional_vertices]; + int numclipvert = ClipEdge(vert); + + // Convert barycentric weights to actual vertices + for (int i = 0; i < numclipvert; i++) + { + auto &v = clippedvert[i]; + memset(&v, 0, sizeof(ScreenTriVertex)); + for (int w = 0; w < 3; w++) + { + float weight = weights[i * 3 + w]; + v.x += vert[w]->gl_Position.X * weight; + v.y += vert[w]->gl_Position.Y * weight; + v.z += vert[w]->gl_Position.Z * weight; + v.w += vert[w]->gl_Position.W * weight; + v.u += vert[w]->vTexCoord.X * weight; + v.v += vert[w]->vTexCoord.Y * weight; + v.worldX += vert[w]->pixelpos.X * weight; + v.worldY += vert[w]->pixelpos.Y * weight; + v.worldZ += vert[w]->pixelpos.Z * weight; + } + } #ifdef NO_SSE // Map to 2D viewport: @@ -499,8 +528,18 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *vert, boo } } -int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert) +int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *const* verts) { + // use barycentric weights for clipped vertices + weights = weightsbuffer; + for (int i = 0; i < 3; i++) + { + weights[i * 3 + 0] = 0.0f; + weights[i * 3 + 1] = 0.0f; + weights[i * 3 + 2] = 0.0f; + weights[i * 3 + i] = 1.0f; + } + // Clip and cull so that the following is true for all vertices: // -v.w <= v.x <= v.w // -v.w <= v.y <= v.w @@ -514,16 +553,16 @@ int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *verts, ShadedTriVert float *clipd = clipdistance; for (int i = 0; i < 3; i++) { - const auto &v = verts[i]; - clipd[0] = v.x + v.w; - clipd[1] = v.w - v.x; - clipd[2] = v.y + v.w; - clipd[3] = v.w - v.y; - clipd[4] = v.z + v.w; - clipd[5] = v.w - v.z; - clipd[6] = v.clipDistance[0]; - clipd[7] = v.clipDistance[1]; - clipd[8] = v.clipDistance[2]; + const auto &v = *verts[i]; + clipd[0] = v.gl_Position.X + v.gl_Position.W; + clipd[1] = v.gl_Position.W - v.gl_Position.X; + clipd[2] = v.gl_Position.Y + v.gl_Position.W; + clipd[3] = v.gl_Position.W - v.gl_Position.Y; + clipd[4] = v.gl_Position.Z + v.gl_Position.W; + clipd[5] = v.gl_Position.W - v.gl_Position.Z; + clipd[6] = v.gl_ClipDistance[0]; + clipd[7] = v.gl_ClipDistance[1]; + clipd[8] = v.gl_ClipDistance[2]; for (int j = 0; j < 9; j++) needsclipping = needsclipping || clipd[i]; clipd += numclipdistances; @@ -532,16 +571,12 @@ int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *verts, ShadedTriVert // If all halfspace clip distances are positive then the entire triangle is visible. Skip the expensive clipping step. if (!needsclipping) { - for (int i = 0; i < 3; i++) - { - memcpy(clippedvert + i, &verts[i], sizeof(ShadedTriVertex)); - } return 3; } #else - __m128 mx = _mm_loadu_ps(&verts[0].x); - __m128 my = _mm_loadu_ps(&verts[1].x); - __m128 mz = _mm_loadu_ps(&verts[2].x); + __m128 mx = _mm_loadu_ps(&verts[0]->gl_Position.X); + __m128 my = _mm_loadu_ps(&verts[1]->gl_Position.X); + __m128 mz = _mm_loadu_ps(&verts[2]->gl_Position.X); __m128 mw = _mm_setzero_ps(); _MM_TRANSPOSE4_PS(mx, my, mz, mw); __m128 clipd0 = _mm_add_ps(mx, mw); @@ -550,9 +585,9 @@ int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *verts, ShadedTriVert __m128 clipd3 = _mm_sub_ps(mw, my); __m128 clipd4 = _mm_add_ps(mz, mw); __m128 clipd5 = _mm_sub_ps(mw, mz); - __m128 clipd6 = _mm_setr_ps(verts[0].clipDistance[0], verts[1].clipDistance[0], verts[2].clipDistance[0], 0.0f); - __m128 clipd7 = _mm_setr_ps(verts[0].clipDistance[1], verts[1].clipDistance[1], verts[2].clipDistance[1], 0.0f); - __m128 clipd8 = _mm_setr_ps(verts[0].clipDistance[2], verts[1].clipDistance[2], verts[2].clipDistance[2], 0.0f); + __m128 clipd6 = _mm_setr_ps(verts[0]->gl_ClipDistance[0], verts[1]->gl_ClipDistance[0], verts[2]->gl_ClipDistance[0], 0.0f); + __m128 clipd7 = _mm_setr_ps(verts[0]->gl_ClipDistance[1], verts[1]->gl_ClipDistance[1], verts[2]->gl_ClipDistance[1], 0.0f); + __m128 clipd8 = _mm_setr_ps(verts[0]->gl_ClipDistance[2], verts[1]->gl_ClipDistance[2], verts[2]->gl_ClipDistance[2], 0.0f); __m128 mneedsclipping = _mm_cmplt_ps(clipd0, _mm_setzero_ps()); mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd1, _mm_setzero_ps())); mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd2, _mm_setzero_ps())); @@ -564,10 +599,6 @@ int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *verts, ShadedTriVert mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd8, _mm_setzero_ps())); if (_mm_movemask_ps(mneedsclipping) == 0) { - for (int i = 0; i < 3; i++) - { - memcpy(clippedvert + i, &verts[i], sizeof(ShadedTriVertex)); - } return 3; } float clipdistance[numclipdistances * 4]; @@ -582,16 +613,6 @@ int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *verts, ShadedTriVert _mm_storeu_ps(clipdistance + 32, clipd8); #endif - // use barycentric weights while clipping vertices - float weights[max_additional_vertices * 3 * 2]; - for (int i = 0; i < 3; i++) - { - weights[i * 3 + 0] = 0.0f; - weights[i * 3 + 1] = 0.0f; - weights[i * 3 + 2] = 0.0f; - weights[i * 3 + i] = 1.0f; - } - // Clip against each halfspace float *input = weights; float *output = weights + max_additional_vertices * 3; @@ -650,26 +671,8 @@ int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *verts, ShadedTriVert if (inputverts == 0) break; } - - // Convert barycentric weights to actual vertices - for (int i = 0; i < inputverts; i++) - { - auto &v = clippedvert[i]; - memset(&v, 0, sizeof(ShadedTriVertex)); - for (int w = 0; w < 3; w++) - { - float weight = input[i * 3 + w]; - v.x += verts[w].x * weight; - v.y += verts[w].y * weight; - v.z += verts[w].z * weight; - v.w += verts[w].w * weight; - v.u += verts[w].u * weight; - v.v += verts[w].v * weight; - v.worldX += verts[w].worldX * weight; - v.worldY += verts[w].worldY * weight; - v.worldZ += verts[w].worldZ * weight; - } - } + + weights = input; return inputverts; } @@ -704,13 +707,13 @@ void PolySetIndexBufferCommand::Execute(DrawerThread *thread) ///////////////////////////////////////////////////////////////////////////// -PolySetVertexShaderCommand::PolySetVertexShaderCommand(PolyVertexShader *shader) : shader(shader) +PolySetInputAssemblyCommand::PolySetInputAssemblyCommand(PolyInputAssembly *input) : input(input) { } -void PolySetVertexShaderCommand::Execute(DrawerThread *thread) +void PolySetInputAssemblyCommand::Execute(DrawerThread *thread) { - PolyTriangleThreadData::Get(thread)->SetVertexShader(shader); + PolyTriangleThreadData::Get(thread)->SetInputAssembly(input); } ///////////////////////////////////////////////////////////////////////////// @@ -804,6 +807,40 @@ void PolySetViewportCommand::Execute(DrawerThread *thread) ///////////////////////////////////////////////////////////////////////////// +PolySetViewpointUniformsCommand::PolySetViewpointUniformsCommand(const HWViewpointUniforms *uniforms) : uniforms(uniforms) +{ +} + +void PolySetViewpointUniformsCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->SetViewpointUniforms(uniforms); +} + +///////////////////////////////////////////////////////////////////////////// + +PolyPushMatricesCommand::PolyPushMatricesCommand(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) + : modelMatrix(modelMatrix), normalModelMatrix(normalModelMatrix), textureMatrix(textureMatrix) +{ +} + +void PolyPushMatricesCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->PushMatrices(modelMatrix, normalModelMatrix, textureMatrix); +} + +///////////////////////////////////////////////////////////////////////////// + +PolyPushStreamDataCommand::PolyPushStreamDataCommand(const StreamData &data, const Vec2f &uClipSplit) : data(data), uClipSplit(uClipSplit) +{ +} + +void PolyPushStreamDataCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->PushStreamData(data, uClipSplit); +} + +///////////////////////////////////////////////////////////////////////////// + PolyPushConstantsCommand::PolyPushConstantsCommand(const PolyDrawArgs &args) : args(args) { } diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 10287b696..d3f1fa6dc 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -32,7 +32,7 @@ class DCanvas; class PolyDrawerCommand; -class PolyVertexShader; +class PolyInputAssembly; class PolyTriangleDrawer { @@ -41,7 +41,7 @@ public: static void ClearDepth(const DrawerCommandQueuePtr &queue, float value); static void ClearStencil(const DrawerCommandQueuePtr &queue, uint8_t value); static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas); - static void SetVertexShader(const DrawerCommandQueuePtr &queue, PolyVertexShader *shader); + static void SetInputAssembly(const DrawerCommandQueuePtr &queue, PolyInputAssembly *input); static void SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw); static void SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided); static void SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable); @@ -49,42 +49,55 @@ public: static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld); static void SetVertexBuffer(const DrawerCommandQueuePtr &queue, const void *vertices); static void SetIndexBuffer(const DrawerCommandQueuePtr &queue, const void *elements); + static void SetViewpointUniforms(const DrawerCommandQueuePtr &queue, const HWViewpointUniforms *uniforms); static void PushConstants(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args); + static void PushStreamData(const DrawerCommandQueuePtr &queue, const StreamData &data, const Vec2f &uClipSplit); + static void PushMatrices(const DrawerCommandQueuePtr &queue, const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); static void Draw(const DrawerCommandQueuePtr &queue, int index, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); static void DrawIndexed(const DrawerCommandQueuePtr &queue, int index, int count, PolyDrawMode mode = PolyDrawMode::Triangles); static bool IsBgra(); }; -class PolyVertexShader +class PolyInputAssembly { public: - virtual ShadedTriVertex Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) = 0; + virtual void Load(PolyTriangleThreadData *thread, const void *vertices, int index) = 0; }; -class PolyTriVertexShader : public PolyVertexShader +class PolySWInputAssembly : public PolyInputAssembly { public: - ShadedTriVertex Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) override; + void Load(PolyTriangleThreadData *thread, const void *vertices, int index) override; }; class PolyTriangleThreadData { public: - PolyTriangleThreadData(int32_t core, int32_t num_cores, int32_t numa_node, int32_t num_numa_nodes, int numa_start_y, int numa_end_y) : core(core), num_cores(num_cores), numa_node(numa_node), num_numa_nodes(num_numa_nodes), numa_start_y(numa_start_y), numa_end_y(numa_end_y) { } + PolyTriangleThreadData(int32_t core, int32_t num_cores, int32_t numa_node, int32_t num_numa_nodes, int numa_start_y, int numa_end_y) + : core(core), num_cores(num_cores), numa_node(numa_node), num_numa_nodes(num_numa_nodes), numa_start_y(numa_start_y), numa_end_y(numa_end_y) + { + swVertexShader.drawargs = &drawargs; + } void ClearDepth(float value); void ClearStencil(uint8_t value); void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra); + void SetTransform(const Mat4f *objectToClip, const Mat4f *objectToWorld); void SetCullCCW(bool value) { ccw = value; } void SetTwoSided(bool value) { twosided = value; } void SetWeaponScene(bool value) { weaponScene = value; } - void SetModelVertexShader(int frame1, int frame2, float interpolationFactor) { modelFrame1 = frame1; modelFrame2 = frame2; modelInterpolationFactor = interpolationFactor; } - void SetVertexShader(PolyVertexShader *shader) { vertexShader = shader; } + void SetModelVertexShader(int frame1, int frame2, float interpolationFactor) { modelFrame1 = frame1; modelFrame2 = frame2; swVertexShader.modelInterpolationFactor = interpolationFactor; } + + void SetInputAssembly(PolyInputAssembly *input) { inputAssembly = input; } void SetVertexBuffer(const void *data) { vertices = data; } void SetIndexBuffer(const void *data) { elements = (const unsigned int *)data; } + void SetViewpointUniforms(const HWViewpointUniforms *uniforms); void PushConstants(const PolyDrawArgs &args); + void PushStreamData(const StreamData &data, const Vec2f &uClipSplit); + void PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); + void DrawIndexed(int index, int count, PolyDrawMode mode); void Draw(int index, int vcount, PolyDrawMode mode); @@ -140,30 +153,30 @@ public: const void *vertices = nullptr; const unsigned int *elements = nullptr; + PolyMainVertexShader mainVertexShader; + + int modelFrame1 = -1; + int modelFrame2 = -1; + PolySWVertexShader swVertexShader; + private: - void DrawShadedTriangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args); - static bool IsDegenerate(const ShadedTriVertex *vertices); + ShadedTriVertex ShadeVertex(int index); + void DrawShadedTriangle(const ShadedTriVertex *const* vertices, bool ccw, TriDrawTriangleArgs *args); + static bool IsDegenerate(const ShadedTriVertex *const* vertices); static bool IsFrontfacing(TriDrawTriangleArgs *args); - static int ClipEdge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert); + + int ClipEdge(const ShadedTriVertex *const* verts); int viewport_x = 0; int viewport_width = 0; int viewport_height = 0; bool ccw = true; bool twosided = false; -public: - const Mat4f *objectToClip = nullptr; - const Mat4f *objectToWorld = nullptr; -private: - int modelFrame1 = -1; - int modelFrame2 = -1; - float modelInterpolationFactor = 0.0f; - PolyVertexShader *vertexShader = nullptr; - PolyMainVertexShader mainVertexShader; + PolyInputAssembly *inputAssembly = nullptr; enum { max_additional_vertices = 16 }; - - friend class PolyTriVertexShader; + float weightsbuffer[max_additional_vertices * 3 * 2]; + float *weights = nullptr; }; class PolyDrawerCommand : public DrawerCommand @@ -191,14 +204,14 @@ private: const void *indices; }; -class PolySetVertexShaderCommand : public PolyDrawerCommand +class PolySetInputAssemblyCommand : public PolyDrawerCommand { public: - PolySetVertexShaderCommand(PolyVertexShader *shader); + PolySetInputAssemblyCommand(PolyInputAssembly *input); void Execute(DrawerThread *thread) override; private: - PolyVertexShader *shader; + PolyInputAssembly *input; }; class PolySetTransformCommand : public PolyDrawerCommand @@ -300,6 +313,39 @@ private: bool dest_bgra; }; +class PolySetViewpointUniformsCommand : public PolyDrawerCommand +{ +public: + PolySetViewpointUniformsCommand(const HWViewpointUniforms *uniforms); + void Execute(DrawerThread *thread) override; + +private: + const HWViewpointUniforms *uniforms; +}; + +class PolyPushMatricesCommand : public PolyDrawerCommand +{ +public: + PolyPushMatricesCommand(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); + void Execute(DrawerThread *thread) override; + +private: + VSMatrix modelMatrix; + VSMatrix normalModelMatrix; + VSMatrix textureMatrix; +}; + +class PolyPushStreamDataCommand : public PolyDrawerCommand +{ +public: + PolyPushStreamDataCommand(const StreamData &data, const Vec2f &uClipSplit); + void Execute(DrawerThread *thread) override; + +private: + StreamData data; + Vec2f uClipSplit; +}; + class PolyPushConstantsCommand : public PolyDrawerCommand { public: diff --git a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h index 758b0387c..56486d047 100644 --- a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h +++ b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h @@ -9,7 +9,16 @@ #include #endif -class PolyMainVertexShader +class ShadedTriVertex +{ +public: + Vec4f gl_Position; + float gl_ClipDistance[5]; + Vec4f vTexCoord; + Vec4f pixelpos; +}; + +class PolyMainVertexShader : public ShadedTriVertex { public: // Input @@ -21,11 +30,7 @@ public: Vec4f aNormal2; // Output - Vec4f gl_Position; - float gl_ClipDistance[5]; - Vec4f vTexCoord; Vec4f vColor; - Vec4f pixelpos; Vec3f glowdist; Vec3f gradientdist; Vec4f vWorldNormal; @@ -41,12 +46,10 @@ public: VSMatrix TextureMatrix; StreamData Data; Vec2f uClipSplit; - HWViewpointUniforms Viewpoint; + const HWViewpointUniforms *Viewpoint = nullptr; void main() { - float ClipDistance0, ClipDistance1, ClipDistance2, ClipDistance3, ClipDistance4; - Vec2f parmTexCoord = aTexCoord; Vec4f parmPosition = aPosition; @@ -56,7 +59,7 @@ public: else worldcoord = mul(ModelMatrix, parmPosition); - Vec4f eyeCoordPos = mul(Viewpoint.mViewMatrix, worldcoord); + Vec4f eyeCoordPos = mul(Viewpoint->mViewMatrix, worldcoord); vColor = aColor; @@ -87,12 +90,12 @@ public: if (Data.uSplitBottomPlane.Z != 0.0f) { - ClipDistance3 = ((Data.uSplitTopPlane.W + Data.uSplitTopPlane.X * worldcoord.X + Data.uSplitTopPlane.Y * worldcoord.Z) * Data.uSplitTopPlane.Z) - worldcoord.Y; - ClipDistance4 = worldcoord.Y - ((Data.uSplitBottomPlane.W + Data.uSplitBottomPlane.X * worldcoord.X + Data.uSplitBottomPlane.Y * worldcoord.Z) * Data.uSplitBottomPlane.Z); + gl_ClipDistance[3] = ((Data.uSplitTopPlane.W + Data.uSplitTopPlane.X * worldcoord.X + Data.uSplitTopPlane.Y * worldcoord.Z) * Data.uSplitTopPlane.Z) - worldcoord.Y; + gl_ClipDistance[4] = worldcoord.Y - ((Data.uSplitBottomPlane.W + Data.uSplitBottomPlane.X * worldcoord.X + Data.uSplitBottomPlane.Y * worldcoord.Z) * Data.uSplitBottomPlane.Z); } vWorldNormal = mul(NormalModelMatrix, Vec4f(normalize(mix3(aNormal, aNormal2, Data.uInterpolationFactor)), 1.0f)); - vEyeNormal = mul(Viewpoint.mNormalViewMatrix, vWorldNormal); + vEyeNormal = mul(Viewpoint->mNormalViewMatrix, vWorldNormal); } if (!SPHEREMAP) @@ -102,43 +105,39 @@ public: else { Vec3f u = normalize3(eyeCoordPos); - Vec3f n = normalize3(mul(Viewpoint.mNormalViewMatrix, Vec4f(parmTexCoord.X, 0.0f, parmTexCoord.Y, 0.0f))); + Vec3f n = normalize3(mul(Viewpoint->mNormalViewMatrix, Vec4f(parmTexCoord.X, 0.0f, parmTexCoord.Y, 0.0f))); Vec3f r = reflect(u, n); float m = 2.0f * sqrt(r.X*r.X + r.Y*r.Y + (r.Z + 1.0f)*(r.Z + 1.0f)); vTexCoord.X = r.X / m + 0.5f; vTexCoord.Y = r.Y / m + 0.5f; } - gl_Position = mul(Viewpoint.mProjectionMatrix, eyeCoordPos); + gl_Position = mul(Viewpoint->mProjectionMatrix, eyeCoordPos); - if (Viewpoint.mClipHeightDirection != 0.0f) // clip planes used for reflective flats + if (Viewpoint->mClipHeightDirection != 0.0f) // clip planes used for reflective flats { - ClipDistance0 = (worldcoord.Y - Viewpoint.mClipHeight) * Viewpoint.mClipHeightDirection; + gl_ClipDistance[0] = (worldcoord.Y - Viewpoint->mClipHeight) * Viewpoint->mClipHeightDirection; } - else if (Viewpoint.mClipLine.X > -1000000.0f) // and for line portals - this will never be active at the same time as the reflective planes clipping so it can use the same hardware clip plane. + else if (Viewpoint->mClipLine.X > -1000000.0f) // and for line portals - this will never be active at the same time as the reflective planes clipping so it can use the same hardware clip plane. { - ClipDistance0 = -((worldcoord.Z - Viewpoint.mClipLine.Y) * Viewpoint.mClipLine.Z + (Viewpoint.mClipLine.X - worldcoord.X) * Viewpoint.mClipLine.W) + 1.0f / 32768.0f; // allow a tiny bit of imprecisions for colinear linedefs. + gl_ClipDistance[0] = -((worldcoord.Z - Viewpoint->mClipLine.Y) * Viewpoint->mClipLine.Z + (Viewpoint->mClipLine.X - worldcoord.X) * Viewpoint->mClipLine.W) + 1.0f / 32768.0f; // allow a tiny bit of imprecisions for colinear linedefs. } else { - ClipDistance0 = 1.0f; + gl_ClipDistance[0] = 1.0f; } // clip planes used for translucency splitting - ClipDistance1 = worldcoord.Y - uClipSplit.X; - ClipDistance2 = uClipSplit.Y - worldcoord.Y; + gl_ClipDistance[1] = worldcoord.Y - uClipSplit.X; + gl_ClipDistance[2] = uClipSplit.Y - worldcoord.Y; if (Data.uSplitTopPlane == FVector4(0.0f, 0.0f, 0.0f, 0.0f)) { - ClipDistance3 = 1.0f; - ClipDistance4 = 1.0f; + gl_ClipDistance[3] = 1.0f; + gl_ClipDistance[4] = 1.0f; } - gl_ClipDistance[0] = ClipDistance0; - gl_ClipDistance[1] = ClipDistance1; - gl_ClipDistance[2] = ClipDistance2; - gl_ClipDistance[3] = ClipDistance3; - gl_ClipDistance[4] = ClipDistance4; + std::swap(vTexCoord.X, vTexCoord.Y); // textures are transposed because the software renderer did them this way } private: @@ -198,3 +197,59 @@ private: return result; } }; + +class PolySWVertexShader : public ShadedTriVertex +{ +public: + // Input + TriVertex v1; + TriVertex v2; + + // Uniforms + float modelInterpolationFactor = 0.0f; + const Mat4f *objectToClip = nullptr; + const Mat4f *objectToWorld = nullptr; + PolyDrawArgs *drawargs = nullptr; + + void main() + { + Vec4f objpos; + + if (modelInterpolationFactor == 0.f) + { + objpos = Vec4f(v1.x, v1.y, v1.z, v1.w); + vTexCoord.X = v1.u; + vTexCoord.Y = v1.v; + } + else + { + float frac = modelInterpolationFactor; + float inv_frac = 1.0f - frac; + + objpos = Vec4f(v1.x * inv_frac + v2.x * frac, v1.y * inv_frac + v2.y * frac, v1.z * inv_frac + v2.z * frac, 1.0f); + vTexCoord.X = v1.u; + vTexCoord.Y = v1.v; + } + + // Apply transform to get clip coordinates: + gl_Position = (*objectToClip) * objpos; + + if (!objectToWorld) // Identity matrix + { + pixelpos = objpos; + } + else + { + pixelpos = (*objectToWorld) * objpos; + } + + // Calculate gl_ClipDistance[i] + for (int i = 0; i < 3; i++) + { + const auto &clipPlane = drawargs->ClipPlane(i); + gl_ClipDistance[i] = objpos.X * clipPlane.A + objpos.Y * clipPlane.B + objpos.Z * clipPlane.C + objpos.W * clipPlane.D; + } + gl_ClipDistance[3] = 1.0f; + gl_ClipDistance[4] = 1.0f; + } +}; diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 82b652532..413b63d3d 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -38,7 +38,7 @@ #include "screen_triangle.h" #include "x86.h" -static void SortVertices(const TriDrawTriangleArgs *args, ShadedTriVertex **sortedVertices) +static void SortVertices(const TriDrawTriangleArgs *args, ScreenTriVertex **sortedVertices) { sortedVertices[0] = args->v1; sortedVertices[1] = args->v2; @@ -57,7 +57,7 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat using namespace TriScreenDrawerModes; // Sort vertices by Y position - ShadedTriVertex *sortedVertices[3]; + ScreenTriVertex *sortedVertices[3]; SortVertices(args, sortedVertices); int clipleft = 0; diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.h b/src/rendering/polyrenderer/drawers/screen_triangle.h index 613466593..92d346376 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.h +++ b/src/rendering/polyrenderer/drawers/screen_triangle.h @@ -31,11 +31,10 @@ class FString; class PolyDrawArgs; class PolyTriangleThreadData; -struct ShadedTriVertex +struct ScreenTriVertex { float x, y, z, w; float u, v; - float clipDistance[3]; float worldX, worldY, worldZ; }; @@ -47,9 +46,9 @@ struct ScreenTriangleStepVariables struct TriDrawTriangleArgs { - ShadedTriVertex *v1; - ShadedTriVertex *v2; - ShadedTriVertex *v3; + ScreenTriVertex *v1; + ScreenTriVertex *v2; + ScreenTriVertex *v3; const PolyDrawArgs *uniforms; ScreenTriangleStepVariables gradientX; ScreenTriangleStepVariables gradientY; diff --git a/src/rendering/swrenderer/things/r_model.cpp b/src/rendering/swrenderer/things/r_model.cpp index b59170128..1d666fdf4 100644 --- a/src/rendering/swrenderer/things/r_model.cpp +++ b/src/rendering/swrenderer/things/r_model.cpp @@ -148,8 +148,8 @@ namespace swrenderer SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor, Mat4f *worldToClip, bool mirrorWorldToClip) : Thread(thread), Clip3DFloor(clip3DFloor), WorldToClip(worldToClip), MirrorWorldToClip(mirrorWorldToClip) { - static PolyTriVertexShader shader; - PolyTriangleDrawer::SetVertexShader(thread->DrawQueue, &shader); + static PolySWInputAssembly input; + PolyTriangleDrawer::SetInputAssembly(thread->DrawQueue, &input); } void SWModelRenderer::AddLights(AActor *actor) From 8db5e72254b17a6c02a1fcdedee7c66a53a54ad6 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 27 May 2019 07:57:27 +0200 Subject: [PATCH 08/60] - add PolyTriangleDrawer functions for the operations needed by PolyRenderState --- .../polyrenderer/backend/poly_framebuffer.cpp | 3 - .../polyrenderer/backend/poly_renderstate.cpp | 125 ++++-- .../polyrenderer/backend/poly_renderstate.h | 2 +- .../polyrenderer/drawers/poly_triangle.cpp | 379 +++++++++--------- .../polyrenderer/drawers/poly_triangle.h | 310 +++++++++++--- src/rendering/swrenderer/things/r_model.cpp | 4 +- 6 files changed, 521 insertions(+), 302 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index 4131acae9..dce7b8499 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -92,8 +92,6 @@ void PolyFrameBuffer::InitializeState() mRenderState.reset(new PolyRenderState()); CheckCanvas(); - - PolyTriangleDrawer::SetTransform(GetDrawCommands(), GetFrameMemory()->NewObject(Mat4f::Identity()), nullptr); } void PolyFrameBuffer::CheckCanvas() @@ -149,7 +147,6 @@ void PolyFrameBuffer::Update() } CheckCanvas(); - PolyTriangleDrawer::SetTransform(GetDrawCommands(), GetFrameMemory()->NewObject(Mat4f::Identity()), nullptr); Super::Update(); } diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 6b99db945..2f2cccf75 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -57,37 +57,50 @@ bool PolyRenderState::SetDepthClamp(bool on) { bool lastValue = mDepthClamp; mDepthClamp = on; + PolyTriangleDrawer::SetDepthClamp(GetPolyFrameBuffer()->GetDrawCommands(), on); return lastValue; } void PolyRenderState::SetDepthMask(bool on) { - args.SetWriteDepth(on); + PolyTriangleDrawer::SetDepthMask(GetPolyFrameBuffer()->GetDrawCommands(), on); } void PolyRenderState::SetDepthFunc(int func) { + PolyTriangleDrawer::SetDepthFunc(GetPolyFrameBuffer()->GetDrawCommands(), func); } void PolyRenderState::SetDepthRange(float min, float max) { + PolyTriangleDrawer::SetDepthRange(GetPolyFrameBuffer()->GetDrawCommands(), min, max); } void PolyRenderState::SetColorMask(bool r, bool g, bool b, bool a) { - args.SetWriteColor(r || g || b || a); + PolyTriangleDrawer::SetColorMask(GetPolyFrameBuffer()->GetDrawCommands(), r, g, b, a); } void PolyRenderState::SetStencil(int offs, int op, int flags) { + PolyTriangleDrawer::SetStencil(GetPolyFrameBuffer()->GetDrawCommands(), screen->stencilValue + offs, op); + + if (flags != -1) + { + bool cmon = !(flags & SF_ColorMaskOff); + SetColorMask(cmon, cmon, cmon, cmon); // don't write to the graphics buffer + SetDepthMask(!(flags & SF_DepthMaskOff)); + } } void PolyRenderState::SetCulling(int mode) { + PolyTriangleDrawer::SetCulling(GetPolyFrameBuffer()->GetDrawCommands(), mode); } void PolyRenderState::EnableClipDistance(int num, bool state) { + PolyTriangleDrawer::EnableClipDistance(GetPolyFrameBuffer()->GetDrawCommands(), num, state); } void PolyRenderState::Clear(int targets) @@ -102,21 +115,38 @@ void PolyRenderState::Clear(int targets) void PolyRenderState::EnableStencil(bool on) { + PolyTriangleDrawer::EnableStencil(GetPolyFrameBuffer()->GetDrawCommands(), on); } void PolyRenderState::SetScissor(int x, int y, int w, int h) { + auto fb = GetPolyFrameBuffer(); + if (w < 0) + { + x = 0; + y = 0; + w = fb->GetCanvas()->GetWidth(); + h = fb->GetCanvas()->GetHeight(); + } + PolyTriangleDrawer::SetScissor(fb->GetDrawCommands(), x, y, w, h); } void PolyRenderState::SetViewport(int x, int y, int w, int h) { auto fb = GetPolyFrameBuffer(); + if (w < 0) + { + x = 0; + y = 0; + w = fb->GetCanvas()->GetWidth(); + h = fb->GetCanvas()->GetHeight(); + } PolyTriangleDrawer::SetViewport(fb->GetDrawCommands(), x, y, w, h, fb->GetCanvas()); } void PolyRenderState::EnableDepthTest(bool on) { - args.SetDepthTest(on); + PolyTriangleDrawer::EnableDepthTest(GetPolyFrameBuffer()->GetDrawCommands(), on); } void PolyRenderState::EnableMultisampling(bool on) @@ -134,58 +164,71 @@ void PolyRenderState::EnableDrawBuffers(int count) void PolyRenderState::Apply() { drawcalls.Clock(); + auto fb = GetPolyFrameBuffer(); - args.SetStencilTest(false); - args.SetWriteStencil(false); + PolyPushConstants constants; - FColormap cm; - cm.Clear(); - args.SetLight(GetColorTable(cm), (int)(mLightParms[3] * 255.0f), mViewpointUniforms->mGlobVis, true); + int fogset = 0; + if (mFogEnabled) + { + if (mFogEnabled == 2) + { + fogset = -3; // 2D rendering with 'foggy' overlay. + } + else if ((GetFogColor() & 0xffffff) == 0) + { + fogset = gl_fogmode; + } + else + { + fogset = -gl_fogmode; + } + } - args.SetColor(MAKEARGB( - static_cast(mStreamData.uVertexColor.W * 255.0f + 0.5f), - static_cast(mStreamData.uVertexColor.X * 255.0f + 0.5f), - static_cast(mStreamData.uVertexColor.Y * 255.0f + 0.5f), - static_cast(mStreamData.uVertexColor.Z * 255.0f + 0.5f)), 0); + int tempTM = TM_NORMAL; + if (mMaterial.mMaterial && mMaterial.mMaterial->tex && mMaterial.mMaterial->tex->isHardwareCanvas()) + tempTM = TM_OPAQUE; + constants.uFogEnabled = fogset; + constants.uTextureMode = mTextureMode == TM_NORMAL && tempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode; + constants.uLightDist = mLightParms[0]; + constants.uLightFactor = mLightParms[1]; + constants.uFogDensity = mLightParms[2]; + constants.uLightLevel = mLightParms[3]; + constants.uAlphaThreshold = mAlphaThreshold; + constants.uClipSplit = { mClipSplit[0], mClipSplit[1] }; + constants.uLightIndex = mLightIndex; + + if (mVertexBuffer) PolyTriangleDrawer::SetVertexBuffer(fb->GetDrawCommands(), mVertexBuffer->Memory()); + if (mIndexBuffer) PolyTriangleDrawer::SetIndexBuffer(fb->GetDrawCommands(), mIndexBuffer->Memory()); + PolyTriangleDrawer::SetInputAssembly(fb->GetDrawCommands(), static_cast(mVertexBuffer)); + PolyTriangleDrawer::SetRenderStyle(fb->GetDrawCommands(), mRenderStyle); + PolyTriangleDrawer::PushStreamData(fb->GetDrawCommands(), mStreamData, constants); + ApplyMatrices(); + ApplyMaterial(); + + if (mBias.mChanged) + { + PolyTriangleDrawer::SetDepthBias(fb->GetDrawCommands(), mBias.mUnits, mBias.mFactor); + mBias.mChanged = false; + } + + drawcalls.Unclock(); +} + +void PolyRenderState::ApplyMaterial() +{ if (mMaterial.mChanged && mMaterial.mMaterial) { auto base = static_cast(mMaterial.mMaterial->GetLayer(0, mMaterial.mTranslation)); if (base) { DCanvas *texcanvas = base->GetImage(mMaterial); - args.SetTexture(texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth()); - - if (mRenderStyle == LegacyRenderStyles[STYLE_Normal]) - args.SetStyle(TriBlendMode::Normal); - else if (mRenderStyle == LegacyRenderStyles[STYLE_Add]) - args.SetStyle(TriBlendMode::Add); - else if (mRenderStyle == LegacyRenderStyles[STYLE_Translucent]) - args.SetStyle(TriBlendMode::Translucent); - else - args.SetStyle(TriBlendMode::Opaque); - } - else - { - args.SetStyle(TriBlendMode::Fill); + PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth()); } mMaterial.mChanged = false; } - - auto fb = GetPolyFrameBuffer(); - if (mVertexBuffer) PolyTriangleDrawer::SetVertexBuffer(fb->GetDrawCommands(), mVertexBuffer->Memory()); - if (mIndexBuffer) PolyTriangleDrawer::SetIndexBuffer(fb->GetDrawCommands(), mIndexBuffer->Memory()); - PolyTriangleDrawer::SetInputAssembly(fb->GetDrawCommands(), static_cast(mVertexBuffer)); - - ApplyMatrices(); - - PolyTriangleDrawer::PushStreamData(fb->GetDrawCommands(), mStreamData, { mClipSplit[0], mClipSplit[1] }); - - PolyTriangleDrawer::SetTwoSided(fb->GetDrawCommands(), true); - PolyTriangleDrawer::PushConstants(fb->GetDrawCommands(), args); - - drawcalls.Unclock(); } template diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.h b/src/rendering/polyrenderer/backend/poly_renderstate.h index ab3637783..6052e910e 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.h +++ b/src/rendering/polyrenderer/backend/poly_renderstate.h @@ -44,6 +44,7 @@ public: private: void Apply(); + void ApplyMaterial(); void ApplyMatrices(); struct Matrices @@ -58,5 +59,4 @@ private: HWViewpointUniforms *mViewpointUniforms = nullptr; bool mDepthClamp = true; - PolyDrawArgs args; }; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index dbde652d9..ba4741d59 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -126,14 +126,84 @@ void PolyTriangleDrawer::SetIndexBuffer(const DrawerCommandQueuePtr &queue, cons queue->Push(elements); } -void PolyTriangleDrawer::PushConstants(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args) +void PolyTriangleDrawer::PushDrawArgs(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args) { - queue->Push(args); + queue->Push(args); } -void PolyTriangleDrawer::PushStreamData(const DrawerCommandQueuePtr &queue, const StreamData &data, const Vec2f &uClipSplit) +void PolyTriangleDrawer::SetDepthClamp(const DrawerCommandQueuePtr &queue, bool on) { - queue->Push(data, uClipSplit); + queue->Push(on); +} + +void PolyTriangleDrawer::SetDepthMask(const DrawerCommandQueuePtr &queue, bool on) +{ + queue->Push(on); +} + +void PolyTriangleDrawer::SetDepthFunc(const DrawerCommandQueuePtr &queue, int func) +{ + queue->Push(func); +} + +void PolyTriangleDrawer::SetDepthRange(const DrawerCommandQueuePtr &queue, float min, float max) +{ + queue->Push(min, max); +} + +void PolyTriangleDrawer::SetDepthBias(const DrawerCommandQueuePtr &queue, float depthBiasConstantFactor, float depthBiasSlopeFactor) +{ + queue->Push(depthBiasConstantFactor, depthBiasSlopeFactor); +} + +void PolyTriangleDrawer::SetColorMask(const DrawerCommandQueuePtr &queue, bool r, bool g, bool b, bool a) +{ + queue->Push(r, g, b, a); +} + +void PolyTriangleDrawer::SetStencil(const DrawerCommandQueuePtr &queue, int stencilRef, int op) +{ + queue->Push(stencilRef, op); +} + +void PolyTriangleDrawer::SetCulling(const DrawerCommandQueuePtr &queue, int mode) +{ + queue->Push(mode); +} + +void PolyTriangleDrawer::EnableClipDistance(const DrawerCommandQueuePtr &queue, int num, bool state) +{ + queue->Push(num, state); +} + +void PolyTriangleDrawer::EnableStencil(const DrawerCommandQueuePtr &queue, bool on) +{ + queue->Push(on); +} + +void PolyTriangleDrawer::SetScissor(const DrawerCommandQueuePtr &queue, int x, int y, int w, int h) +{ + queue->Push(x, y, w, h); +} + +void PolyTriangleDrawer::EnableDepthTest(const DrawerCommandQueuePtr &queue, bool on) +{ + queue->Push(on); +} + +void PolyTriangleDrawer::SetRenderStyle(const DrawerCommandQueuePtr &queue, FRenderStyle style) +{ + queue->Push(style); +} + +void PolyTriangleDrawer::SetTexture(const DrawerCommandQueuePtr &queue, void *pixels, int width, int height) +{ + queue->Push(pixels, width, height); +} + +void PolyTriangleDrawer::PushStreamData(const DrawerCommandQueuePtr &queue, const StreamData &data, const PolyPushConstants &constants) +{ + queue->Push(data, constants); } void PolyTriangleDrawer::PushMatrices(const DrawerCommandQueuePtr &queue, const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) @@ -216,15 +286,25 @@ void PolyTriangleThreadData::SetTransform(const Mat4f *newObjectToClip, const Ma swVertexShader.objectToWorld = newObjectToWorld; } -void PolyTriangleThreadData::PushConstants(const PolyDrawArgs &args) +void PolyTriangleThreadData::PushDrawArgs(const PolyDrawArgs &args) { drawargs = args; } -void PolyTriangleThreadData::PushStreamData(const StreamData &data, const Vec2f &uClipSplit) +void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPushConstants &constants) { mainVertexShader.Data = data; - mainVertexShader.uClipSplit = uClipSplit; + mainVertexShader.uClipSplit = constants.uClipSplit; + + FColormap cm; + cm.Clear(); + drawargs.SetLight(GetColorTable(cm), (int)(constants.uLightLevel * 255.0f), mainVertexShader.Viewpoint->mGlobVis, true); + + drawargs.SetColor(MAKEARGB( + static_cast(mainVertexShader.Data.uVertexColor.W * 255.0f + 0.5f), + static_cast(mainVertexShader.Data.uVertexColor.X * 255.0f + 0.5f), + static_cast(mainVertexShader.Data.uVertexColor.Y * 255.0f + 0.5f), + static_cast(mainVertexShader.Data.uVertexColor.Z * 255.0f + 0.5f)), 0); } void PolyTriangleThreadData::PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) @@ -239,6 +319,102 @@ void PolyTriangleThreadData::SetViewpointUniforms(const HWViewpointUniforms *uni mainVertexShader.Viewpoint = uniforms; } +void PolyTriangleThreadData::SetDepthClamp(bool on) +{ +} + +void PolyTriangleThreadData::SetDepthMask(bool on) +{ + drawargs.SetWriteDepth(on); +} + +void PolyTriangleThreadData::SetDepthFunc(int func) +{ +} + +void PolyTriangleThreadData::SetDepthRange(float min, float max) +{ +} + +void PolyTriangleThreadData::SetDepthBias(float depthBiasConstantFactor, float depthBiasSlopeFactor) +{ +} + +void PolyTriangleThreadData::SetColorMask(bool r, bool g, bool b, bool a) +{ + drawargs.SetWriteColor(r || g || b || a); +} + +void PolyTriangleThreadData::SetStencil(int stencilRef, int op) +{ + drawargs.SetStencilTestValue(stencilRef); + if (op == SOP_Increment) + { + drawargs.SetWriteStencil(drawargs.StencilTest(), MIN(stencilRef + 1, (int)255)); + } + else if (op == SOP_Decrement) + { + drawargs.SetWriteStencil(drawargs.StencilTest(), MAX(stencilRef - 1, (int)0)); + } + else // SOP_Keep + { + drawargs.SetWriteStencil(false, stencilRef); + } +} + +void PolyTriangleThreadData::SetCulling(int mode) +{ + SetTwoSided(mode == Cull_None); + SetCullCCW(mode == Cull_CCW); +} + +void PolyTriangleThreadData::EnableClipDistance(int num, bool state) +{ +} + +void PolyTriangleThreadData::EnableStencil(bool on) +{ + drawargs.SetStencilTest(on); + drawargs.SetWriteStencil(on && drawargs.StencilTestValue() != drawargs.StencilWriteValue(), drawargs.StencilWriteValue()); +} + +void PolyTriangleThreadData::SetScissor(int x, int y, int w, int h) +{ +} + +void PolyTriangleThreadData::EnableDepthTest(bool on) +{ + drawargs.SetDepthTest(on); +} + +void PolyTriangleThreadData::SetRenderStyle(FRenderStyle style) +{ + if (style == LegacyRenderStyles[STYLE_Normal]) drawargs.SetStyle(TriBlendMode::Normal); + else if (style == LegacyRenderStyles[STYLE_Fuzzy]) drawargs.SetStyle(TriBlendMode::Fuzzy); + //else if (style == LegacyRenderStyles[STYLE_SoulTrans]) drawargs.SetStyle(TriBlendMode::SoulTrans); + //else if (style == LegacyRenderStyles[STYLE_OptFuzzy]) drawargs.SetStyle(TriBlendMode::OptFuzzy); + else if (style == LegacyRenderStyles[STYLE_Stencil]) drawargs.SetStyle(TriBlendMode::Stencil); + else if (style == LegacyRenderStyles[STYLE_Translucent]) drawargs.SetStyle(TriBlendMode::Translucent); + else if (style == LegacyRenderStyles[STYLE_Add]) drawargs.SetStyle(TriBlendMode::Add); + //else if (style == LegacyRenderStyles[STYLE_Shaded]) drawargs.SetStyle(TriBlendMode::Shaded); + else if (style == LegacyRenderStyles[STYLE_TranslucentStencil]) drawargs.SetStyle(TriBlendMode::TranslucentStencil); + else if (style == LegacyRenderStyles[STYLE_Shadow]) drawargs.SetStyle(TriBlendMode::Shadow); + else if (style == LegacyRenderStyles[STYLE_Subtract]) drawargs.SetStyle(TriBlendMode::Subtract); + else if (style == LegacyRenderStyles[STYLE_AddStencil]) drawargs.SetStyle(TriBlendMode::AddStencil); + else if (style == LegacyRenderStyles[STYLE_AddShaded]) drawargs.SetStyle(TriBlendMode::AddShaded); + //else if (style == LegacyRenderStyles[STYLE_Multiply]) drawargs.SetStyle(TriBlendMode::Multiply); + //else if (style == LegacyRenderStyles[STYLE_InverseMultiply]) drawargs.SetStyle(TriBlendMode::InverseMultiply); + //else if (style == LegacyRenderStyles[STYLE_ColorBlend]) drawargs.SetStyle(TriBlendMode::ColorBlend); + //else if (style == LegacyRenderStyles[STYLE_Source]) drawargs.SetStyle(TriBlendMode::Source); + //else if (style == LegacyRenderStyles[STYLE_ColorAdd]) drawargs.SetStyle(TriBlendMode::ColorAdd); + else drawargs.SetStyle(TriBlendMode::Opaque); +} + +void PolyTriangleThreadData::SetTexture(void *pixels, int width, int height) +{ + drawargs.SetTexture((uint8_t*)pixels, width, height); +} + void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode drawmode) { if (vcount < 3) @@ -682,192 +858,3 @@ PolyTriangleThreadData *PolyTriangleThreadData::Get(DrawerThread *thread) thread->poly = std::make_shared(thread->core, thread->num_cores, thread->numa_node, thread->num_numa_nodes, thread->numa_start_y, thread->numa_end_y); return thread->poly.get(); } - -///////////////////////////////////////////////////////////////////////////// - -PolySetVertexBufferCommand::PolySetVertexBufferCommand(const void *vertices) : vertices(vertices) -{ -} - -void PolySetVertexBufferCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->SetVertexBuffer(vertices); -} - -///////////////////////////////////////////////////////////////////////////// - -PolySetIndexBufferCommand::PolySetIndexBufferCommand(const void *indices) : indices(indices) -{ -} - -void PolySetIndexBufferCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->SetIndexBuffer(indices); -} - -///////////////////////////////////////////////////////////////////////////// - -PolySetInputAssemblyCommand::PolySetInputAssemblyCommand(PolyInputAssembly *input) : input(input) -{ -} - -void PolySetInputAssemblyCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->SetInputAssembly(input); -} - -///////////////////////////////////////////////////////////////////////////// - -PolySetTransformCommand::PolySetTransformCommand(const Mat4f *objectToClip, const Mat4f *objectToWorld) : objectToClip(objectToClip), objectToWorld(objectToWorld) -{ -} - -void PolySetTransformCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->SetTransform(objectToClip, objectToWorld); -} - -///////////////////////////////////////////////////////////////////////////// - -PolySetCullCCWCommand::PolySetCullCCWCommand(bool ccw) : ccw(ccw) -{ -} - -void PolySetCullCCWCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->SetCullCCW(ccw); -} - -///////////////////////////////////////////////////////////////////////////// - -PolySetTwoSidedCommand::PolySetTwoSidedCommand(bool twosided) : twosided(twosided) -{ -} - -void PolySetTwoSidedCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->SetTwoSided(twosided); -} - -///////////////////////////////////////////////////////////////////////////// - -PolySetWeaponSceneCommand::PolySetWeaponSceneCommand(bool value) : value(value) -{ -} - -void PolySetWeaponSceneCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->SetWeaponScene(value); -} - -///////////////////////////////////////////////////////////////////////////// - -PolySetModelVertexShaderCommand::PolySetModelVertexShaderCommand(int frame1, int frame2, float interpolationFactor) : frame1(frame1), frame2(frame2), interpolationFactor(interpolationFactor) -{ -} - -void PolySetModelVertexShaderCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->SetModelVertexShader(frame1, frame2, interpolationFactor); -} - -///////////////////////////////////////////////////////////////////////////// - -PolyClearDepthCommand::PolyClearDepthCommand(float value) : value(value) -{ -} - -void PolyClearDepthCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->ClearDepth(value); -} - -///////////////////////////////////////////////////////////////////////////// - -PolyClearStencilCommand::PolyClearStencilCommand(uint8_t value) : value(value) -{ -} - -void PolyClearStencilCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->ClearStencil(value); -} - -///////////////////////////////////////////////////////////////////////////// - -PolySetViewportCommand::PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra) - : x(x), y(y), width(width), height(height), dest(dest), dest_width(dest_width), dest_height(dest_height), dest_pitch(dest_pitch), dest_bgra(dest_bgra) -{ -} - -void PolySetViewportCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->SetViewport(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra); -} - -///////////////////////////////////////////////////////////////////////////// - -PolySetViewpointUniformsCommand::PolySetViewpointUniformsCommand(const HWViewpointUniforms *uniforms) : uniforms(uniforms) -{ -} - -void PolySetViewpointUniformsCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->SetViewpointUniforms(uniforms); -} - -///////////////////////////////////////////////////////////////////////////// - -PolyPushMatricesCommand::PolyPushMatricesCommand(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) - : modelMatrix(modelMatrix), normalModelMatrix(normalModelMatrix), textureMatrix(textureMatrix) -{ -} - -void PolyPushMatricesCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->PushMatrices(modelMatrix, normalModelMatrix, textureMatrix); -} - -///////////////////////////////////////////////////////////////////////////// - -PolyPushStreamDataCommand::PolyPushStreamDataCommand(const StreamData &data, const Vec2f &uClipSplit) : data(data), uClipSplit(uClipSplit) -{ -} - -void PolyPushStreamDataCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->PushStreamData(data, uClipSplit); -} - -///////////////////////////////////////////////////////////////////////////// - -PolyPushConstantsCommand::PolyPushConstantsCommand(const PolyDrawArgs &args) : args(args) -{ -} - -void PolyPushConstantsCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->PushConstants(args); -} - -///////////////////////////////////////////////////////////////////////////// - -PolyDrawCommand::PolyDrawCommand(int index, int count, PolyDrawMode mode) : index(index), count(count), mode(mode) -{ -} - -void PolyDrawCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->Draw(index, count, mode); -} - -///////////////////////////////////////////////////////////////////////////// - -PolyDrawIndexedCommand::PolyDrawIndexedCommand(int index, int count, PolyDrawMode mode) : index(index), count(count), mode(mode) -{ -} - -void PolyDrawIndexedCommand::Execute(DrawerThread *thread) -{ - PolyTriangleThreadData::Get(thread)->DrawIndexed(index, count, mode); -} diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index d3f1fa6dc..17a55e93c 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -33,6 +33,8 @@ class DCanvas; class PolyDrawerCommand; class PolyInputAssembly; +class PolyPipeline; +struct PolyPushConstants; class PolyTriangleDrawer { @@ -42,20 +44,53 @@ public: static void ClearStencil(const DrawerCommandQueuePtr &queue, uint8_t value); static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas); static void SetInputAssembly(const DrawerCommandQueuePtr &queue, PolyInputAssembly *input); + static void SetVertexBuffer(const DrawerCommandQueuePtr &queue, const void *vertices); + static void SetIndexBuffer(const DrawerCommandQueuePtr &queue, const void *elements); + static void SetViewpointUniforms(const DrawerCommandQueuePtr &queue, const HWViewpointUniforms *uniforms); + static void SetDepthClamp(const DrawerCommandQueuePtr &queue, bool on); + static void SetDepthMask(const DrawerCommandQueuePtr &queue, bool on); + static void SetDepthFunc(const DrawerCommandQueuePtr &queue, int func); + static void SetDepthRange(const DrawerCommandQueuePtr &queue, float min, float max); + static void SetDepthBias(const DrawerCommandQueuePtr &queue, float depthBiasConstantFactor, float depthBiasSlopeFactor); + static void SetColorMask(const DrawerCommandQueuePtr &queue, bool r, bool g, bool b, bool a); + static void SetStencil(const DrawerCommandQueuePtr &queue, int stencilRef, int op); + static void SetCulling(const DrawerCommandQueuePtr &queue, int mode); + static void EnableClipDistance(const DrawerCommandQueuePtr &queue, int num, bool state); + static void EnableStencil(const DrawerCommandQueuePtr &queue, bool on); + static void SetScissor(const DrawerCommandQueuePtr &queue, int x, int y, int w, int h); + static void EnableDepthTest(const DrawerCommandQueuePtr &queue, bool on); + static void SetRenderStyle(const DrawerCommandQueuePtr &queue, FRenderStyle style); + static void SetTexture(const DrawerCommandQueuePtr &queue, void *pixels, int width, int height); + static void PushStreamData(const DrawerCommandQueuePtr &queue, const StreamData &data, const PolyPushConstants &constants); + static void PushMatrices(const DrawerCommandQueuePtr &queue, const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); + static void Draw(const DrawerCommandQueuePtr &queue, int index, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); + static void DrawIndexed(const DrawerCommandQueuePtr &queue, int index, int count, PolyDrawMode mode = PolyDrawMode::Triangles); + static bool IsBgra(); + + // Old softpoly/swrenderer interface static void SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw); static void SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided); static void SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable); static void SetModelVertexShader(const DrawerCommandQueuePtr &queue, int frame1, int frame2, float interpolationFactor); static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld); - static void SetVertexBuffer(const DrawerCommandQueuePtr &queue, const void *vertices); - static void SetIndexBuffer(const DrawerCommandQueuePtr &queue, const void *elements); - static void SetViewpointUniforms(const DrawerCommandQueuePtr &queue, const HWViewpointUniforms *uniforms); - static void PushConstants(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args); - static void PushStreamData(const DrawerCommandQueuePtr &queue, const StreamData &data, const Vec2f &uClipSplit); - static void PushMatrices(const DrawerCommandQueuePtr &queue, const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); - static void Draw(const DrawerCommandQueuePtr &queue, int index, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); - static void DrawIndexed(const DrawerCommandQueuePtr &queue, int index, int count, PolyDrawMode mode = PolyDrawMode::Triangles); - static bool IsBgra(); + static void PushDrawArgs(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args); +}; + +struct PolyPushConstants +{ + int uTextureMode; + float uAlphaThreshold; + Vec2f uClipSplit; + + // Lighting + Fog + float uLightLevel; + float uFogDensity; + float uLightFactor; + float uLightDist; + int uFogEnabled; + + // dynamic lights + int uLightIndex; }; class PolyInputAssembly @@ -93,9 +128,23 @@ public: void SetVertexBuffer(const void *data) { vertices = data; } void SetIndexBuffer(const void *data) { elements = (const unsigned int *)data; } void SetViewpointUniforms(const HWViewpointUniforms *uniforms); + void SetDepthClamp(bool on); + void SetDepthMask(bool on); + void SetDepthFunc(int func); + void SetDepthRange(float min, float max); + void SetDepthBias(float depthBiasConstantFactor, float depthBiasSlopeFactor); + void SetColorMask(bool r, bool g, bool b, bool a); + void SetStencil(int stencilRef, int op); + void SetCulling(int mode); + void EnableClipDistance(int num, bool state); + void EnableStencil(bool on); + void SetScissor(int x, int y, int w, int h); + void EnableDepthTest(bool on); + void SetRenderStyle(FRenderStyle style); + void SetTexture(void *pixels, int width, int height); - void PushConstants(const PolyDrawArgs &args); - void PushStreamData(const StreamData &data, const Vec2f &uClipSplit); + void PushDrawArgs(const PolyDrawArgs &args); + void PushStreamData(const StreamData &data, const PolyPushConstants &constants); void PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); void DrawIndexed(int index, int count, PolyDrawMode mode); @@ -171,7 +220,7 @@ private: int viewport_width = 0; int viewport_height = 0; bool ccw = true; - bool twosided = false; + bool twosided = true; PolyInputAssembly *inputAssembly = nullptr; enum { max_additional_vertices = 16 }; @@ -184,11 +233,163 @@ class PolyDrawerCommand : public DrawerCommand public: }; +class PolySetDepthClampCommand : public PolyDrawerCommand +{ +public: + PolySetDepthClampCommand(bool on) : on(on) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetDepthClamp(on); } + +private: + bool on; +}; + +class PolySetDepthMaskCommand : public PolyDrawerCommand +{ +public: + PolySetDepthMaskCommand(bool on) : on(on) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetDepthMask(on); } + +private: + bool on; +}; + +class PolySetDepthFuncCommand : public PolyDrawerCommand +{ +public: + PolySetDepthFuncCommand(int func) : func(func) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetDepthFunc(func); } + +private: + int func; +}; + +class PolySetDepthRangeCommand : public PolyDrawerCommand +{ +public: + PolySetDepthRangeCommand(float min, float max) : min(min), max(max) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetDepthRange(min, max); } + +private: + float min; + float max; +}; + +class PolySetDepthBiasCommand : public PolyDrawerCommand +{ +public: + PolySetDepthBiasCommand(float depthBiasConstantFactor, float depthBiasSlopeFactor) : depthBiasConstantFactor(depthBiasConstantFactor), depthBiasSlopeFactor(depthBiasSlopeFactor) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetDepthBias(depthBiasConstantFactor, depthBiasSlopeFactor); } + +private: + float depthBiasConstantFactor; + float depthBiasSlopeFactor; +}; + +class PolySetColorMaskCommand : public PolyDrawerCommand +{ +public: + PolySetColorMaskCommand(bool r, bool g, bool b, bool a) : r(r), g(g), b(b), a(a) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetColorMask(r, g, b, a); } + +private: + bool r; + bool g; + bool b; + bool a; +}; + +class PolySetStencilCommand : public PolyDrawerCommand +{ +public: + PolySetStencilCommand(int stencilRef, int op) : stencilRef(stencilRef), op(op) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetStencil(stencilRef, op); } + +private: + int stencilRef; + int op; +}; + +class PolySetCullingCommand : public PolyDrawerCommand +{ +public: + PolySetCullingCommand(int mode) : mode(mode) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetCulling(mode); } + +private: + int mode; +}; + +class PolyEnableClipDistanceCommand : public PolyDrawerCommand +{ +public: + PolyEnableClipDistanceCommand(int num, bool state) : num(num), state(state) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->EnableClipDistance(num, state); } + +private: + int num; + bool state; +}; + +class PolyEnableStencilCommand : public PolyDrawerCommand +{ +public: + PolyEnableStencilCommand(bool on) : on(on) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->EnableStencil(on); } + +private: + bool on; +}; + +class PolySetScissorCommand : public PolyDrawerCommand +{ +public: + PolySetScissorCommand(int x, int y, int w, int h) : x(x), y(y), w(w), h(h) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetScissor(x, y, w, h); } + +private: + int x; + int y; + int w; + int h; +}; + +class PolyEnableDepthTestCommand : public PolyDrawerCommand +{ +public: + PolyEnableDepthTestCommand(bool on) : on(on) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->EnableDepthTest(on); } + +private: + bool on; +}; + +class PolySetRenderStyleCommand : public PolyDrawerCommand +{ +public: + PolySetRenderStyleCommand(FRenderStyle style) : style(style) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetRenderStyle(style); } + +private: + FRenderStyle style; +}; + +class PolySetTextureCommand : public PolyDrawerCommand +{ +public: + PolySetTextureCommand(void *pixels, int width, int height) : pixels(pixels), width(width), height(height) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetTexture(pixels, width, height); } + +private: + void *pixels; + int width; + int height; +}; + class PolySetVertexBufferCommand : public PolyDrawerCommand { public: - PolySetVertexBufferCommand(const void *vertices); - void Execute(DrawerThread *thread) override; + PolySetVertexBufferCommand(const void *vertices) : vertices(vertices) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetVertexBuffer(vertices); } private: const void *vertices; @@ -197,8 +398,8 @@ private: class PolySetIndexBufferCommand : public PolyDrawerCommand { public: - PolySetIndexBufferCommand(const void *indices); - void Execute(DrawerThread *thread) override; + PolySetIndexBufferCommand(const void *indices) : indices(indices) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetIndexBuffer(indices); } private: const void *indices; @@ -207,8 +408,8 @@ private: class PolySetInputAssemblyCommand : public PolyDrawerCommand { public: - PolySetInputAssemblyCommand(PolyInputAssembly *input); - void Execute(DrawerThread *thread) override; + PolySetInputAssemblyCommand(PolyInputAssembly *input) : input(input) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetInputAssembly(input); } private: PolyInputAssembly *input; @@ -217,9 +418,8 @@ private: class PolySetTransformCommand : public PolyDrawerCommand { public: - PolySetTransformCommand(const Mat4f *objectToClip, const Mat4f *objectToWorld); - - void Execute(DrawerThread *thread) override; + PolySetTransformCommand(const Mat4f *objectToClip, const Mat4f *objectToWorld) : objectToClip(objectToClip), objectToWorld(objectToWorld) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetTransform(objectToClip, objectToWorld); } private: const Mat4f *objectToClip; @@ -229,9 +429,8 @@ private: class PolySetCullCCWCommand : public PolyDrawerCommand { public: - PolySetCullCCWCommand(bool ccw); - - void Execute(DrawerThread *thread) override; + PolySetCullCCWCommand(bool ccw) : ccw(ccw) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetCullCCW(ccw); } private: bool ccw; @@ -240,9 +439,8 @@ private: class PolySetTwoSidedCommand : public PolyDrawerCommand { public: - PolySetTwoSidedCommand(bool twosided); - - void Execute(DrawerThread *thread) override; + PolySetTwoSidedCommand(bool twosided) : twosided(twosided) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetTwoSided(twosided); } private: bool twosided; @@ -251,9 +449,8 @@ private: class PolySetWeaponSceneCommand : public PolyDrawerCommand { public: - PolySetWeaponSceneCommand(bool value); - - void Execute(DrawerThread *thread) override; + PolySetWeaponSceneCommand(bool value) : value(value) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetWeaponScene(value); } private: bool value; @@ -262,9 +459,8 @@ private: class PolySetModelVertexShaderCommand : public PolyDrawerCommand { public: - PolySetModelVertexShaderCommand(int frame1, int frame2, float interpolationFactor); - - void Execute(DrawerThread *thread) override; + PolySetModelVertexShaderCommand(int frame1, int frame2, float interpolationFactor) : frame1(frame1), frame2(frame2), interpolationFactor(interpolationFactor) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetModelVertexShader(frame1, frame2, interpolationFactor); } private: int frame1; @@ -275,9 +471,8 @@ private: class PolyClearDepthCommand : public PolyDrawerCommand { public: - PolyClearDepthCommand(float value); - - void Execute(DrawerThread *thread) override; + PolyClearDepthCommand(float value) : value(value) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->ClearDepth(value); } private: float value; @@ -286,9 +481,8 @@ private: class PolyClearStencilCommand : public PolyDrawerCommand { public: - PolyClearStencilCommand(uint8_t value); - - void Execute(DrawerThread *thread) override; + PolyClearStencilCommand(uint8_t value) : value(value) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->ClearStencil(value); } private: uint8_t value; @@ -297,9 +491,9 @@ private: class PolySetViewportCommand : public PolyDrawerCommand { public: - PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra); - - void Execute(DrawerThread *thread) override; + PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra) + : x(x), y(y), width(width), height(height), dest(dest), dest_width(dest_width), dest_height(dest_height), dest_pitch(dest_pitch), dest_bgra(dest_bgra) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetViewport(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra); } private: int x; @@ -316,8 +510,8 @@ private: class PolySetViewpointUniformsCommand : public PolyDrawerCommand { public: - PolySetViewpointUniformsCommand(const HWViewpointUniforms *uniforms); - void Execute(DrawerThread *thread) override; + PolySetViewpointUniformsCommand(const HWViewpointUniforms *uniforms) : uniforms(uniforms) {} + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetViewpointUniforms(uniforms); } private: const HWViewpointUniforms *uniforms; @@ -326,8 +520,9 @@ private: class PolyPushMatricesCommand : public PolyDrawerCommand { public: - PolyPushMatricesCommand(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); - void Execute(DrawerThread *thread) override; + PolyPushMatricesCommand(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) + : modelMatrix(modelMatrix), normalModelMatrix(normalModelMatrix), textureMatrix(textureMatrix) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->PushMatrices(modelMatrix, normalModelMatrix, textureMatrix); } private: VSMatrix modelMatrix; @@ -338,20 +533,19 @@ private: class PolyPushStreamDataCommand : public PolyDrawerCommand { public: - PolyPushStreamDataCommand(const StreamData &data, const Vec2f &uClipSplit); - void Execute(DrawerThread *thread) override; + PolyPushStreamDataCommand(const StreamData &data, const PolyPushConstants &constants) : data(data), constants(constants) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->PushStreamData(data, constants); } private: StreamData data; - Vec2f uClipSplit; + PolyPushConstants constants; }; -class PolyPushConstantsCommand : public PolyDrawerCommand +class PolyPushDrawArgsCommand : public PolyDrawerCommand { public: - PolyPushConstantsCommand(const PolyDrawArgs &args); - - void Execute(DrawerThread *thread) override; + PolyPushDrawArgsCommand(const PolyDrawArgs &args) : args(args) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->PushDrawArgs(args); } private: PolyDrawArgs args; @@ -360,9 +554,8 @@ private: class PolyDrawCommand : public PolyDrawerCommand { public: - PolyDrawCommand(int index, int count, PolyDrawMode mode); - - void Execute(DrawerThread *thread) override; + PolyDrawCommand(int index, int count, PolyDrawMode mode) : index(index), count(count), mode(mode) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->Draw(index, count, mode); } private: int index; @@ -373,9 +566,8 @@ private: class PolyDrawIndexedCommand : public PolyDrawerCommand { public: - PolyDrawIndexedCommand(int index, int count, PolyDrawMode mode); - - void Execute(DrawerThread *thread) override; + PolyDrawIndexedCommand(int index, int count, PolyDrawMode mode) : index(index), count(count), mode(mode) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->DrawIndexed(index, count, mode); } private: int index; diff --git a/src/rendering/swrenderer/things/r_model.cpp b/src/rendering/swrenderer/things/r_model.cpp index 1d666fdf4..227556d04 100644 --- a/src/rendering/swrenderer/things/r_model.cpp +++ b/src/rendering/swrenderer/things/r_model.cpp @@ -367,7 +367,7 @@ namespace swrenderer args.SetClipPlane(1, ClipTop); args.SetClipPlane(2, ClipBottom); - PolyTriangleDrawer::PushConstants(Thread->DrawQueue, args); + PolyTriangleDrawer::PushDrawArgs(Thread->DrawQueue, args); PolyTriangleDrawer::Draw(Thread->DrawQueue, start, count); } @@ -386,7 +386,7 @@ namespace swrenderer args.SetClipPlane(1, ClipTop); args.SetClipPlane(2, ClipBottom); - PolyTriangleDrawer::PushConstants(Thread->DrawQueue, args); + PolyTriangleDrawer::PushDrawArgs(Thread->DrawQueue, args); PolyTriangleDrawer::DrawIndexed(Thread->DrawQueue, static_cast(offset / sizeof(unsigned int)), numIndices); } From 0d8d50c23e25abbe94a5fb4236fa576b6eba6d8e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 27 May 2019 16:51:54 +0200 Subject: [PATCH 09/60] - fix viewport location - add scissor support --- .../polyrenderer/backend/poly_renderstate.cpp | 4 +- .../polyrenderer/drawers/poly_triangle.cpp | 38 +++++++++---------- .../polyrenderer/drawers/poly_triangle.h | 10 +++++ .../polyrenderer/drawers/screen_triangle.cpp | 8 ++-- src/rendering/swrenderer/scene/r_scene.cpp | 1 + 5 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 2f2cccf75..a21ebf108 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -128,7 +128,7 @@ void PolyRenderState::SetScissor(int x, int y, int w, int h) w = fb->GetCanvas()->GetWidth(); h = fb->GetCanvas()->GetHeight(); } - PolyTriangleDrawer::SetScissor(fb->GetDrawCommands(), x, y, w, h); + PolyTriangleDrawer::SetScissor(fb->GetDrawCommands(), x, fb->GetCanvas()->GetHeight() - y - h, w, h); } void PolyRenderState::SetViewport(int x, int y, int w, int h) @@ -141,7 +141,7 @@ void PolyRenderState::SetViewport(int x, int y, int w, int h) w = fb->GetCanvas()->GetWidth(); h = fb->GetCanvas()->GetHeight(); } - PolyTriangleDrawer::SetViewport(fb->GetDrawCommands(), x, y, w, h, fb->GetCanvas()); + PolyTriangleDrawer::SetViewport(fb->GetDrawCommands(), x, fb->GetCanvas()->GetHeight() - y - h, w, h, fb->GetCanvas()); } void PolyRenderState::EnableDepthTest(bool on) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index ba4741d59..914004485 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -71,19 +71,7 @@ void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, bool dest_bgra = canvas->IsBgra(); isBgraRenderTarget = dest_bgra; - int offsetx = clamp(x, 0, dest_width); - int pixelsize = dest_bgra ? 4 : 1; - - int viewport_x = x - offsetx; - int viewport_y = y; - int viewport_width = width; - int viewport_height = height; - - dest += offsetx * pixelsize; - dest_width = clamp(viewport_x + viewport_width, 0, dest_width - offsetx); - dest_height = clamp(viewport_y + viewport_height, 0, dest_height); - - queue->Push(viewport_x, viewport_y, viewport_width, viewport_height, dest, dest_width, dest_height, dest_pitch, dest_bgra); + queue->Push(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra); } void PolyTriangleDrawer::SetInputAssembly(const DrawerCommandQueuePtr &queue, PolyInputAssembly *input) @@ -276,8 +264,24 @@ void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, ui dest_height = new_dest_height; dest_pitch = new_dest_pitch; dest_bgra = new_dest_bgra; - ccw = true; - weaponScene = false; + UpdateClip(); +} + +void PolyTriangleThreadData::SetScissor(int x, int y, int w, int h) +{ + scissor.left = x; + scissor.right = x + w; + scissor.top = y; + scissor.bottom = y + h; + UpdateClip(); +} + +void PolyTriangleThreadData::UpdateClip() +{ + clip.left = MAX(MAX(viewport_x, scissor.left), 0); + clip.top = MAX(MAX(viewport_y, scissor.top), 0); + clip.right = MIN(MIN(viewport_x + viewport_width, scissor.right), dest_width); + clip.bottom = MIN(MIN(viewport_y + viewport_height, scissor.bottom), dest_height); } void PolyTriangleThreadData::SetTransform(const Mat4f *newObjectToClip, const Mat4f *newObjectToWorld) @@ -378,10 +382,6 @@ void PolyTriangleThreadData::EnableStencil(bool on) drawargs.SetWriteStencil(on && drawargs.StencilTestValue() != drawargs.StencilWriteValue(), drawargs.StencilWriteValue()); } -void PolyTriangleThreadData::SetScissor(int x, int y, int w, int h) -{ -} - void PolyTriangleThreadData::EnableDepthTest(bool on) { drawargs.SetDepthTest(on); diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 17a55e93c..a14216cae 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -143,6 +143,8 @@ public: void SetRenderStyle(FRenderStyle style); void SetTexture(void *pixels, int width, int height); + void UpdateClip(); + void PushDrawArgs(const PolyDrawArgs &args); void PushStreamData(const StreamData &data, const PolyPushConstants &constants); void PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); @@ -197,6 +199,14 @@ public: int viewport_y = 0; + struct ClipRect + { + int left = 0; + int top = 0; + int right = 0; + int bottom = 0; + } clip, scissor; + PolyDrawArgs drawargs; const void *vertices = nullptr; diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 413b63d3d..5f37e3b87 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -60,10 +60,10 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat ScreenTriVertex *sortedVertices[3]; SortVertices(args, sortedVertices); - int clipleft = 0; - int cliptop = MAX(thread->viewport_y, thread->numa_start_y); - int clipright = thread->dest_width; - int clipbottom = MIN(thread->dest_height, thread->numa_end_y); + int clipleft = thread->clip.left; + int cliptop = MAX(thread->clip.top, thread->numa_start_y); + int clipright = thread->clip.right; + int clipbottom = MIN(thread->clip.bottom, thread->numa_end_y); int topY = (int)(sortedVertices[0]->y + 0.5f); int midY = (int)(sortedVertices[1]->y + 0.5f); diff --git a/src/rendering/swrenderer/scene/r_scene.cpp b/src/rendering/swrenderer/scene/r_scene.cpp index 76fbec103..7bd5dcea3 100644 --- a/src/rendering/swrenderer/scene/r_scene.cpp +++ b/src/rendering/swrenderer/scene/r_scene.cpp @@ -276,6 +276,7 @@ namespace swrenderer PolyTriangleDrawer::ClearStencil(MainThread()->DrawQueue, 0); PolyTriangleDrawer::SetViewport(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight, thread->Viewport->RenderTarget); + PolyTriangleDrawer::SetScissor(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight); // Cull things outside the range seen by this thread VisibleSegmentRenderer visitor; From 117617aad8ac32587e3e73a5ca38b1adaf8390f2 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 27 May 2019 19:18:27 +0200 Subject: [PATCH 10/60] - minor blend and light adjustment --- .../polyrenderer/drawers/poly_triangle.cpp | 55 ++++++++++++------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 914004485..d712c3b96 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -302,7 +302,7 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu FColormap cm; cm.Clear(); - drawargs.SetLight(GetColorTable(cm), (int)(constants.uLightLevel * 255.0f), mainVertexShader.Viewpoint->mGlobVis, true); + drawargs.SetLight(GetColorTable(cm), (int)(constants.uLightLevel * 255.0f), mainVertexShader.Viewpoint->mGlobVis * 32.0f, false); drawargs.SetColor(MAKEARGB( static_cast(mainVertexShader.Data.uVertexColor.W * 255.0f + 0.5f), @@ -389,25 +389,40 @@ void PolyTriangleThreadData::EnableDepthTest(bool on) void PolyTriangleThreadData::SetRenderStyle(FRenderStyle style) { - if (style == LegacyRenderStyles[STYLE_Normal]) drawargs.SetStyle(TriBlendMode::Normal); - else if (style == LegacyRenderStyles[STYLE_Fuzzy]) drawargs.SetStyle(TriBlendMode::Fuzzy); - //else if (style == LegacyRenderStyles[STYLE_SoulTrans]) drawargs.SetStyle(TriBlendMode::SoulTrans); - //else if (style == LegacyRenderStyles[STYLE_OptFuzzy]) drawargs.SetStyle(TriBlendMode::OptFuzzy); - else if (style == LegacyRenderStyles[STYLE_Stencil]) drawargs.SetStyle(TriBlendMode::Stencil); - else if (style == LegacyRenderStyles[STYLE_Translucent]) drawargs.SetStyle(TriBlendMode::Translucent); - else if (style == LegacyRenderStyles[STYLE_Add]) drawargs.SetStyle(TriBlendMode::Add); - //else if (style == LegacyRenderStyles[STYLE_Shaded]) drawargs.SetStyle(TriBlendMode::Shaded); - else if (style == LegacyRenderStyles[STYLE_TranslucentStencil]) drawargs.SetStyle(TriBlendMode::TranslucentStencil); - else if (style == LegacyRenderStyles[STYLE_Shadow]) drawargs.SetStyle(TriBlendMode::Shadow); - else if (style == LegacyRenderStyles[STYLE_Subtract]) drawargs.SetStyle(TriBlendMode::Subtract); - else if (style == LegacyRenderStyles[STYLE_AddStencil]) drawargs.SetStyle(TriBlendMode::AddStencil); - else if (style == LegacyRenderStyles[STYLE_AddShaded]) drawargs.SetStyle(TriBlendMode::AddShaded); - //else if (style == LegacyRenderStyles[STYLE_Multiply]) drawargs.SetStyle(TriBlendMode::Multiply); - //else if (style == LegacyRenderStyles[STYLE_InverseMultiply]) drawargs.SetStyle(TriBlendMode::InverseMultiply); - //else if (style == LegacyRenderStyles[STYLE_ColorBlend]) drawargs.SetStyle(TriBlendMode::ColorBlend); - //else if (style == LegacyRenderStyles[STYLE_Source]) drawargs.SetStyle(TriBlendMode::Source); - //else if (style == LegacyRenderStyles[STYLE_ColorAdd]) drawargs.SetStyle(TriBlendMode::ColorAdd); - else drawargs.SetStyle(TriBlendMode::Opaque); + if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero && style.Flags == 0) + { + drawargs.SetStyle(TriBlendMode::Opaque); + } + else if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_Src && style.DestAlpha == STYLEALPHA_InvSrc) + { + drawargs.SetStyle(TriBlendMode::Normal); + } + else if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero) + { + drawargs.SetStyle(TriBlendMode::Normal); + } + else + { + if (style == LegacyRenderStyles[STYLE_Normal]) drawargs.SetStyle(TriBlendMode::Normal); + else if (style == LegacyRenderStyles[STYLE_Fuzzy]) drawargs.SetStyle(TriBlendMode::Fuzzy); + //else if (style == LegacyRenderStyles[STYLE_SoulTrans]) drawargs.SetStyle(TriBlendMode::SoulTrans); + //else if (style == LegacyRenderStyles[STYLE_OptFuzzy]) drawargs.SetStyle(TriBlendMode::OptFuzzy); + else if (style == LegacyRenderStyles[STYLE_Stencil]) drawargs.SetStyle(TriBlendMode::Stencil); + else if (style == LegacyRenderStyles[STYLE_Translucent]) drawargs.SetStyle(TriBlendMode::Translucent); + else if (style == LegacyRenderStyles[STYLE_Add]) drawargs.SetStyle(TriBlendMode::Add); + //else if (style == LegacyRenderStyles[STYLE_Shaded]) drawargs.SetStyle(TriBlendMode::Shaded); + else if (style == LegacyRenderStyles[STYLE_TranslucentStencil]) drawargs.SetStyle(TriBlendMode::TranslucentStencil); + else if (style == LegacyRenderStyles[STYLE_Shadow]) drawargs.SetStyle(TriBlendMode::Shadow); + else if (style == LegacyRenderStyles[STYLE_Subtract]) drawargs.SetStyle(TriBlendMode::Subtract); + else if (style == LegacyRenderStyles[STYLE_AddStencil]) drawargs.SetStyle(TriBlendMode::AddStencil); + else if (style == LegacyRenderStyles[STYLE_AddShaded]) drawargs.SetStyle(TriBlendMode::AddShaded); + //else if (style == LegacyRenderStyles[STYLE_Multiply]) drawargs.SetStyle(TriBlendMode::Multiply); + //else if (style == LegacyRenderStyles[STYLE_InverseMultiply]) drawargs.SetStyle(TriBlendMode::InverseMultiply); + //else if (style == LegacyRenderStyles[STYLE_ColorBlend]) drawargs.SetStyle(TriBlendMode::ColorBlend); + //else if (style == LegacyRenderStyles[STYLE_Source]) drawargs.SetStyle(TriBlendMode::Source); + //else if (style == LegacyRenderStyles[STYLE_ColorAdd]) drawargs.SetStyle(TriBlendMode::ColorAdd); + else drawargs.SetStyle(TriBlendMode::Opaque); + } } void PolyTriangleThreadData::SetTexture(void *pixels, int width, int height) From 9f8cd68211744698e5468ea8d4865ffdb11b0fcc Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 27 May 2019 20:03:11 +0200 Subject: [PATCH 11/60] - fix use after delete --- .../polyrenderer/backend/poly_buffers.cpp | 10 ++-- .../polyrenderer/backend/poly_buffers.h | 22 ++++++--- .../polyrenderer/backend/poly_framebuffer.cpp | 4 +- .../polyrenderer/backend/poly_renderstate.cpp | 47 ++++++++++++++++++- .../polyrenderer/backend/poly_renderstate.h | 3 ++ 5 files changed, 71 insertions(+), 15 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_buffers.cpp b/src/rendering/polyrenderer/backend/poly_buffers.cpp index e186b7a71..ad6a36857 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.cpp +++ b/src/rendering/polyrenderer/backend/poly_buffers.cpp @@ -76,14 +76,12 @@ void PolyBuffer::Unlock() void PolyVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) { - for (int j = 0; j < numAttributes; j++) - { - mOffsets[attrs[j].location] = attrs[j].offset; - } - mStride = stride; + VertexFormat = GetPolyFrameBuffer()->GetRenderState()->GetVertexFormat(numBindingPoints, numAttributes, stride, attrs); } -void PolyVertexBuffer::Load(PolyTriangleThreadData *thread, const void *vertices, int index) +///////////////////////////////////////////////////////////////////////////// + +void PolyVertexInputAssembly::Load(PolyTriangleThreadData *thread, const void *vertices, int index) { const uint8_t *vertex = static_cast(vertices) + mStride * index; const float *attrVertex = reinterpret_cast(vertex + mOffsets[VATTR_VERTEX]); diff --git a/src/rendering/polyrenderer/backend/poly_buffers.h b/src/rendering/polyrenderer/backend/poly_buffers.h index b4e183194..1d8c38e82 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.h +++ b/src/rendering/polyrenderer/backend/poly_buffers.h @@ -39,17 +39,27 @@ private: std::vector mData; }; -class PolyVertexBuffer : public IVertexBuffer, public PolyBuffer, public PolyInputAssembly +class PolyVertexInputAssembly : public PolyInputAssembly +{ +public: + size_t mOffsets[VATTR_MAX] = {}; + size_t mStride = 0; + + int NumBindingPoints; + size_t Stride; + std::vector Attrs; + int UseVertexData; + + void Load(PolyTriangleThreadData *thread, const void *vertices, int index) override; +}; + +class PolyVertexBuffer : public IVertexBuffer, public PolyBuffer { public: PolyVertexBuffer() { } void SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) override; - void Load(PolyTriangleThreadData *thread, const void *vertices, int index) override; - -private: - size_t mOffsets[VATTR_MAX] = {}; - size_t mStride = 0; + PolyVertexInputAssembly *VertexFormat = nullptr; }; class PolyIndexBuffer : public IIndexBuffer, public PolyBuffer diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index dce7b8499..d457aea49 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -84,13 +84,13 @@ void PolyFrameBuffer::InitializeState() uniformblockalignment = 1; maxuniformblock = 0x7fffffff; + mRenderState.reset(new PolyRenderState()); + mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight()); mSkyData = new FSkyVertexBuffer; mViewpoints = new GLViewpointBuffer; mLights = new FLightBuffer(); - mRenderState.reset(new PolyRenderState()); - CheckCanvas(); } diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index a21ebf108..cece607d1 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -201,7 +201,7 @@ void PolyRenderState::Apply() if (mVertexBuffer) PolyTriangleDrawer::SetVertexBuffer(fb->GetDrawCommands(), mVertexBuffer->Memory()); if (mIndexBuffer) PolyTriangleDrawer::SetIndexBuffer(fb->GetDrawCommands(), mIndexBuffer->Memory()); - PolyTriangleDrawer::SetInputAssembly(fb->GetDrawCommands(), static_cast(mVertexBuffer)); + PolyTriangleDrawer::SetInputAssembly(fb->GetDrawCommands(), static_cast(mVertexBuffer)->VertexFormat); PolyTriangleDrawer::SetRenderStyle(fb->GetDrawCommands(), mRenderStyle); PolyTriangleDrawer::PushStreamData(fb->GetDrawCommands(), mStreamData, constants); ApplyMatrices(); @@ -287,3 +287,48 @@ void PolyRenderState::Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t len PolyTriangleDrawer::SetViewpointUniforms(GetPolyFrameBuffer()->GetDrawCommands(), mViewpointUniforms); } } + +PolyVertexInputAssembly *PolyRenderState::GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) +{ + for (size_t i = 0; i < mVertexFormats.size(); i++) + { + auto f = mVertexFormats[i].get(); + if (f->Attrs.size() == (size_t)numAttributes && f->NumBindingPoints == numBindingPoints && f->Stride == stride) + { + bool matches = true; + for (int j = 0; j < numAttributes; j++) + { + if (memcmp(&f->Attrs[j], &attrs[j], sizeof(FVertexBufferAttribute)) != 0) + { + matches = false; + break; + } + } + + if (matches) + return f; + } + } + + auto fmt = std::make_unique(); + fmt->NumBindingPoints = numBindingPoints; + fmt->Stride = stride; + fmt->UseVertexData = 0; + for (int j = 0; j < numAttributes; j++) + { + if (attrs[j].location == VATTR_COLOR) + fmt->UseVertexData |= 1; + else if (attrs[j].location == VATTR_NORMAL) + fmt->UseVertexData |= 2; + fmt->Attrs.push_back(attrs[j]); + } + + for (int j = 0; j < numAttributes; j++) + { + fmt->mOffsets[attrs[j].location] = attrs[j].offset; + } + fmt->mStride = stride; + + mVertexFormats.push_back(std::move(fmt)); + return mVertexFormats.back().get(); +} diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.h b/src/rendering/polyrenderer/backend/poly_renderstate.h index 6052e910e..b0fee75ce 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.h +++ b/src/rendering/polyrenderer/backend/poly_renderstate.h @@ -42,6 +42,8 @@ public: void Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t length); + PolyVertexInputAssembly *GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs); + private: void Apply(); void ApplyMaterial(); @@ -57,6 +59,7 @@ private: bool mFirstMatrixApply = true; HWViewpointUniforms *mViewpointUniforms = nullptr; + std::vector> mVertexFormats; bool mDepthClamp = true; }; From c2535519e881d72d88c4daa51c35436e5769a87e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 27 May 2019 20:20:20 +0200 Subject: [PATCH 12/60] - fix blend mode for the fireballs --- src/rendering/polyrenderer/drawers/poly_triangle.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index d712c3b96..6b542f962 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -401,6 +401,10 @@ void PolyTriangleThreadData::SetRenderStyle(FRenderStyle style) { drawargs.SetStyle(TriBlendMode::Normal); } + else if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_SrcCol && style.DestAlpha == STYLEALPHA_One) + { + drawargs.SetStyle(TriBlendMode::SrcColor); + } else { if (style == LegacyRenderStyles[STYLE_Normal]) drawargs.SetStyle(TriBlendMode::Normal); From b6e00cb208cc3961afea7998908fda91e8bd7179 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 27 May 2019 21:23:58 +0200 Subject: [PATCH 13/60] - fix use after delete of some textures --- .../polyrenderer/backend/poly_framebuffer.cpp | 1 + .../polyrenderer/backend/poly_framebuffer.h | 1 + .../polyrenderer/backend/poly_hwtexture.cpp | 22 ++++++++++++++----- .../polyrenderer/backend/poly_hwtexture.h | 1 + .../polyrenderer/backend/poly_renderstate.cpp | 21 +++++++++--------- .../polyrenderer/backend/poly_renderstate.h | 1 + 6 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index d457aea49..b6397b859 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -140,6 +140,7 @@ void PolyFrameBuffer::Update() DrawerThreads::WaitForWorkers(); mFrameMemory.Clear(); FrameDeleteList.Buffers.clear(); + FrameDeleteList.Images.clear(); if (mCanvas) { diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.h b/src/rendering/polyrenderer/backend/poly_framebuffer.h index e56318145..e6f6e2afd 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.h +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.h @@ -62,6 +62,7 @@ public: struct DeleteList { std::vector> Buffers; + std::vector> Images; } FrameDeleteList; private: diff --git a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp index 9302738be..ff3ee95fa 100644 --- a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp +++ b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp @@ -34,11 +34,15 @@ void PolyHardwareTexture::ResetAll() void PolyHardwareTexture::Reset() { + if (auto fb = GetPolyFrameBuffer()) + { + auto &deleteList = fb->FrameDeleteList; + if (mCanvas) deleteList.Images.push_back(std::move(mCanvas)); + } } void PolyHardwareTexture::Precache(FMaterial *mat, int translation, int flags) { -#if 0 int numLayers = mat->GetLayers(); GetImage(mat->tex, translation, flags); for (int i = 1; i < numLayers; i++) @@ -47,15 +51,16 @@ void PolyHardwareTexture::Precache(FMaterial *mat, int translation, int flags) auto systex = static_cast(mat->GetLayer(i, 0, &layer)); systex->GetImage(layer, 0, mat->isExpanded() ? CTF_Expand : 0); } -#endif } DCanvas *PolyHardwareTexture::GetImage(const FMaterialState &state) { + FTexture *tex = state.mMaterial->tex; + if (tex->isHardwareCanvas()) static_cast(tex)->NeedUpdate(); + if (!mCanvas) { FMaterial *mat = state.mMaterial; - FTexture *tex = state.mMaterial->tex; int clampmode = state.mClampMode; int translation = state.mTranslation; @@ -66,14 +71,19 @@ DCanvas *PolyHardwareTexture::GetImage(const FMaterialState &state) // Textures that are already scaled in the texture lump will not get replaced by hires textures. int flags = state.mMaterial->isExpanded() ? CTF_Expand : (gl_texture_usehires && !tex->isScaled() && clampmode <= CLAMP_XY) ? CTF_CheckHires : 0; - if (tex->isHardwareCanvas()) static_cast(tex)->NeedUpdate(); - - CreateImage(tex, translation, flags); + return GetImage(tex, translation, flags); } return mCanvas.get(); } +DCanvas *PolyHardwareTexture::GetImage(FTexture *tex, int translation, int flags) +{ + if (!mCanvas) + CreateImage(tex, translation, flags); + return mCanvas.get(); +} + void PolyHardwareTexture::AllocateBuffer(int w, int h, int texelsize) { if (!mCanvas || mCanvas->GetWidth() != w || mCanvas->GetHeight() != h) diff --git a/src/rendering/polyrenderer/backend/poly_hwtexture.h b/src/rendering/polyrenderer/backend/poly_hwtexture.h index 84d1147bf..805fd37da 100644 --- a/src/rendering/polyrenderer/backend/poly_hwtexture.h +++ b/src/rendering/polyrenderer/backend/poly_hwtexture.h @@ -26,6 +26,7 @@ public: void Precache(FMaterial *mat, int translation, int flags); DCanvas *GetImage(const FMaterialState &state); + DCanvas *GetImage(FTexture *tex, int translation, int flags); // Software renderer stuff void AllocateBuffer(int w, int h, int texelsize) override; diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index cece607d1..5e770c1db 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -166,8 +166,6 @@ void PolyRenderState::Apply() drawcalls.Clock(); auto fb = GetPolyFrameBuffer(); - PolyPushConstants constants; - int fogset = 0; if (mFogEnabled) { @@ -185,12 +183,16 @@ void PolyRenderState::Apply() } } - int tempTM = TM_NORMAL; - if (mMaterial.mMaterial && mMaterial.mMaterial->tex && mMaterial.mMaterial->tex->isHardwareCanvas()) - tempTM = TM_OPAQUE; + ApplyMaterial(); + if (mVertexBuffer) PolyTriangleDrawer::SetVertexBuffer(fb->GetDrawCommands(), mVertexBuffer->Memory()); + if (mIndexBuffer) PolyTriangleDrawer::SetIndexBuffer(fb->GetDrawCommands(), mIndexBuffer->Memory()); + PolyTriangleDrawer::SetInputAssembly(fb->GetDrawCommands(), static_cast(mVertexBuffer)->VertexFormat); + PolyTriangleDrawer::SetRenderStyle(fb->GetDrawCommands(), mRenderStyle); + + PolyPushConstants constants; constants.uFogEnabled = fogset; - constants.uTextureMode = mTextureMode == TM_NORMAL && tempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode; + constants.uTextureMode = mTextureMode == TM_NORMAL && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode; constants.uLightDist = mLightParms[0]; constants.uLightFactor = mLightParms[1]; constants.uFogDensity = mLightParms[2]; @@ -199,13 +201,8 @@ void PolyRenderState::Apply() constants.uClipSplit = { mClipSplit[0], mClipSplit[1] }; constants.uLightIndex = mLightIndex; - if (mVertexBuffer) PolyTriangleDrawer::SetVertexBuffer(fb->GetDrawCommands(), mVertexBuffer->Memory()); - if (mIndexBuffer) PolyTriangleDrawer::SetIndexBuffer(fb->GetDrawCommands(), mIndexBuffer->Memory()); - PolyTriangleDrawer::SetInputAssembly(fb->GetDrawCommands(), static_cast(mVertexBuffer)->VertexFormat); - PolyTriangleDrawer::SetRenderStyle(fb->GetDrawCommands(), mRenderStyle); PolyTriangleDrawer::PushStreamData(fb->GetDrawCommands(), mStreamData, constants); ApplyMatrices(); - ApplyMaterial(); if (mBias.mChanged) { @@ -220,6 +217,8 @@ void PolyRenderState::ApplyMaterial() { if (mMaterial.mChanged && mMaterial.mMaterial) { + mTempTM = mMaterial.mMaterial->tex->isHardwareCanvas() ? TM_OPAQUE : TM_NORMAL; + auto base = static_cast(mMaterial.mMaterial->GetLayer(0, mMaterial.mTranslation)); if (base) { diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.h b/src/rendering/polyrenderer/backend/poly_renderstate.h index b0fee75ce..8634d64e5 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.h +++ b/src/rendering/polyrenderer/backend/poly_renderstate.h @@ -62,4 +62,5 @@ private: std::vector> mVertexFormats; bool mDepthClamp = true; + int mTempTM = TM_NORMAL; }; From bd591c75fbbcf0819ac4bf1f446e7fac07a280b5 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 28 May 2019 06:45:21 +0200 Subject: [PATCH 14/60] - implement depth bias --- .../polyrenderer/backend/poly_renderstate.cpp | 2 +- .../polyrenderer/drawers/poly_triangle.cpp | 8 ++ .../polyrenderer/drawers/poly_triangle.h | 5 +- .../polyrenderer/drawers/screen_triangle.cpp | 103 +++++++++--------- src/rendering/swrenderer/drawers/r_draw.cpp | 8 +- 5 files changed, 69 insertions(+), 57 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 5e770c1db..b75236c81 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -108,7 +108,7 @@ void PolyRenderState::Clear(int targets) //if (targets & CT_Color) // PolyTriangleDrawer::ClearColor(GetPolyFrameBuffer()->GetDrawCommands()); if (targets & CT_Depth) - PolyTriangleDrawer::ClearDepth(GetPolyFrameBuffer()->GetDrawCommands(), 0.0f); + PolyTriangleDrawer::ClearDepth(GetPolyFrameBuffer()->GetDrawCommands(), 65535.0f); if (targets & CT_Stencil) PolyTriangleDrawer::ClearStencil(GetPolyFrameBuffer()->GetDrawCommands(), 0); } diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 6b542f962..7a279ebbb 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -338,10 +338,18 @@ void PolyTriangleThreadData::SetDepthFunc(int func) void PolyTriangleThreadData::SetDepthRange(float min, float max) { + // The only two variants used by hwrenderer layer + if (min == 0.0f && max == 1.0f) + { + } + else if (min == 1.0f && max == 1.0f) + { + } } void PolyTriangleThreadData::SetDepthBias(float depthBiasConstantFactor, float depthBiasSlopeFactor) { + depthbias = (float)(depthBiasConstantFactor / 65536.0); } void PolyTriangleThreadData::SetColorMask(bool r, bool g, bool b, bool a) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index a14216cae..81a4bf7e0 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -121,7 +121,7 @@ public: void SetTransform(const Mat4f *objectToClip, const Mat4f *objectToWorld); void SetCullCCW(bool value) { ccw = value; } void SetTwoSided(bool value) { twosided = value; } - void SetWeaponScene(bool value) { weaponScene = value; } + void SetWeaponScene(bool value) { depthbias = value ? -1.0f : 0.0f; } void SetModelVertexShader(int frame1, int frame2, float interpolationFactor) { modelFrame1 = frame1; modelFrame2 = frame2; swVertexShader.modelInterpolationFactor = interpolationFactor; } void SetInputAssembly(PolyInputAssembly *input) { inputAssembly = input; } @@ -187,6 +187,7 @@ public: int32_t texelV[MAXWIDTH]; uint16_t lightarray[MAXWIDTH]; uint32_t dynlights[MAXWIDTH]; + float depthvalues[MAXWIDTH]; static PolyTriangleThreadData *Get(DrawerThread *thread); @@ -195,7 +196,7 @@ public: int dest_height = 0; bool dest_bgra = false; uint8_t *dest = nullptr; - bool weaponScene = false; + float depthbias = 0.0f; int viewport_y = 0; diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 5f37e3b87..af6b3ec22 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -151,13 +151,37 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat TriangleDrawers[opt](args, thread, edges, topY, bottomY); } +static void FillDepthValues(float *depthvalues, float posXW, float stepXW, int count, float depthbias) +{ +#ifndef NO_SSE + __m128 mstepXW = _mm_set1_ps(stepXW * 4.0f); + __m128 mfirstStepXW = _mm_setr_ps(0.0f, stepXW, stepXW + stepXW, stepXW + stepXW + stepXW); + __m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW); + __m128 mdepthbias = _mm_set1_ps(depthbias); + while (count > 0) + { + _mm_storeu_ps(depthvalues, _mm_add_ps(_mm_rcp_ps(mposXW), mdepthbias)); + mposXW = _mm_add_ps(mposXW, mstepXW); + depthvalues += 4; + count -= 4; + } +#else + while (count > 0) + { + *(depthvalues++) = 1.0f / posXW + depthbias; + posXW += stepXW; + count--; + } +#endif +} + template void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread, int16_t *edges, int topY, int bottomY) { using namespace TriScreenDrawerModes; void(*drawfunc)(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); - float stepXW, v1X, v1Y, v1W, posXW; + float stepXW, v1X, v1Y, v1W; uint8_t stencilTestValue, stencilWriteValue; float *zbuffer; float *zbufferLine; @@ -194,12 +218,14 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa if (OptT::Flags & SWTRI_WriteStencil) stencilWriteValue = args->uniforms->StencilWriteValue(); - float weaponWOffset; + float depthbias; if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_WriteDepth)) { - weaponWOffset = thread->weaponScene ? 1.0f : 0.0f; + depthbias = thread->depthbias; } + float *depthvalues = thread->depthvalues; + int num_cores = thread->num_cores; for (int y = topY; y < bottomY; y += num_cores) { @@ -215,16 +241,11 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa float startX = x + (0.5f - v1X); float startY = y + (0.5f - v1Y); - posXW = v1W + stepXW * startX + args->gradientY.W * startY + weaponWOffset; + float posXW = v1W + stepXW * startX + args->gradientY.W * startY; + FillDepthValues(depthvalues + x, posXW, stepXW, xend - x, depthbias); } #ifndef NO_SSE - __m128 mstepXW, mfirstStepXW; - if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_WriteDepth)) - { - mstepXW = _mm_set1_ps(stepXW * 4.0f); - mfirstStepXW = _mm_setr_ps(0.0f, stepXW, stepXW + stepXW, stepXW + stepXW + stepXW); - } while (x < xend) { int xstart = x; @@ -232,9 +253,9 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) { int xendsse = x + ((xend - x) / 4); - __m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW); + __m128 mposXW; while (x < xendsse && - _mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 15 && + _mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 15 && stencilLine[x] == stencilTestValue && stencilLine[x + 1] == stencilTestValue && stencilLine[x + 2] == stencilTestValue && @@ -242,37 +263,31 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa { if (OptT::Flags & SWTRI_WriteDepth) _mm_storeu_ps(zbufferLine + x, mposXW); - mposXW = _mm_add_ps(mposXW, mstepXW); x += 4; } - posXW = _mm_cvtss_f32(mposXW); - while (zbufferLine[x] <= posXW && stencilLine[x] == stencilTestValue && x < xend) + while (zbufferLine[x] >= depthvalues[x] && stencilLine[x] == stencilTestValue && x < xend) { if (OptT::Flags & SWTRI_WriteDepth) - zbufferLine[x] = posXW; - posXW += stepXW; + zbufferLine[x] = depthvalues[x]; x++; } } else if (OptT::Flags & SWTRI_DepthTest) { int xendsse = x + ((xend - x) / 4); - __m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW); - while (x < xendsse && _mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 15) + __m128 mposXW; + while (x < xendsse && _mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 15) { if (OptT::Flags & SWTRI_WriteDepth) _mm_storeu_ps(zbufferLine + x, mposXW); - mposXW = _mm_add_ps(mposXW, mstepXW); x += 4; } - posXW = _mm_cvtss_f32(mposXW); - while (zbufferLine[x] <= posXW && x < xend) + while (zbufferLine[x] >= depthvalues[x] && x < xend) { if (OptT::Flags & SWTRI_WriteDepth) - zbufferLine[x] = posXW; - posXW += stepXW; + zbufferLine[x] = depthvalues[x]; x++; } } @@ -315,8 +330,7 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa { for (int i = xstart; i < x; i++) { - zbufferLine[i] = posXW; - posXW += stepXW; + zbufferLine[i] = depthvalues[i]; } } } @@ -324,39 +338,33 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) { int xendsse = x + ((xend - x) / 4); - __m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW); + __m128 mposXW; while (x < xendsse && - (_mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 0 || + (_mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 0 || stencilLine[x] != stencilTestValue || stencilLine[x + 1] != stencilTestValue || stencilLine[x + 2] != stencilTestValue || stencilLine[x + 3] != stencilTestValue)) { - mposXW = _mm_add_ps(mposXW, mstepXW); x += 4; } - posXW = _mm_cvtss_f32(mposXW); - while ((zbufferLine[x] > posXW || stencilLine[x] != stencilTestValue) && x < xend) + while ((zbufferLine[x] < depthvalues[x] || stencilLine[x] != stencilTestValue) && x < xend) { - posXW += stepXW; x++; } } else if (OptT::Flags & SWTRI_DepthTest) { int xendsse = x + ((xend - x) / 4); - __m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW); - while (x < xendsse && _mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 0) + __m128 mposXW; + while (x < xendsse && _mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 0) { - mposXW = _mm_add_ps(mposXW, mstepXW); x += 4; } - posXW = _mm_cvtss_f32(mposXW); - while (zbufferLine[x] > posXW && x < xend) + while (zbufferLine[x] < depthvalues[x] && x < xend) { - posXW += stepXW; x++; } } @@ -381,21 +389,19 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) { - while (zbufferLine[x] <= posXW && stencilLine[x] == stencilTestValue && x < xend) + while (zbufferLine[x] >= depthvalues[x] && stencilLine[x] == stencilTestValue && x < xend) { if (OptT::Flags & SWTRI_WriteDepth) - zbufferLine[x] = posXW; - posXW += stepXW; + zbufferLine[x] = depthvalues[x]; x++; } } else if (OptT::Flags & SWTRI_DepthTest) { - while (zbufferLine[x] <= posXW && x < xend) + while (zbufferLine[x] >= depthvalues[x] && x < xend) { if (OptT::Flags & SWTRI_WriteDepth) - zbufferLine[x] = posXW; - posXW += stepXW; + zbufferLine[x] = depthvalues[x]; x++; } } @@ -424,25 +430,22 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa { for (int i = xstart; i < x; i++) { - zbufferLine[i] = posXW; - posXW += stepXW; + zbufferLine[i] = depthvalues[i]; } } } if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) { - while ((zbufferLine[x] > posXW || stencilLine[x] != stencilTestValue) && x < xend) + while ((zbufferLine[x] < depthvalues[x] || stencilLine[x] != stencilTestValue) && x < xend) { - posXW += stepXW; x++; } } else if (OptT::Flags & SWTRI_DepthTest) { - while (zbufferLine[x] > posXW && x < xend) + while (zbufferLine[x] < depthvalues[x] && x < xend) { - posXW += stepXW; x++; } } diff --git a/src/rendering/swrenderer/drawers/r_draw.cpp b/src/rendering/swrenderer/drawers/r_draw.cpp index 42d9d6c07..20425a7ec 100644 --- a/src/rendering/swrenderer/drawers/r_draw.cpp +++ b/src/rendering/swrenderer/drawers/r_draw.cpp @@ -220,7 +220,7 @@ namespace swrenderer class DepthColumnCommand : public DrawerCommand { public: - DepthColumnCommand(const WallDrawerArgs &args, float idepth) : idepth(idepth) + DepthColumnCommand(const WallDrawerArgs &args, float idepth) : idepth(1.0f / idepth) { auto rendertarget = args.Viewport()->RenderTarget; if (rendertarget->IsBgra()) @@ -244,7 +244,7 @@ namespace swrenderer count = args.Count(); } - DepthColumnCommand(const SkyDrawerArgs &args, float idepth) : idepth(idepth) + DepthColumnCommand(const SkyDrawerArgs &args, float idepth) : idepth(1.0f / idepth) { auto rendertarget = args.Viewport()->RenderTarget; if (rendertarget->IsBgra()) @@ -319,7 +319,7 @@ namespace swrenderer if (idepth1 == idepth2) { - float depth = idepth1; + float depth = 1.0f / idepth1; #ifdef DEPTH_DEBUG uint32_t gray = clamp((int32_t)(1.0f / depth / 4.0f), 0, 255); uint32_t color = MAKEARGB(255, gray, gray, gray); @@ -344,7 +344,7 @@ namespace swrenderer dest[x] = color; #endif - values[x] = depth; + values[x] = 1.0f / depth; depth += step; } } From 555beb58f01cae79759efa78c1a1166016512e4f Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 28 May 2019 08:13:19 +0200 Subject: [PATCH 15/60] - tell softpoly backend which hwrenderer shader is active and use that to decide which drawer to use --- .../polyrenderer/backend/poly_framebuffer.cpp | 7 + .../polyrenderer/backend/poly_renderstate.cpp | 10 ++ .../polyrenderer/drawers/poly_triangle.cpp | 138 ++++++++++++------ .../polyrenderer/drawers/poly_triangle.h | 19 +++ .../polyrenderer/drawers/screen_triangle.cpp | 8 +- 5 files changed, 135 insertions(+), 47 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index b6397b859..bdbc1ef80 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -541,6 +541,13 @@ void PolyFrameBuffer::BeginFrame() { SetViewportRects(nullptr); CheckCanvas(); + + swrenderer::R_InitFuzzTable(GetCanvas()->GetPitch()); + static int next_random = 0; + swrenderer::fuzzpos = (swrenderer::fuzzpos + swrenderer::fuzz_random_x_offset[next_random] * FUZZTABLE / 100) % FUZZTABLE; + next_random++; + if (next_random == FUZZ_RANDOM_X_SIZE) + next_random = 0; } void PolyFrameBuffer::Draw2D() diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index b75236c81..7423cc973 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -190,6 +190,16 @@ void PolyRenderState::Apply() PolyTriangleDrawer::SetInputAssembly(fb->GetDrawCommands(), static_cast(mVertexBuffer)->VertexFormat); PolyTriangleDrawer::SetRenderStyle(fb->GetDrawCommands(), mRenderStyle); + if (mSpecialEffect > EFF_NONE) + { + PolyTriangleDrawer::SetShader(fb->GetDrawCommands(), mSpecialEffect, 0, false); + } + else + { + int effectState = mMaterial.mOverrideShader >= 0 ? mMaterial.mOverrideShader : (mMaterial.mMaterial ? mMaterial.mMaterial->GetShaderIndex() : 0); + PolyTriangleDrawer::SetShader(fb->GetDrawCommands(), EFF_NONE, mTextureEnabled ? effectState : SHADER_NoTexture, mAlphaThreshold >= 0.f); + } + PolyPushConstants constants; constants.uFogEnabled = fogset; constants.uTextureMode = mTextureMode == TM_NORMAL && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 7a279ebbb..097c7b2c5 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -189,6 +189,11 @@ void PolyTriangleDrawer::SetTexture(const DrawerCommandQueuePtr &queue, void *pi queue->Push(pixels, width, height); } +void PolyTriangleDrawer::SetShader(const DrawerCommandQueuePtr &queue, int specialEffect, int effectState, bool alphaTest) +{ + queue->Push(specialEffect, effectState, alphaTest); +} + void PolyTriangleDrawer::PushStreamData(const DrawerCommandQueuePtr &queue, const StreamData &data, const PolyPushConstants &constants) { queue->Push(data, constants); @@ -304,11 +309,80 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu cm.Clear(); drawargs.SetLight(GetColorTable(cm), (int)(constants.uLightLevel * 255.0f), mainVertexShader.Viewpoint->mGlobVis * 32.0f, false); - drawargs.SetColor(MAKEARGB( - static_cast(mainVertexShader.Data.uVertexColor.W * 255.0f + 0.5f), - static_cast(mainVertexShader.Data.uVertexColor.X * 255.0f + 0.5f), - static_cast(mainVertexShader.Data.uVertexColor.Y * 255.0f + 0.5f), - static_cast(mainVertexShader.Data.uVertexColor.Z * 255.0f + 0.5f)), 0); + if (SpecialEffect != EFF_NONE) + { + // To do: need new drawers for these + switch (SpecialEffect) + { + default: break; + case EFF_FOGBOUNDARY: drawargs.SetStyle(TriBlendMode::FogBoundary); break; + case EFF_SPHEREMAP: drawargs.SetStyle(TriBlendMode::Fill); break; + case EFF_BURN: drawargs.SetStyle(TriBlendMode::Fill); break; + case EFF_STENCIL: drawargs.SetStyle(TriBlendMode::Fill); break; + } + } + else + { + switch (EffectState) + { + default: + break; + case SHADER_Paletted: + break; + case SHADER_NoTexture: + drawargs.SetStyle(TriBlendMode::Fill); + drawargs.SetColor(MAKEARGB( + static_cast(mainVertexShader.Data.uVertexColor.W * 255.0f + 0.5f), + static_cast(mainVertexShader.Data.uVertexColor.X * 255.0f + 0.5f), + static_cast(mainVertexShader.Data.uVertexColor.Y * 255.0f + 0.5f), + static_cast(mainVertexShader.Data.uVertexColor.Z * 255.0f + 0.5f)), 0); + return; + case SHADER_BasicFuzz: + case SHADER_SmoothFuzz: + case SHADER_SwirlyFuzz: + case SHADER_TranslucentFuzz: + case SHADER_JaggedFuzz: + case SHADER_NoiseFuzz: + case SHADER_SmoothNoiseFuzz: + case SHADER_SoftwareFuzz: + drawargs.SetStyle(TriBlendMode::Fuzzy); + drawargs.SetColor(0xff000000, 0); + return; + } + + auto style = RenderStyle; + if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero) + { + drawargs.SetStyle(AlphaTest ? TriBlendMode::Normal : TriBlendMode::Opaque); + } + else if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_Src && style.DestAlpha == STYLEALPHA_InvSrc) + { + drawargs.SetStyle(TriBlendMode::Normal); + } + else if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_SrcCol && style.DestAlpha == STYLEALPHA_One) + { + drawargs.SetStyle(TriBlendMode::SrcColor); + } + else + { + if (style == LegacyRenderStyles[STYLE_Normal]) drawargs.SetStyle(TriBlendMode::Normal); + else if (style == LegacyRenderStyles[STYLE_Stencil]) drawargs.SetStyle(TriBlendMode::Stencil); + else if (style == LegacyRenderStyles[STYLE_Translucent]) drawargs.SetStyle(TriBlendMode::Translucent); + else if (style == LegacyRenderStyles[STYLE_Add]) drawargs.SetStyle(TriBlendMode::Add); + //else if (style == LegacyRenderStyles[STYLE_Shaded]) drawargs.SetStyle(TriBlendMode::Shaded); + else if (style == LegacyRenderStyles[STYLE_TranslucentStencil]) drawargs.SetStyle(TriBlendMode::TranslucentStencil); + else if (style == LegacyRenderStyles[STYLE_Shadow]) drawargs.SetStyle(TriBlendMode::Shadow); + else if (style == LegacyRenderStyles[STYLE_Subtract]) drawargs.SetStyle(TriBlendMode::Subtract); + else if (style == LegacyRenderStyles[STYLE_AddStencil]) drawargs.SetStyle(TriBlendMode::AddStencil); + else if (style == LegacyRenderStyles[STYLE_AddShaded]) drawargs.SetStyle(TriBlendMode::AddShaded); + //else if (style == LegacyRenderStyles[STYLE_Multiply]) drawargs.SetStyle(TriBlendMode::Multiply); + //else if (style == LegacyRenderStyles[STYLE_InverseMultiply]) drawargs.SetStyle(TriBlendMode::InverseMultiply); + //else if (style == LegacyRenderStyles[STYLE_ColorBlend]) drawargs.SetStyle(TriBlendMode::ColorBlend); + else if (style == LegacyRenderStyles[STYLE_Source]) drawargs.SetStyle(TriBlendMode::Opaque); + //else if (style == LegacyRenderStyles[STYLE_ColorAdd]) drawargs.SetStyle(TriBlendMode::ColorAdd); + else drawargs.SetStyle(TriBlendMode::Opaque); + } + } } void PolyTriangleThreadData::PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) @@ -334,6 +408,14 @@ void PolyTriangleThreadData::SetDepthMask(bool on) void PolyTriangleThreadData::SetDepthFunc(int func) { + if (func == DF_LEqual || func == DF_Less) + { + drawargs.SetDepthTest(true); + } + else if (func == DF_Always) + { + drawargs.SetDepthTest(false); + } } void PolyTriangleThreadData::SetDepthRange(float min, float max) @@ -397,44 +479,14 @@ void PolyTriangleThreadData::EnableDepthTest(bool on) void PolyTriangleThreadData::SetRenderStyle(FRenderStyle style) { - if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero && style.Flags == 0) - { - drawargs.SetStyle(TriBlendMode::Opaque); - } - else if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_Src && style.DestAlpha == STYLEALPHA_InvSrc) - { - drawargs.SetStyle(TriBlendMode::Normal); - } - else if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero) - { - drawargs.SetStyle(TriBlendMode::Normal); - } - else if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_SrcCol && style.DestAlpha == STYLEALPHA_One) - { - drawargs.SetStyle(TriBlendMode::SrcColor); - } - else - { - if (style == LegacyRenderStyles[STYLE_Normal]) drawargs.SetStyle(TriBlendMode::Normal); - else if (style == LegacyRenderStyles[STYLE_Fuzzy]) drawargs.SetStyle(TriBlendMode::Fuzzy); - //else if (style == LegacyRenderStyles[STYLE_SoulTrans]) drawargs.SetStyle(TriBlendMode::SoulTrans); - //else if (style == LegacyRenderStyles[STYLE_OptFuzzy]) drawargs.SetStyle(TriBlendMode::OptFuzzy); - else if (style == LegacyRenderStyles[STYLE_Stencil]) drawargs.SetStyle(TriBlendMode::Stencil); - else if (style == LegacyRenderStyles[STYLE_Translucent]) drawargs.SetStyle(TriBlendMode::Translucent); - else if (style == LegacyRenderStyles[STYLE_Add]) drawargs.SetStyle(TriBlendMode::Add); - //else if (style == LegacyRenderStyles[STYLE_Shaded]) drawargs.SetStyle(TriBlendMode::Shaded); - else if (style == LegacyRenderStyles[STYLE_TranslucentStencil]) drawargs.SetStyle(TriBlendMode::TranslucentStencil); - else if (style == LegacyRenderStyles[STYLE_Shadow]) drawargs.SetStyle(TriBlendMode::Shadow); - else if (style == LegacyRenderStyles[STYLE_Subtract]) drawargs.SetStyle(TriBlendMode::Subtract); - else if (style == LegacyRenderStyles[STYLE_AddStencil]) drawargs.SetStyle(TriBlendMode::AddStencil); - else if (style == LegacyRenderStyles[STYLE_AddShaded]) drawargs.SetStyle(TriBlendMode::AddShaded); - //else if (style == LegacyRenderStyles[STYLE_Multiply]) drawargs.SetStyle(TriBlendMode::Multiply); - //else if (style == LegacyRenderStyles[STYLE_InverseMultiply]) drawargs.SetStyle(TriBlendMode::InverseMultiply); - //else if (style == LegacyRenderStyles[STYLE_ColorBlend]) drawargs.SetStyle(TriBlendMode::ColorBlend); - //else if (style == LegacyRenderStyles[STYLE_Source]) drawargs.SetStyle(TriBlendMode::Source); - //else if (style == LegacyRenderStyles[STYLE_ColorAdd]) drawargs.SetStyle(TriBlendMode::ColorAdd); - else drawargs.SetStyle(TriBlendMode::Opaque); - } + RenderStyle = style; +} + +void PolyTriangleThreadData::SetShader(int specialEffect, int effectState, bool alphaTest) +{ + SpecialEffect = specialEffect; + EffectState = effectState; + AlphaTest = alphaTest; } void PolyTriangleThreadData::SetTexture(void *pixels, int width, int height) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 81a4bf7e0..1dc82568f 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -61,6 +61,7 @@ public: static void EnableDepthTest(const DrawerCommandQueuePtr &queue, bool on); static void SetRenderStyle(const DrawerCommandQueuePtr &queue, FRenderStyle style); static void SetTexture(const DrawerCommandQueuePtr &queue, void *pixels, int width, int height); + static void SetShader(const DrawerCommandQueuePtr &queue, int specialEffect, int effectState, bool alphaTest); static void PushStreamData(const DrawerCommandQueuePtr &queue, const StreamData &data, const PolyPushConstants &constants); static void PushMatrices(const DrawerCommandQueuePtr &queue, const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); static void Draw(const DrawerCommandQueuePtr &queue, int index, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); @@ -142,6 +143,7 @@ public: void EnableDepthTest(bool on); void SetRenderStyle(FRenderStyle style); void SetTexture(void *pixels, int width, int height); + void SetShader(int specialEffect, int effectState, bool alphaTest); void UpdateClip(); @@ -208,6 +210,11 @@ public: int bottom = 0; } clip, scissor; + FRenderStyle RenderStyle; + int SpecialEffect = EFF_NONE; + int EffectState = 0; + bool AlphaTest = false; + PolyDrawArgs drawargs; const void *vertices = nullptr; @@ -396,6 +403,18 @@ private: int height; }; +class PolySetShaderCommand : public PolyDrawerCommand +{ +public: + PolySetShaderCommand(int specialEffect, int effectState, bool alphaTest) : specialEffect(specialEffect), effectState(effectState), alphaTest(alphaTest) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetShader(specialEffect, effectState, alphaTest); } + +private: + int specialEffect; + int effectState; + bool alphaTest; +}; + class PolySetVertexBufferCommand : public PolyDrawerCommand { public: diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index af6b3ec22..1bc6a708c 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -887,7 +887,7 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyT if (ModeT::BlendOp == STYLEOP_Fuzz) { - fuzzscale = (200 << FRACBITS) / viewheight; + fuzzscale = (200 << FRACBITS) / thread->dest_height; _fuzzpos = swrenderer::fuzzpos; } @@ -1314,7 +1314,7 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTr if (ModeT::BlendOp == STYLEOP_Fuzz) { - fuzzscale = (200 << FRACBITS) / viewheight; + fuzzscale = (200 << FRACBITS) / thread->dest_height; _fuzzpos = swrenderer::fuzzpos; } @@ -1626,7 +1626,7 @@ void DrawRect8(const void *destOrg, int destWidth, int destHeight, int destPitch int _fuzzpos; if (ModeT::BlendOp == STYLEOP_Fuzz) { - fuzzscale = (200 << FRACBITS) / viewheight; + fuzzscale = (200 << FRACBITS) / thread->dest_height; _fuzzpos = swrenderer::fuzzpos; } @@ -1877,7 +1877,7 @@ void DrawRectOpt32(const void *destOrg, int destWidth, int destHeight, int destP int _fuzzpos; if (ModeT::BlendOp == STYLEOP_Fuzz) { - fuzzscale = (200 << FRACBITS) / viewheight; + fuzzscale = (200 << FRACBITS) / thread->dest_height; _fuzzpos = swrenderer::fuzzpos; } From eff38393afc158c7d81959e54353ef2a60ff7e96 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 29 May 2019 01:14:42 +0200 Subject: [PATCH 16/60] - fix stencil writing color --- src/rendering/polyrenderer/drawers/poly_triangle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 097c7b2c5..81efcd737 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -436,7 +436,7 @@ void PolyTriangleThreadData::SetDepthBias(float depthBiasConstantFactor, float d void PolyTriangleThreadData::SetColorMask(bool r, bool g, bool b, bool a) { - drawargs.SetWriteColor(r || g || b || a); + drawargs.SetWriteColor(r); } void PolyTriangleThreadData::SetStencil(int stencilRef, int op) From be5ecce59894d5f14a735fa24287c9e95617db4c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 29 May 2019 02:22:45 +0200 Subject: [PATCH 17/60] - fix fill color and translucency --- .../polyrenderer/backend/poly_buffers.cpp | 20 +++++++++++++++++++ .../polyrenderer/drawers/poly_triangle.cpp | 12 ++++------- .../polyrenderer/drawers/poly_vertex_shader.h | 6 ++++-- .../polyrenderer/drawers/screen_triangle.cpp | 2 ++ .../polyrenderer/drawers/screen_triangle.h | 2 ++ 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_buffers.cpp b/src/rendering/polyrenderer/backend/poly_buffers.cpp index ad6a36857..526c5279c 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.cpp +++ b/src/rendering/polyrenderer/backend/poly_buffers.cpp @@ -86,9 +86,29 @@ void PolyVertexInputAssembly::Load(PolyTriangleThreadData *thread, const void *v const uint8_t *vertex = static_cast(vertices) + mStride * index; const float *attrVertex = reinterpret_cast(vertex + mOffsets[VATTR_VERTEX]); const float *attrTexcoord = reinterpret_cast(vertex + mOffsets[VATTR_TEXCOORD]); + const uint8_t *attrColor = reinterpret_cast(vertex + mOffsets[VATTR_COLOR]); thread->mainVertexShader.aPosition = { attrVertex[0], attrVertex[1], attrVertex[2], 1.0f }; thread->mainVertexShader.aTexCoord = { attrTexcoord[0], attrTexcoord[1] }; + + if (UseVertexData) + { + uint32_t r = attrColor[0]; + uint32_t g = attrColor[1]; + uint32_t b = attrColor[2]; + uint32_t a = attrColor[3]; + thread->mainVertexShader.aColor = MAKEARGB(a, r, g, b); + } + else + { + const auto &c = thread->mainVertexShader.Data.uVertexColor; + thread->mainVertexShader.aColor = MAKEARGB( + static_cast(c.W * 255.0f + 0.5f), + static_cast(c.X * 255.0f + 0.5f), + static_cast(c.Y * 255.0f + 0.5f), + static_cast(c.Z * 255.0f + 0.5f) + ); + } } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 81efcd737..01f345160 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -330,12 +330,7 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu case SHADER_Paletted: break; case SHADER_NoTexture: - drawargs.SetStyle(TriBlendMode::Fill); - drawargs.SetColor(MAKEARGB( - static_cast(mainVertexShader.Data.uVertexColor.W * 255.0f + 0.5f), - static_cast(mainVertexShader.Data.uVertexColor.X * 255.0f + 0.5f), - static_cast(mainVertexShader.Data.uVertexColor.Y * 255.0f + 0.5f), - static_cast(mainVertexShader.Data.uVertexColor.Z * 255.0f + 0.5f)), 0); + drawargs.SetStyle(TriBlendMode::FillTranslucent); return; case SHADER_BasicFuzz: case SHADER_SmoothFuzz: @@ -346,7 +341,6 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu case SHADER_SmoothNoiseFuzz: case SHADER_SoftwareFuzz: drawargs.SetStyle(TriBlendMode::Fuzzy); - drawargs.SetColor(0xff000000, 0); return; } @@ -431,7 +425,7 @@ void PolyTriangleThreadData::SetDepthRange(float min, float max) void PolyTriangleThreadData::SetDepthBias(float depthBiasConstantFactor, float depthBiasSlopeFactor) { - depthbias = (float)(depthBiasConstantFactor / 65536.0); + depthbias = (float)(depthBiasConstantFactor / 2500.0); } void PolyTriangleThreadData::SetColorMask(bool r, bool g, bool b, bool a) @@ -659,6 +653,8 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve if (IsDegenerate(vert)) return; + drawargs.SetColor(vert[0]->vColor, 0); + // Cull, clip and generate additional vertices as needed ScreenTriVertex clippedvert[max_additional_vertices]; int numclipvert = ClipEdge(vert); diff --git a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h index 56486d047..a431f8941 100644 --- a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h +++ b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h @@ -15,6 +15,7 @@ public: Vec4f gl_Position; float gl_ClipDistance[5]; Vec4f vTexCoord; + uint32_t vColor; Vec4f pixelpos; }; @@ -24,13 +25,12 @@ public: // Input Vec4f aPosition; Vec2f aTexCoord; - Vec4f aColor; + uint32_t aColor; Vec4f aVertex2; Vec4f aNormal; Vec4f aNormal2; // Output - Vec4f vColor; Vec3f glowdist; Vec3f gradientdist; Vec4f vWorldNormal; @@ -243,6 +243,8 @@ public: pixelpos = (*objectToWorld) * objpos; } + vColor = drawargs->Color(); + // Calculate gl_ClipDistance[i] for (int i = 0; i < 3; i++) { diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 1bc6a708c..e8ce32528 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -2128,6 +2128,7 @@ void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs * &DrawSpan8, &DrawSpan8, &DrawSpan8, + &DrawSpan8, &DrawSpan8, &DrawSpan8, &DrawSpan8, @@ -2160,6 +2161,7 @@ void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs &DrawSpan32, &DrawSpan32, &DrawSpan32, + &DrawSpan32, &DrawSpan32, &DrawSpan32, &DrawSpan32, diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.h b/src/rendering/polyrenderer/drawers/screen_triangle.h index 92d346376..3e9bef620 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.h +++ b/src/rendering/polyrenderer/drawers/screen_triangle.h @@ -104,6 +104,7 @@ enum class TriBlendMode FogBoundary, SrcColor, Fill, + FillTranslucent, Normal, Fuzzy, Stencil, @@ -162,6 +163,7 @@ namespace TriScreenDrawerModes struct StyleFogBoundary { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_FogBoundary; }; struct StyleSrcColor { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_SrcColorOneMinusSrcColor; }; struct StyleFill { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Fill; }; + struct StyleFillTranslucent { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Fill; }; struct StyleNormal { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = 0; }; struct StyleFuzzy { static const int BlendOp = STYLEOP_Fuzz, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; }; From a1229be5c6653a53fd9c187041cd283c0c9573ff Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 29 May 2019 05:45:19 +0200 Subject: [PATCH 18/60] - implement camera textures --- src/CMakeLists.txt | 1 - .../polyrenderer/backend/poly_framebuffer.cpp | 33 +++------ .../polyrenderer/backend/poly_framebuffer.h | 2 + .../polyrenderer/backend/poly_hwtexture.cpp | 11 +++ .../polyrenderer/backend/poly_hwtexture.h | 2 + .../polyrenderer/backend/poly_renderstate.cpp | 19 ++++-- .../polyrenderer/backend/poly_renderstate.h | 8 ++- .../polyrenderer/drawers/poly_buffer.cpp | 67 ------------------- .../polyrenderer/drawers/poly_buffer.h | 55 --------------- .../polyrenderer/drawers/poly_triangle.cpp | 27 +++----- .../polyrenderer/drawers/poly_triangle.h | 38 ++++++++--- .../polyrenderer/drawers/screen_triangle.cpp | 6 +- src/rendering/polyrenderer/poly_all.cpp | 1 - src/rendering/swrenderer/drawers/r_draw.cpp | 14 ++-- src/rendering/swrenderer/scene/r_scene.cpp | 17 ++++- src/rendering/swrenderer/scene/r_scene.h | 3 + .../swrenderer/viewport/r_viewport.h | 2 + 17 files changed, 112 insertions(+), 194 deletions(-) delete mode 100644 src/rendering/polyrenderer/drawers/poly_buffer.cpp delete mode 100644 src/rendering/polyrenderer/drawers/poly_buffer.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 978b32759..7eb9fd373 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -785,7 +785,6 @@ set ( SWRENDER_SOURCES ) set( POLYRENDER_SOURCES - rendering/polyrenderer/drawers/poly_buffer.cpp rendering/polyrenderer/drawers/poly_triangle.cpp rendering/polyrenderer/drawers/poly_draw_args.cpp rendering/polyrenderer/drawers/screen_triangle.cpp diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index bdbc1ef80..c5e2a6707 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -102,9 +102,10 @@ void PolyFrameBuffer::CheckCanvas() mCanvas.reset(new DCanvas(0, 0, true)); mCanvas->Resize(GetWidth(), GetHeight(), false); + mDepthStencil.reset(); + mDepthStencil.reset(new PolyDepthStencil(GetWidth(), GetHeight())); - PolyTriangleDrawer::ResizeBuffers(mCanvas.get()); - PolyTriangleDrawer::SetViewport(GetDrawCommands(), 0, 0, mCanvas->GetWidth(), mCanvas->GetHeight(), mCanvas.get()); + mRenderState->SetRenderTarget(GetCanvas(), GetDepthStencil()); } } @@ -308,42 +309,28 @@ sector_t *PolyFrameBuffer::RenderViewpoint(FRenderViewpoint &mainvp, AActor * ca void PolyFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV) { -#if 0 // This doesn't need to clear the fake flat cache. It can be shared between camera textures and the main view of a scene. FMaterial *mat = FMaterial::ValidateTexture(tex, false); auto BaseLayer = static_cast(mat->GetLayer(0, 0)); int width = mat->TextureWidth(); int height = mat->TextureHeight(); - PolyTextureImage *image = BaseLayer->GetImage(tex, 0, 0); - PolyTextureImage *depthStencil = BaseLayer->GetDepthStencil(tex); - - mRenderState->EndRenderPass(); - - PolyImageTransition barrier0; - barrier0.addImage(image, Poly_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); - barrier0.execute(GetDrawCommands()); - - mRenderState->SetRenderTarget(image->View.get(), depthStencil->View.get(), image->Image->width, image->Image->height, Poly_FORMAT_R8G8B8A8_UNORM, Poly_SAMPLE_COUNT_1_BIT); + DCanvas *image = BaseLayer->GetImage(tex, 0, 0); + PolyDepthStencil *depthStencil = BaseLayer->GetDepthStencil(tex); + mRenderState->SetRenderTarget(image, depthStencil); IntRect bounds; bounds.left = bounds.top = 0; - bounds.width = MIN(mat->GetWidth(), image->Image->width); - bounds.height = MIN(mat->GetHeight(), image->Image->height); + bounds.width = MIN(mat->GetWidth(), image->GetWidth()); + bounds.height = MIN(mat->GetHeight(), image->GetHeight()); FRenderViewpoint texvp; RenderViewpoint(texvp, Viewpoint, &bounds, FOV, (float)width / height, (float)width / height, false, false); - mRenderState->EndRenderPass(); - - PolyImageTransition barrier1; - barrier1.addImage(image, Poly_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); - barrier1.execute(GetDrawCommands()); - - mRenderState->SetRenderTarget(GetBuffers()->SceneColor.View.get(), GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), Poly_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); + DrawerThreads::WaitForWorkers(); + mRenderState->SetRenderTarget(GetCanvas(), GetDepthStencil()); tex->SetUpdated(true); -#endif } void PolyFrameBuffer::DrawScene(HWDrawInfo *di, int drawmode) diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.h b/src/rendering/polyrenderer/backend/poly_framebuffer.h index e6f6e2afd..b779beb58 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.h +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.h @@ -18,6 +18,7 @@ public: RenderMemory *GetFrameMemory() { return &mFrameMemory; } PolyRenderState *GetRenderState() { return mRenderState.get(); } DCanvas *GetCanvas() { return mCanvas.get(); } + PolyDepthStencil *GetDepthStencil() { return mDepthStencil.get(); } const DrawerCommandQueuePtr &GetDrawCommands(); void FlushDrawCommands(); @@ -75,6 +76,7 @@ private: std::unique_ptr mRenderState; std::unique_ptr mCanvas; + std::unique_ptr mDepthStencil; std::shared_ptr mDrawCommands; RenderMemory mFrameMemory; }; diff --git a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp index ff3ee95fa..cd3102b53 100644 --- a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp +++ b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp @@ -84,6 +84,17 @@ DCanvas *PolyHardwareTexture::GetImage(FTexture *tex, int translation, int flags return mCanvas.get(); } +PolyDepthStencil *PolyHardwareTexture::GetDepthStencil(FTexture *tex) +{ + if (!mDepthStencil) + { + int w = tex->GetWidth(); + int h = tex->GetHeight(); + mDepthStencil.reset(new PolyDepthStencil(w, h)); + } + return mDepthStencil.get(); +} + void PolyHardwareTexture::AllocateBuffer(int w, int h, int texelsize) { if (!mCanvas || mCanvas->GetWidth() != w || mCanvas->GetHeight() != h) diff --git a/src/rendering/polyrenderer/backend/poly_hwtexture.h b/src/rendering/polyrenderer/backend/poly_hwtexture.h index 805fd37da..d88604c66 100644 --- a/src/rendering/polyrenderer/backend/poly_hwtexture.h +++ b/src/rendering/polyrenderer/backend/poly_hwtexture.h @@ -27,6 +27,7 @@ public: DCanvas *GetImage(const FMaterialState &state); DCanvas *GetImage(FTexture *tex, int translation, int flags); + PolyDepthStencil *GetDepthStencil(FTexture *tex); // Software renderer stuff void AllocateBuffer(int w, int h, int texelsize) override; @@ -43,4 +44,5 @@ private: PolyHardwareTexture *Prev = nullptr; PolyHardwareTexture *Next = nullptr; std::unique_ptr mCanvas; + std::unique_ptr mDepthStencil; }; diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 7423cc973..25690564e 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -125,10 +125,10 @@ void PolyRenderState::SetScissor(int x, int y, int w, int h) { x = 0; y = 0; - w = fb->GetCanvas()->GetWidth(); - h = fb->GetCanvas()->GetHeight(); + w = mRenderTarget.Canvas->GetWidth(); + h = mRenderTarget.Canvas->GetHeight(); } - PolyTriangleDrawer::SetScissor(fb->GetDrawCommands(), x, fb->GetCanvas()->GetHeight() - y - h, w, h); + PolyTriangleDrawer::SetScissor(fb->GetDrawCommands(), x, mRenderTarget.Canvas->GetHeight() - y - h, w, h); } void PolyRenderState::SetViewport(int x, int y, int w, int h) @@ -138,10 +138,10 @@ void PolyRenderState::SetViewport(int x, int y, int w, int h) { x = 0; y = 0; - w = fb->GetCanvas()->GetWidth(); - h = fb->GetCanvas()->GetHeight(); + w = mRenderTarget.Canvas->GetWidth(); + h = mRenderTarget.Canvas->GetHeight(); } - PolyTriangleDrawer::SetViewport(fb->GetDrawCommands(), x, fb->GetCanvas()->GetHeight() - y - h, w, h, fb->GetCanvas()); + PolyTriangleDrawer::SetViewport(fb->GetDrawCommands(), x, mRenderTarget.Canvas->GetHeight() - y - h, w, h, mRenderTarget.Canvas, mRenderTarget.DepthStencil); } void PolyRenderState::EnableDepthTest(bool on) @@ -288,6 +288,13 @@ void PolyRenderState::ApplyMatrices() } } +void PolyRenderState::SetRenderTarget(DCanvas *canvas, PolyDepthStencil *depthStencil) +{ + mRenderTarget.Canvas = canvas; + mRenderTarget.DepthStencil = depthStencil; + PolyTriangleDrawer::SetViewport(GetPolyFrameBuffer()->GetDrawCommands(), 0, 0, canvas->GetWidth(), canvas->GetHeight(), canvas, depthStencil); +} + void PolyRenderState::Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t length) { if (buffer->bindingpoint == VIEWPOINT_BINDINGPOINT) diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.h b/src/rendering/polyrenderer/backend/poly_renderstate.h index 8634d64e5..4afa1218e 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.h +++ b/src/rendering/polyrenderer/backend/poly_renderstate.h @@ -40,8 +40,8 @@ public: void EnableLineSmooth(bool on) override; void EnableDrawBuffers(int count) override; + void SetRenderTarget(DCanvas *canvas, PolyDepthStencil *depthStencil); void Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t length); - PolyVertexInputAssembly *GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs); private: @@ -63,4 +63,10 @@ private: bool mDepthClamp = true; int mTempTM = TM_NORMAL; + + struct RenderTarget + { + DCanvas *Canvas = nullptr; + PolyDepthStencil *DepthStencil = nullptr; + } mRenderTarget; }; diff --git a/src/rendering/polyrenderer/drawers/poly_buffer.cpp b/src/rendering/polyrenderer/drawers/poly_buffer.cpp deleted file mode 100644 index d205fe8cc..000000000 --- a/src/rendering/polyrenderer/drawers/poly_buffer.cpp +++ /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. -** -*/ - -#include -#include "templates.h" -#include "doomdef.h" - -#include "w_wad.h" -#include "v_video.h" -#include "doomstat.h" -#include "st_stuff.h" -#include "g_game.h" -#include "g_level.h" -#include "r_data/r_translate.h" -#include "v_palette.h" -#include "r_data/colormaps.h" -#include "poly_buffer.h" -#include "screen_triangle.h" - -///////////////////////////////////////////////////////////////////////////// - -PolyZBuffer *PolyZBuffer::Instance() -{ - static PolyZBuffer buffer; - return &buffer; -} - -void PolyZBuffer::Resize(int newwidth, int newheight) -{ - width = newwidth; - height = newheight; - values.resize(width * height); -} - -///////////////////////////////////////////////////////////////////////////// - -PolyStencilBuffer *PolyStencilBuffer::Instance() -{ - static PolyStencilBuffer buffer; - return &buffer; -} - -void PolyStencilBuffer::Resize(int newwidth, int newheight) -{ - width = newwidth; - height = newheight; - values.resize(width * height); -} diff --git a/src/rendering/polyrenderer/drawers/poly_buffer.h b/src/rendering/polyrenderer/drawers/poly_buffer.h deleted file mode 100644 index 14ffd5063..000000000 --- a/src/rendering/polyrenderer/drawers/poly_buffer.h +++ /dev/null @@ -1,55 +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 - -class PolyZBuffer -{ -public: - static PolyZBuffer *Instance(); - void Resize(int newwidth, int newheight); - int Width() const { return width; } - int Height() const { return height; } - float *Values() { return values.data(); } - -private: - int width; - int height; - std::vector values; -}; - -class PolyStencilBuffer -{ -public: - static PolyStencilBuffer *Instance(); - void Resize(int newwidth, int newheight); - int Width() const { return width; } - int Height() const { return height; } - uint8_t *Values() { return values.data(); } - -private: - int width; - int height; - std::vector values; -}; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 01f345160..0dd087a04 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -41,12 +41,6 @@ static bool isBgraRenderTarget = false; -void PolyTriangleDrawer::ResizeBuffers(DCanvas *canvas) -{ - PolyStencilBuffer::Instance()->Resize(canvas->GetWidth(), canvas->GetHeight()); - PolyZBuffer::Instance()->Resize(canvas->GetPitch(), canvas->GetHeight()); -} - bool PolyTriangleDrawer::IsBgra() { return isBgraRenderTarget; @@ -62,7 +56,7 @@ void PolyTriangleDrawer::ClearStencil(const DrawerCommandQueuePtr &queue, uint8_ queue->Push(value); } -void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas) +void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas, PolyDepthStencil *depthstencil) { uint8_t *dest = (uint8_t*)canvas->GetPixels(); int dest_width = canvas->GetWidth(); @@ -71,7 +65,7 @@ void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, bool dest_bgra = canvas->IsBgra(); isBgraRenderTarget = dest_bgra; - queue->Push(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra); + queue->Push(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra, depthstencil); } void PolyTriangleDrawer::SetInputAssembly(const DrawerCommandQueuePtr &queue, PolyInputAssembly *input) @@ -223,10 +217,9 @@ void PolyTriangleDrawer::DrawIndexed(const DrawerCommandQueuePtr &queue, int ind void PolyTriangleThreadData::ClearDepth(float value) { - auto buffer = PolyZBuffer::Instance(); - int width = buffer->Width(); - int height = buffer->Height(); - float *data = buffer->Values(); + int width = depthstencil->Width(); + int height = depthstencil->Height(); + float *data = depthstencil->DepthValues(); int skip = skipped_by_thread(0); int count = count_for_thread(0, height); @@ -242,10 +235,9 @@ void PolyTriangleThreadData::ClearDepth(float value) void PolyTriangleThreadData::ClearStencil(uint8_t value) { - auto buffer = PolyStencilBuffer::Instance(); - int width = buffer->Width(); - int height = buffer->Height(); - uint8_t *data = buffer->Values(); + int width = depthstencil->Width(); + int height = depthstencil->Height(); + uint8_t *data = depthstencil->StencilValues(); int skip = skipped_by_thread(0); int count = count_for_thread(0, height); @@ -258,7 +250,7 @@ void PolyTriangleThreadData::ClearStencil(uint8_t value) } } -void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, uint8_t *new_dest, int new_dest_width, int new_dest_height, int new_dest_pitch, bool new_dest_bgra) +void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, uint8_t *new_dest, int new_dest_width, int new_dest_height, int new_dest_pitch, bool new_dest_bgra, PolyDepthStencil *new_depthstencil) { viewport_x = x; viewport_y = y; @@ -269,6 +261,7 @@ void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, ui dest_height = new_dest_height; dest_pitch = new_dest_pitch; dest_bgra = new_dest_bgra; + depthstencil = new_depthstencil; UpdateClip(); } diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 1dc82568f..ed7d0aaea 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -26,23 +26,19 @@ #include "swrenderer/drawers/r_thread.h" #include "polyrenderer/drawers/screen_triangle.h" #include "polyrenderer/math/gpu_types.h" -#include "polyrenderer/drawers/poly_buffer.h" #include "polyrenderer/drawers/poly_draw_args.h" #include "polyrenderer/drawers/poly_vertex_shader.h" class DCanvas; class PolyDrawerCommand; class PolyInputAssembly; -class PolyPipeline; +class PolyDepthStencil; struct PolyPushConstants; class PolyTriangleDrawer { public: - static void ResizeBuffers(DCanvas *canvas); - static void ClearDepth(const DrawerCommandQueuePtr &queue, float value); - static void ClearStencil(const DrawerCommandQueuePtr &queue, uint8_t value); - static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas); + static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas, PolyDepthStencil *depthStencil); static void SetInputAssembly(const DrawerCommandQueuePtr &queue, PolyInputAssembly *input); static void SetVertexBuffer(const DrawerCommandQueuePtr &queue, const void *vertices); static void SetIndexBuffer(const DrawerCommandQueuePtr &queue, const void *elements); @@ -64,6 +60,8 @@ public: static void SetShader(const DrawerCommandQueuePtr &queue, int specialEffect, int effectState, bool alphaTest); static void PushStreamData(const DrawerCommandQueuePtr &queue, const StreamData &data, const PolyPushConstants &constants); static void PushMatrices(const DrawerCommandQueuePtr &queue, const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); + static void ClearDepth(const DrawerCommandQueuePtr &queue, float value); + static void ClearStencil(const DrawerCommandQueuePtr &queue, uint8_t value); static void Draw(const DrawerCommandQueuePtr &queue, int index, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); static void DrawIndexed(const DrawerCommandQueuePtr &queue, int index, int count, PolyDrawMode mode = PolyDrawMode::Triangles); static bool IsBgra(); @@ -77,6 +75,23 @@ public: static void PushDrawArgs(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args); }; +class PolyDepthStencil +{ +public: + PolyDepthStencil(int width, int height) : width(width), height(height), depthbuffer(width * height), stencilbuffer(width * height) { } + + int Width() const { return width; } + int Height() const { return height; } + float *DepthValues() { return depthbuffer.data(); } + uint8_t *StencilValues() { return stencilbuffer.data(); } + +private: + int width; + int height; + std::vector depthbuffer; + std::vector stencilbuffer; +}; + struct PolyPushConstants { int uTextureMode; @@ -117,7 +132,7 @@ public: void ClearDepth(float value); void ClearStencil(uint8_t value); - void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra); + void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, PolyDepthStencil *depthstencil); void SetTransform(const Mat4f *objectToClip, const Mat4f *objectToWorld); void SetCullCCW(bool value) { ccw = value; } @@ -198,6 +213,8 @@ public: int dest_height = 0; bool dest_bgra = false; uint8_t *dest = nullptr; + PolyDepthStencil *depthstencil = nullptr; + float depthbias = 0.0f; int viewport_y = 0; @@ -521,9 +538,9 @@ private: class PolySetViewportCommand : public PolyDrawerCommand { public: - PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra) - : x(x), y(y), width(width), height(height), dest(dest), dest_width(dest_width), dest_height(dest_height), dest_pitch(dest_pitch), dest_bgra(dest_bgra) { } - void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetViewport(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra); } + PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, PolyDepthStencil *depthstencil) + : x(x), y(y), width(width), height(height), dest(dest), dest_width(dest_width), dest_height(dest_height), dest_pitch(dest_pitch), dest_bgra(dest_bgra), depthstencil(depthstencil) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetViewport(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra, depthstencil); } private: int x; @@ -535,6 +552,7 @@ private: int dest_height; int dest_pitch; bool dest_bgra; + PolyDepthStencil *depthstencil; }; class PolySetViewpointUniformsCommand : public PolyDrawerCommand diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index e8ce32528..664bd7137 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -201,16 +201,16 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa v1X = args->v1->x; v1Y = args->v1->y; v1W = args->v1->w; - zbuffer = PolyZBuffer::Instance()->Values(); + zbuffer = thread->depthstencil->DepthValues(); } if ((OptT::Flags & SWTRI_StencilTest) || (OptT::Flags & SWTRI_WriteStencil)) { - stencilbuffer = PolyStencilBuffer::Instance()->Values(); + stencilbuffer = thread->depthstencil->StencilValues(); } if ((OptT::Flags & SWTRI_StencilTest) || (OptT::Flags & SWTRI_WriteStencil) || (OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_WriteDepth)) - pitch = PolyStencilBuffer::Instance()->Width(); + pitch = thread->depthstencil->Width(); if (OptT::Flags & SWTRI_StencilTest) stencilTestValue = args->uniforms->StencilTestValue(); diff --git a/src/rendering/polyrenderer/poly_all.cpp b/src/rendering/polyrenderer/poly_all.cpp index 0d7295d7f..5e0dba3f2 100644 --- a/src/rendering/polyrenderer/poly_all.cpp +++ b/src/rendering/polyrenderer/poly_all.cpp @@ -1,5 +1,4 @@ #include "../swrenderer/textures/r_swtexture.h" -#include "drawers/poly_buffer.cpp" #include "drawers/poly_draw_args.cpp" #include "drawers/poly_triangle.cpp" #include "drawers/screen_triangle.cpp" diff --git a/src/rendering/swrenderer/drawers/r_draw.cpp b/src/rendering/swrenderer/drawers/r_draw.cpp index 20425a7ec..b2a101788 100644 --- a/src/rendering/swrenderer/drawers/r_draw.cpp +++ b/src/rendering/swrenderer/drawers/r_draw.cpp @@ -51,7 +51,7 @@ #include "r_draw_pal.h" #include "r_thread.h" #include "swrenderer/scene/r_light.h" -#include "polyrenderer/drawers/poly_buffer.h" +#include "polyrenderer/drawers/poly_triangle.h" CVAR(Bool, r_dynlights, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); CVAR(Bool, r_fuzzscale, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); @@ -270,9 +270,9 @@ namespace swrenderer void Execute(DrawerThread *thread) override { - auto zbuffer = PolyZBuffer::Instance(); - int pitch = PolyStencilBuffer::Instance()->Width(); - float *values = zbuffer->Values() + y * pitch + x; + auto zbuffer = PolyTriangleThreadData::Get(thread)->depthstencil; + int pitch = zbuffer->Width(); + float *values = zbuffer->DepthValues() + y * pitch + x; int cnt = count; values = thread->dest_for_thread(y, pitch, values); @@ -312,9 +312,9 @@ namespace swrenderer if (thread->skipped_by_thread(y)) return; - auto zbuffer = PolyZBuffer::Instance(); - int pitch = PolyStencilBuffer::Instance()->Width(); - float *values = zbuffer->Values() + y * pitch; + auto zbuffer = PolyTriangleThreadData::Get(thread)->depthstencil; + int pitch = zbuffer->Width(); + float *values = zbuffer->DepthValues() + y * pitch; int end = x2; if (idepth1 == idepth2) diff --git a/src/rendering/swrenderer/scene/r_scene.cpp b/src/rendering/swrenderer/scene/r_scene.cpp index 7bd5dcea3..280c9c1d0 100644 --- a/src/rendering/swrenderer/scene/r_scene.cpp +++ b/src/rendering/swrenderer/scene/r_scene.cpp @@ -107,7 +107,12 @@ namespace swrenderer r_modelscene = r_models && Models.Size() > 0; if (r_modelscene) { - PolyTriangleDrawer::ResizeBuffers(viewport->RenderTarget); + if (!DepthStencil || DepthStencil->Width() != viewport->RenderTarget->GetWidth() || DepthStencil->Height() != viewport->RenderTarget->GetHeight()) + { + DepthStencil.reset(); + DepthStencil.reset(new PolyDepthStencil(viewport->RenderTarget->GetWidth(), viewport->RenderTarget->GetHeight())); + } + PolyTriangleDrawer::SetViewport(MainThread()->DrawQueue, 0, 0, viewport->RenderTarget->GetWidth(), viewport->RenderTarget->GetHeight(), viewport->RenderTarget, DepthStencil.get()); PolyTriangleDrawer::ClearStencil(MainThread()->DrawQueue, 0); } @@ -275,7 +280,7 @@ namespace swrenderer if (r_modelscene && thread->MainThread) PolyTriangleDrawer::ClearStencil(MainThread()->DrawQueue, 0); - PolyTriangleDrawer::SetViewport(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight, thread->Viewport->RenderTarget); + PolyTriangleDrawer::SetViewport(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight, thread->Viewport->RenderTarget, DepthStencil.get()); PolyTriangleDrawer::SetScissor(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight); // Cull things outside the range seen by this thread @@ -372,7 +377,13 @@ namespace swrenderer viewactive = true; viewport->SetViewport(actor->Level, MainThread(), width, height, MainThread()->Viewport->viewwindow.WidescreenRatio); if (r_modelscene) - PolyTriangleDrawer::ResizeBuffers(viewport->RenderTarget); + { + if (!DepthStencil || DepthStencil->Width() != viewport->RenderTarget->GetWidth() || DepthStencil->Height() != viewport->RenderTarget->GetHeight()) + { + DepthStencil.reset(); + DepthStencil.reset(new PolyDepthStencil(viewport->RenderTarget->GetWidth(), viewport->RenderTarget->GetHeight())); + } + } // Render: RenderActorView(actor, false, dontmaplines); diff --git a/src/rendering/swrenderer/scene/r_scene.h b/src/rendering/swrenderer/scene/r_scene.h index 035d12133..c5fa8e959 100644 --- a/src/rendering/swrenderer/scene/r_scene.h +++ b/src/rendering/swrenderer/scene/r_scene.h @@ -32,6 +32,8 @@ extern cycle_t FrameCycles; +class PolyDepthStencil; + namespace swrenderer { extern cycle_t WallCycles, PlaneCycles, MaskedCycles, DrawerWaitCycles; @@ -67,6 +69,7 @@ namespace swrenderer bool dontmaplines = false; int clearcolor = 0; + std::unique_ptr DepthStencil; std::vector> Threads; std::mutex start_mutex; std::condition_variable start_condition; diff --git a/src/rendering/swrenderer/viewport/r_viewport.h b/src/rendering/swrenderer/viewport/r_viewport.h index 10a665732..ae80ac825 100644 --- a/src/rendering/swrenderer/viewport/r_viewport.h +++ b/src/rendering/swrenderer/viewport/r_viewport.h @@ -11,6 +11,8 @@ #define MINZ double((2048*4) / double(1 << 20)) +class PolyDepthStencil; + namespace swrenderer { class RenderThread; From b9230d44250128ae6e277e1feb05fcd817a087c4 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 29 May 2019 06:42:02 +0200 Subject: [PATCH 19/60] - fix negative uLightLevel being applied --- src/rendering/polyrenderer/drawers/poly_triangle.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 0dd087a04..7ca3628cc 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -300,7 +300,14 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu FColormap cm; cm.Clear(); - drawargs.SetLight(GetColorTable(cm), (int)(constants.uLightLevel * 255.0f), mainVertexShader.Viewpoint->mGlobVis * 32.0f, false); + if (constants.uLightLevel >= 0.0f) + { + drawargs.SetLight(GetColorTable(cm), (int)(constants.uLightLevel * 255.0f), mainVertexShader.Viewpoint->mGlobVis * 32.0f, false); + } + else + { + drawargs.SetLight(GetColorTable(cm), 255, mainVertexShader.Viewpoint->mGlobVis * 32.0f, true); + } if (SpecialEffect != EFF_NONE) { From 4bbab49e046ea4da4290f5c04ce7fbc771bd9773 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 30 May 2019 23:31:39 +0200 Subject: [PATCH 20/60] - present using direct3d 9 --- src/win32/win32polyvideo.cpp | 124 +++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/src/win32/win32polyvideo.cpp b/src/win32/win32polyvideo.cpp index cb7638fdf..e783c710b 100644 --- a/src/win32/win32polyvideo.cpp +++ b/src/win32/win32polyvideo.cpp @@ -1,10 +1,132 @@ #include #include "hardware.h" +#include "doomerrors.h" #include extern HWND Window; +#if 1 + +#include +#pragma comment(lib, "d3d9.lib") + +struct D3D9Present +{ + D3D9Present() + { + d3d9 = Direct3DCreate9(D3D_SDK_VERSION); + if (!d3d9) + { + I_FatalError("Direct3DCreate9 failed"); + } + + bool vsync = false; + RECT rect = {}; + GetClientRect(Window, &rect); + ClientWidth = rect.right; + ClientHeight = rect.bottom; + + D3DPRESENT_PARAMETERS pp = {}; + pp.Windowed = true; + pp.SwapEffect = D3DSWAPEFFECT_DISCARD; + pp.BackBufferWidth = ClientWidth; + pp.BackBufferHeight = ClientHeight; + pp.BackBufferCount = 1; + pp.hDeviceWindow = Window; + pp.PresentationInterval = vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + + HRESULT result = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, &device); + if (FAILED(result)) + { + I_FatalError("IDirect3D9.CreateDevice failed"); + } + } + + void Present(int w, int h, const void *pixels) + { + HRESULT result; + if (SrcWidth != w || SrcHeight != h || !surface) + { + if (surface) + { + surface->Release(); + surface = nullptr; + } + + SrcWidth = w; + SrcHeight = h; + result = device->CreateOffscreenPlainSurface(SrcWidth, SrcHeight, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, 0); + if (FAILED(result)) + { + I_FatalError("IDirect3DDevice9.CreateOffscreenPlainSurface failed"); + } + } + + D3DLOCKED_RECT lockrect = {}; + result = surface->LockRect(&lockrect, nullptr, D3DLOCK_DISCARD); + if (FAILED(result)) + return; + + int pixelsize = 4; + const uint8_t *src = (const uint8_t*)pixels; + uint8_t *dst = (uint8_t*)lockrect.pBits; + for (int y = 0; y < h; y++) + { + memcpy(dst + y * lockrect.Pitch, src + y * w * pixelsize, w * pixelsize); + } + + surface->UnlockRect(); + + IDirect3DSurface9 *backbuffer = nullptr; + device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); + if (FAILED(result)) + return; + + result = device->BeginScene(); + if (SUCCEEDED(result)) + { + RECT srcrect = {}, dstrect = {}; + srcrect.right = SrcWidth; + srcrect.bottom = SrcHeight; + dstrect.right = ClientWidth; + dstrect.bottom = ClientHeight; + device->StretchRect(surface, &srcrect, backbuffer, &dstrect, D3DTEXF_LINEAR); + + result = device->EndScene(); + if (SUCCEEDED(result)) + device->Present(nullptr, nullptr, 0, nullptr); + } + + backbuffer->Release(); + } + + ~D3D9Present() + { + if (surface) surface->Release(); + if (device) device->Release(); + if (d3d9) d3d9->Release(); + } + +private: + int SrcWidth = 0; + int SrcHeight = 0; + int ClientWidth = 0; + int ClientHeight = 0; + + IDirect3D9 *d3d9 = nullptr; + IDirect3DDevice9 *device = nullptr; + IDirect3DSurface9 *surface = nullptr; +}; + +void I_PresentPolyImage(int w, int h, const void *pixels) +{ + static D3D9Present present; + present.Present(w, h, pixels); +} + +#else + void I_PresentPolyImage(int w, int h, const void *pixels) { BITMAPV5HEADER info = {}; @@ -27,3 +149,5 @@ void I_PresentPolyImage(int w, int h, const void *pixels) StretchDIBits(dc, 0, 0, box.right, box.bottom, 0, 0, w, h, pixels, (const BITMAPINFO *)&info, DIB_RGB_COLORS, SRCCOPY); ReleaseDC(Window, dc); } + +#endif From 4a7824c38027584d17b1b4c542cccf3c07236280 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 31 May 2019 05:22:06 +0200 Subject: [PATCH 21/60] - implement vsync and letterbox --- .../polyrenderer/backend/poly_framebuffer.cpp | 28 +- src/win32/win32polyvideo.cpp | 248 ++++++++++-------- 2 files changed, 166 insertions(+), 110 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index c5e2a6707..3d8b75bd8 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -48,13 +48,20 @@ extern bool keepGpuStatActive; extern FString gpuStatOutput; #ifdef WIN32 -void I_PresentPolyImage(int w, int h, const void *pixels); +void I_PolyPresentInit(); +uint8_t *I_PolyPresentLock(int w, int h, int &pitch); +void I_PolyPresentUnlock(int x, int y, int w, int h); +void I_PolyPresentDeinit(); #else -void I_PresentPolyImage(int w, int h, const void *pixels) { } +void I_PolyPresentInit() { } +uint8_t *I_PolyPresentLock(int w, int h, int &pitch) { pitch = 0; return nullptr; } +void I_PolyPresentUnlock() { } +void I_PolyPresentDeinit() { } #endif PolyFrameBuffer::PolyFrameBuffer(void *hMonitor, bool fullscreen) : Super(hMonitor, fullscreen) { + I_PolyPresentInit(); } PolyFrameBuffer::~PolyFrameBuffer() @@ -74,6 +81,8 @@ PolyFrameBuffer::~PolyFrameBuffer() mShadowMap.Reset(); screen = tmp; + + I_PolyPresentDeinit(); } void PolyFrameBuffer::InitializeState() @@ -145,7 +154,20 @@ void PolyFrameBuffer::Update() if (mCanvas) { - I_PresentPolyImage(mCanvas->GetWidth(), mCanvas->GetHeight(), mCanvas->GetPixels()); + int w = mCanvas->GetWidth(); + int h = mCanvas->GetHeight(); + int pixelsize = 4; + const uint8_t *src = (const uint8_t*)mCanvas->GetPixels(); + int pitch = 0; + uint8_t *dst = I_PolyPresentLock(w, h, pitch); + if (dst) + { + for (int y = 0; y < h; y++) + { + memcpy(dst + y * pitch, src + y * w * pixelsize, w * pixelsize); + } + I_PolyPresentUnlock(mOutputLetterbox.left, mOutputLetterbox.top, mOutputLetterbox.width, mOutputLetterbox.height); + } } CheckCanvas(); diff --git a/src/win32/win32polyvideo.cpp b/src/win32/win32polyvideo.cpp index e783c710b..a6e74218a 100644 --- a/src/win32/win32polyvideo.cpp +++ b/src/win32/win32polyvideo.cpp @@ -4,26 +4,72 @@ #include "doomerrors.h" #include -extern HWND Window; +EXTERN_CVAR(Bool, vid_vsync) -#if 1 +extern HWND Window; #include #pragma comment(lib, "d3d9.lib") -struct D3D9Present +namespace { - D3D9Present() + int SrcWidth = 0; + int SrcHeight = 0; + int ClientWidth = 0; + int ClientHeight = 0; + bool CurrentVSync = false; + + IDirect3D9 *d3d9 = nullptr; + IDirect3DDevice9 *device = nullptr; + IDirect3DSurface9 *surface = nullptr; +} + +void I_PolyPresentInit() +{ + d3d9 = Direct3DCreate9(D3D_SDK_VERSION); + if (!d3d9) { - d3d9 = Direct3DCreate9(D3D_SDK_VERSION); - if (!d3d9) + I_FatalError("Direct3DCreate9 failed"); + } + + RECT rect = {}; + GetClientRect(Window, &rect); + + CurrentVSync = vid_vsync; + ClientWidth = rect.right; + ClientHeight = rect.bottom; + + D3DPRESENT_PARAMETERS pp = {}; + pp.Windowed = true; + pp.SwapEffect = D3DSWAPEFFECT_DISCARD; + pp.BackBufferWidth = ClientWidth; + pp.BackBufferHeight = ClientHeight; + pp.BackBufferCount = 1; + pp.hDeviceWindow = Window; + pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + + HRESULT result = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, &device); + if (FAILED(result)) + { + I_FatalError("IDirect3D9.CreateDevice failed"); + } +} + +uint8_t *I_PolyPresentLock(int w, int h, int &pitch) +{ + HRESULT result; + + RECT rect = {}; + GetClientRect(Window, &rect); + if (rect.right != ClientWidth || rect.bottom != ClientHeight || CurrentVSync != vid_vsync) + { + if (surface) { - I_FatalError("Direct3DCreate9 failed"); + surface->Release(); + surface = nullptr; } - bool vsync = false; - RECT rect = {}; - GetClientRect(Window, &rect); + CurrentVSync = vid_vsync; ClientWidth = rect.right; ClientHeight = rect.bottom; @@ -34,120 +80,108 @@ struct D3D9Present pp.BackBufferHeight = ClientHeight; pp.BackBufferCount = 1; pp.hDeviceWindow = Window; - pp.PresentationInterval = vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + device->Reset(&pp); + } - HRESULT result = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, &device); + if (SrcWidth != w || SrcHeight != h || !surface) + { + if (surface) + { + surface->Release(); + surface = nullptr; + } + + SrcWidth = w; + SrcHeight = h; + result = device->CreateOffscreenPlainSurface(SrcWidth, SrcHeight, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, 0); if (FAILED(result)) { - I_FatalError("IDirect3D9.CreateDevice failed"); + I_FatalError("IDirect3DDevice9.CreateOffscreenPlainSurface failed"); } } - void Present(int w, int h, const void *pixels) + D3DLOCKED_RECT lockrect = {}; + result = surface->LockRect(&lockrect, nullptr, D3DLOCK_DISCARD); + if (FAILED(result)) { - HRESULT result; - if (SrcWidth != w || SrcHeight != h || !surface) + pitch = 0; + return nullptr; + } + + pitch = lockrect.Pitch; + return (uint8_t*)lockrect.pBits; +} + +void I_PolyPresentUnlock(int x, int y, int width, int height) +{ + surface->UnlockRect(); + + IDirect3DSurface9 *backbuffer = nullptr; + HRESULT result = device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); + if (FAILED(result)) + return; + + result = device->BeginScene(); + if (SUCCEEDED(result)) + { + int count = 0; + D3DRECT clearrects[4]; + if (y > 0) { - if (surface) - { - surface->Release(); - surface = nullptr; - } - - SrcWidth = w; - SrcHeight = h; - result = device->CreateOffscreenPlainSurface(SrcWidth, SrcHeight, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, 0); - if (FAILED(result)) - { - I_FatalError("IDirect3DDevice9.CreateOffscreenPlainSurface failed"); - } + clearrects[count].x1 = 0; + clearrects[count].y1 = 0; + clearrects[count].x2 = ClientWidth; + clearrects[count].y2 = y; + count++; } - - D3DLOCKED_RECT lockrect = {}; - result = surface->LockRect(&lockrect, nullptr, D3DLOCK_DISCARD); - if (FAILED(result)) - return; - - int pixelsize = 4; - const uint8_t *src = (const uint8_t*)pixels; - uint8_t *dst = (uint8_t*)lockrect.pBits; - for (int y = 0; y < h; y++) + if (y + height < ClientHeight) { - memcpy(dst + y * lockrect.Pitch, src + y * w * pixelsize, w * pixelsize); + clearrects[count].x1 = 0; + clearrects[count].y1 = y + height; + clearrects[count].x2 = ClientWidth; + clearrects[count].y2 = ClientHeight; + count++; } + if (x > 0) + { + clearrects[count].x1 = 0; + clearrects[count].y1 = y; + clearrects[count].x2 = x; + clearrects[count].y2 = y + height; + count++; + } + if (x + width < ClientWidth) + { + clearrects[count].x1 = x + width; + clearrects[count].y1 = y; + clearrects[count].x2 = ClientWidth; + clearrects[count].y2 = y + height; + count++; + } + if (count > 0) + device->Clear(count, clearrects, D3DCLEAR_TARGET, 0, 0.0f, 0); - surface->UnlockRect(); + RECT srcrect = {}, dstrect = {}; + srcrect.right = SrcWidth; + srcrect.bottom = SrcHeight; + dstrect.left = x; + dstrect.top = y; + dstrect.right = x + width; + dstrect.bottom = y + height; + device->StretchRect(surface, &srcrect, backbuffer, &dstrect, D3DTEXF_LINEAR); - IDirect3DSurface9 *backbuffer = nullptr; - device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); - if (FAILED(result)) - return; - - result = device->BeginScene(); + result = device->EndScene(); if (SUCCEEDED(result)) - { - RECT srcrect = {}, dstrect = {}; - srcrect.right = SrcWidth; - srcrect.bottom = SrcHeight; - dstrect.right = ClientWidth; - dstrect.bottom = ClientHeight; - device->StretchRect(surface, &srcrect, backbuffer, &dstrect, D3DTEXF_LINEAR); - - result = device->EndScene(); - if (SUCCEEDED(result)) - device->Present(nullptr, nullptr, 0, nullptr); - } - - backbuffer->Release(); + device->Present(nullptr, nullptr, 0, nullptr); } - ~D3D9Present() - { - if (surface) surface->Release(); - if (device) device->Release(); - if (d3d9) d3d9->Release(); - } - -private: - int SrcWidth = 0; - int SrcHeight = 0; - int ClientWidth = 0; - int ClientHeight = 0; - - IDirect3D9 *d3d9 = nullptr; - IDirect3DDevice9 *device = nullptr; - IDirect3DSurface9 *surface = nullptr; -}; - -void I_PresentPolyImage(int w, int h, const void *pixels) -{ - static D3D9Present present; - present.Present(w, h, pixels); + backbuffer->Release(); } -#else - -void I_PresentPolyImage(int w, int h, const void *pixels) +void I_PolyPresentDeinit() { - BITMAPV5HEADER info = {}; - info.bV5Size = sizeof(BITMAPV5HEADER); - info.bV5Width = w; - info.bV5Height = -h; - info.bV5Planes = 1; - info.bV5BitCount = 32; - info.bV5Compression = BI_RGB; - info.bV5SizeImage = 0; - info.bV5CSType = LCS_WINDOWS_COLOR_SPACE; - - RECT box = {}; - GetClientRect(Window, &box); - - HDC dc = GetDC(Window); - if (box.right == w && box.bottom == h) - SetDIBitsToDevice(dc, 0, 0, w, h, 0, 0, 0, h, pixels, (const BITMAPINFO *)&info, DIB_RGB_COLORS); - else - StretchDIBits(dc, 0, 0, box.right, box.bottom, 0, 0, w, h, pixels, (const BITMAPINFO *)&info, DIB_RGB_COLORS, SRCCOPY); - ReleaseDC(Window, dc); + if (surface) surface->Release(); + if (device) device->Release(); + if (d3d9) d3d9->Release(); } - -#endif From a5608c67b55d4fad2e48526520fac0c509000868 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 31 May 2019 05:42:04 +0200 Subject: [PATCH 22/60] - upload using all threads --- .../polyrenderer/backend/poly_framebuffer.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index 3d8b75bd8..37e658d9f 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -147,10 +147,6 @@ void PolyFrameBuffer::Update() Flush3D.Unclock(); FlushDrawCommands(); - DrawerThreads::WaitForWorkers(); - mFrameMemory.Clear(); - FrameDeleteList.Buffers.clear(); - FrameDeleteList.Images.clear(); if (mCanvas) { @@ -162,14 +158,27 @@ void PolyFrameBuffer::Update() uint8_t *dst = I_PolyPresentLock(w, h, pitch); if (dst) { +#if 1 + auto copyqueue = std::make_shared(&mFrameMemory); + copyqueue->Push(dst, pitch / pixelsize, src, w, h, w, pixelsize); + DrawerThreads::Execute(copyqueue); +#else for (int y = 0; y < h; y++) { memcpy(dst + y * pitch, src + y * w * pixelsize, w * pixelsize); } +#endif + + DrawerThreads::WaitForWorkers(); I_PolyPresentUnlock(mOutputLetterbox.left, mOutputLetterbox.top, mOutputLetterbox.width, mOutputLetterbox.height); } } + DrawerThreads::WaitForWorkers(); + mFrameMemory.Clear(); + FrameDeleteList.Buffers.clear(); + FrameDeleteList.Images.clear(); + CheckCanvas(); Super::Update(); From 80805656ed75cb5425239fc8b76973178d8dd4d7 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 31 May 2019 06:43:24 +0200 Subject: [PATCH 23/60] - implement alpha test --- .../polyrenderer/drawers/poly_triangle.cpp | 2 +- .../polyrenderer/drawers/poly_triangle.h | 1 + .../polyrenderer/drawers/screen_triangle.cpp | 719 +++--------------- .../polyrenderer/drawers/screen_triangle.h | 9 +- 4 files changed, 99 insertions(+), 632 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 7ca3628cc..022ca963f 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -347,7 +347,7 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu auto style = RenderStyle; if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero) { - drawargs.SetStyle(AlphaTest ? TriBlendMode::Normal : TriBlendMode::Opaque); + drawargs.SetStyle(AlphaTest ? TriBlendMode::AlphaTest : TriBlendMode::Opaque); } else if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_Src && style.DestAlpha == STYLEALPHA_InvSrc) { diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index ed7d0aaea..f3ffaee7c 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -205,6 +205,7 @@ public: uint16_t lightarray[MAXWIDTH]; uint32_t dynlights[MAXWIDTH]; float depthvalues[MAXWIDTH]; + uint8_t alphatestbuffer[MAXWIDTH]; static PolyTriangleThreadData *Get(DrawerThread *thread); diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 664bd7137..23838bb9c 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -189,6 +189,9 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa uint8_t *stencilLine; int pitch; + bool alphatest = thread->AlphaTest; + uint8_t *alphatestbuf = thread->alphatestbuffer; + if (OptT::Flags & SWTRI_WriteColor) { int bmode = (int)args->uniforms->BlendMode(); @@ -261,14 +264,14 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa stencilLine[x + 2] == stencilTestValue && stencilLine[x + 3] == stencilTestValue) { - if (OptT::Flags & SWTRI_WriteDepth) + if (!alphatest && (OptT::Flags & SWTRI_WriteDepth)) _mm_storeu_ps(zbufferLine + x, mposXW); x += 4; } while (zbufferLine[x] >= depthvalues[x] && stencilLine[x] == stencilTestValue && x < xend) { - if (OptT::Flags & SWTRI_WriteDepth) + if (!alphatest && (OptT::Flags & SWTRI_WriteDepth)) zbufferLine[x] = depthvalues[x]; x++; } @@ -279,14 +282,14 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa __m128 mposXW; while (x < xendsse && _mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 15) { - if (OptT::Flags & SWTRI_WriteDepth) + if (!alphatest && (OptT::Flags & SWTRI_WriteDepth)) _mm_storeu_ps(zbufferLine + x, mposXW); x += 4; } while (zbufferLine[x] >= depthvalues[x] && x < xend) { - if (OptT::Flags & SWTRI_WriteDepth) + if (!alphatest && (OptT::Flags & SWTRI_WriteDepth)) zbufferLine[x] = depthvalues[x]; x++; } @@ -312,25 +315,48 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa if (OptT::Flags & SWTRI_WriteColor) drawfunc(y, xstart, x, args, thread); - if (OptT::Flags & SWTRI_WriteStencil) + if (alphatest) { - int i = xstart; - int xendsse = xstart + ((x - xstart) / 16); - while (i < xendsse) + if (OptT::Flags & SWTRI_WriteStencil) { - _mm_storeu_si128((__m128i*)&stencilLine[i], _mm_set1_epi8(stencilWriteValue)); - i += 16; + for (int i = xstart; i < x; i++) + { + if (alphatestbuf[i] > 127) + stencilLine[i++] = stencilWriteValue; + } } - while (i < x) - stencilLine[i++] = stencilWriteValue; - } - - if (!(OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_WriteDepth)) - { - for (int i = xstart; i < x; i++) + if (OptT::Flags & SWTRI_WriteDepth) { - zbufferLine[i] = depthvalues[i]; + for (int i = xstart; i < x; i++) + { + if (alphatestbuf[i] > 127) + zbufferLine[i] = depthvalues[i]; + } + } + } + else + { + if (OptT::Flags & SWTRI_WriteStencil) + { + int i = xstart; + int xendsse = xstart + ((x - xstart) / 16); + while (i < xendsse) + { + _mm_storeu_si128((__m128i*)&stencilLine[i], _mm_set1_epi8(stencilWriteValue)); + i += 16; + } + + while (i < x) + stencilLine[i++] = stencilWriteValue; + } + + if (!(OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_WriteDepth)) + { + for (int i = xstart; i < x; i++) + { + zbufferLine[i] = depthvalues[i]; + } } } } @@ -391,7 +417,7 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa { while (zbufferLine[x] >= depthvalues[x] && stencilLine[x] == stencilTestValue && x < xend) { - if (OptT::Flags & SWTRI_WriteDepth) + if (!alphatest && (OptT::Flags & SWTRI_WriteDepth)) zbufferLine[x] = depthvalues[x]; x++; } @@ -400,7 +426,7 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa { while (zbufferLine[x] >= depthvalues[x] && x < xend) { - if (OptT::Flags & SWTRI_WriteDepth) + if (!alphatest && (OptT::Flags & SWTRI_WriteDepth)) zbufferLine[x] = depthvalues[x]; x++; } @@ -420,17 +446,40 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa if (OptT::Flags & SWTRI_WriteColor) drawfunc(y, xstart, x, args, thread); - if (OptT::Flags & SWTRI_WriteStencil) + if (alphatest) { - for (int i = xstart; i < x; i++) - stencilLine[i] = stencilWriteValue; - } - - if (!(OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_WriteDepth)) - { - for (int i = xstart; i < x; i++) + if (OptT::Flags & SWTRI_WriteStencil) { - zbufferLine[i] = depthvalues[i]; + for (int i = xstart; i < x; i++) + { + if (alphatestbuf[i] > 127) + stencilLine[i++] = stencilWriteValue; + } + } + + if (OptT::Flags & SWTRI_WriteDepth) + { + for (int i = xstart; i < x; i++) + { + if (alphatestbuf[i] > 127) + zbufferLine[i] = depthvalues[i]; + } + } + } + else + { + if (OptT::Flags & SWTRI_WriteStencil) + { + for (int i = xstart; i < x; i++) + stencilLine[i] = stencilWriteValue; + } + + if (!(OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_WriteDepth)) + { + for (int i = xstart; i < x; i++) + { + zbufferLine[i] = depthvalues[i]; + } } } } @@ -841,6 +890,7 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyT const uint32_t *texPixels, *translation; uint32_t fillcolor; int actoralpha; + uint8_t *alphatestbuf; uint32_t *texel = thread->texel; int32_t *texelV = thread->texelV; @@ -891,6 +941,11 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyT _fuzzpos = swrenderer::fuzzpos; } + if (ModeT::SWFlags & SWSTYLEF_AlphaTest) + { + alphatestbuf = thread->alphatestbuffer; + } + uint32_t *dest = (uint32_t*)thread->dest; uint32_t *destLine = dest + thread->dest_pitch * y; @@ -904,7 +959,8 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyT !(ModeT::Flags & STYLEF_RedIsAlpha) && !(ModeT::SWFlags & SWSTYLEF_Skycap) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary) && - !(ModeT::SWFlags & SWSTYLEF_Fill)) + !(ModeT::SWFlags & SWSTYLEF_Fill) && + !(ModeT::SWFlags & SWSTYLEF_AlphaTest)) { sseend += (x1 - x0) / 2 * 2; @@ -1064,6 +1120,11 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyT fgalpha = (fgalpha * actoralpha) >> 8; } + if (ModeT::SWFlags & SWSTYLEF_AlphaTest) + { + alphatestbuf[x] = fgalpha; + } + uint32_t lightshade; if (OptT::Flags & SWOPT_FixedLight) { @@ -1591,536 +1652,6 @@ 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) -{ - using namespace TriScreenDrawerModes; - - int x0 = clamp((int)(args->X0() + 0.5f), 0, destWidth); - int x1 = clamp((int)(args->X1() + 0.5f), 0, destWidth); - int y0 = clamp((int)(args->Y0() + 0.5f), 0, destHeight); - int y1 = clamp((int)(args->Y1() + 0.5f), 0, destHeight); - - if (x1 <= x0 || y1 <= y0) - return; - - const uint8_t *colormaps, *texPixels, *translation; - int texWidth, texHeight; - uint32_t fillcolor; - int alpha; - uint32_t light; - - texPixels = args->TexturePixels(); - translation = args->Translation(); - texWidth = args->TextureWidth(); - texHeight = args->TextureHeight(); - fillcolor = args->Color(); - alpha = args->Alpha(); - colormaps = args->BaseColormap(); - light = args->Light(); - light += light >> 7; // 255 -> 256 - light = ((256 - light) * NUMCOLORMAPS) & 0xffffff00; - - fixed_t fuzzscale; - int _fuzzpos; - if (ModeT::BlendOp == STYLEOP_Fuzz) - { - fuzzscale = (200 << FRACBITS) / thread->dest_height; - _fuzzpos = swrenderer::fuzzpos; - } - - float fstepU = (args->U1() - args->U0()) / (args->X1() - args->X0()); - float fstepV = (args->V1() - args->V0()) / (args->Y1() - args->Y0()); - uint32_t startU = (int32_t)((args->U0() + (x0 + 0.5f - args->X0()) * fstepU) * 0x1000000); - uint32_t startV = (int32_t)((args->V0() + (y0 + 0.5f - args->Y0()) * fstepV) * 0x1000000); - uint32_t stepU = (int32_t)(fstepU * 0x1000000); - uint32_t stepV = (int32_t)(fstepV * 0x1000000); - - uint32_t posV = startV; - y1 = MIN(y1, thread->numa_end_y); - int num_cores = thread->num_cores; - int skip = thread->skipped_by_thread(y0); - posV += skip * stepV; - stepV *= num_cores; - for (int y = y0 + skip; y < y1; y += num_cores, posV += stepV) - { - uint8_t *destLine = ((uint8_t*)destOrg) + y * destPitch; - - uint32_t posU = startU; - for (int x = x0; x < x1; x++) - { - if (ModeT::BlendOp == STYLEOP_Fuzz) - { - using namespace swrenderer; - - uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16; - unsigned int sampleshadeout = (texPixels[texelX * texHeight + texelY] != 0) ? 256 : 0; - - int scaled_x = (x * fuzzscale) >> FRACBITS; - int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + _fuzzpos; - - fixed_t fuzzcount = FUZZTABLE << FRACBITS; - fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount; - unsigned int alpha = fuzzoffset[fuzz >> FRACBITS]; - - sampleshadeout = (sampleshadeout * alpha) >> 5; - - uint32_t a = 256 - sampleshadeout; - - uint32_t dest = GPalette.BaseColors[destLine[x]].d; - uint32_t r = (RPART(dest) * a) >> 8; - uint32_t g = (GPART(dest) * a) >> 8; - uint32_t b = (BPART(dest) * a) >> 8; - destLine[x] = RGB256k.All[((r >> 2) << 12) | ((g >> 2) << 6) | (b >> 2)]; - } - else - { - int fg = 0; - if (ModeT::SWFlags & SWSTYLEF_Fill) - { - fg = fillcolor; - } - else - { - uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16; - fg = texPixels[texelX * texHeight + texelY]; - } - - int fgalpha = 255; - - if (ModeT::BlendDest == STYLEALPHA_InvSrc) - { - if (fg == 0) - fgalpha = 0; - } - - if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill)) - { - if (ModeT::Flags & STYLEF_RedIsAlpha) - fgalpha = fg; - fg = fillcolor; - } - - if (!(ModeT::Flags & STYLEF_Alpha1)) - { - fgalpha = (fgalpha * alpha) >> 8; - } - - if (ModeT::SWFlags & SWSTYLEF_Translated) - fg = translation[fg]; - - uint8_t shadedfg = colormaps[light + fg]; - - if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero) - { - destLine[x] = shadedfg; - } - else if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_One) - { - uint32_t src = GPalette.BaseColors[shadedfg]; - uint32_t dest = GPalette.BaseColors[destLine[x]]; - - if (ModeT::BlendOp == STYLEOP_Add) - { - uint32_t out_r = MIN(RPART(dest) + RPART(src), 255); - uint32_t out_g = MIN(GPART(dest) + GPART(src), 255); - uint32_t out_b = MIN(BPART(dest) + BPART(src), 255); - destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; - } - else if (ModeT::BlendOp == STYLEOP_RevSub) - { - uint32_t out_r = MAX(RPART(dest) - RPART(src), 0); - uint32_t out_g = MAX(GPART(dest) - GPART(src), 0); - uint32_t out_b = MAX(BPART(dest) - BPART(src), 0); - destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; - } - else //if (ModeT::BlendOp == STYLEOP_Sub) - { - uint32_t out_r = MAX(RPART(src) - RPART(dest), 0); - uint32_t out_g = MAX(GPART(src) - GPART(dest), 0); - uint32_t out_b = MAX(BPART(src) - BPART(dest), 0); - destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; - } - } - else if (ModeT::SWFlags & SWSTYLEF_SrcColorOneMinusSrcColor) - { - uint32_t src = GPalette.BaseColors[shadedfg]; - uint32_t dest = GPalette.BaseColors[destLine[x]]; - - uint32_t sfactor_r = RPART(src); sfactor_r += sfactor_r >> 7; // 255 -> 256 - uint32_t sfactor_g = GPART(src); sfactor_g += sfactor_g >> 7; // 255 -> 256 - uint32_t sfactor_b = BPART(src); sfactor_b += sfactor_b >> 7; // 255 -> 256 - uint32_t sfactor_a = fgalpha; sfactor_a += sfactor_a >> 7; // 255 -> 256 - uint32_t dfactor_r = 256 - sfactor_r; - uint32_t dfactor_g = 256 - sfactor_g; - uint32_t dfactor_b = 256 - sfactor_b; - uint32_t out_r = (RPART(dest) * dfactor_r + RPART(src) * sfactor_r + 128) >> 8; - uint32_t out_g = (GPART(dest) * dfactor_g + GPART(src) * sfactor_g + 128) >> 8; - uint32_t out_b = (BPART(dest) * dfactor_b + BPART(src) * sfactor_b + 128) >> 8; - - destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; - } - else if (ModeT::BlendSrc == STYLEALPHA_Src && ModeT::BlendDest == STYLEALPHA_InvSrc && fgalpha == 255) - { - destLine[x] = shadedfg; - } - else if (ModeT::BlendSrc != STYLEALPHA_Src || ModeT::BlendDest != STYLEALPHA_InvSrc || fgalpha != 0) - { - uint32_t src = GPalette.BaseColors[shadedfg]; - uint32_t dest = GPalette.BaseColors[destLine[x]]; - - uint32_t sfactor = fgalpha; sfactor += sfactor >> 7; // 255 -> 256 - uint32_t dfactor = 256 - sfactor; - uint32_t src_r = RPART(src) * sfactor; - uint32_t src_g = GPART(src) * sfactor; - uint32_t src_b = BPART(src) * sfactor; - uint32_t dest_r = RPART(dest); - uint32_t dest_g = GPART(dest); - uint32_t dest_b = BPART(dest); - if (ModeT::BlendDest == STYLEALPHA_One) - { - dest_r <<= 8; - dest_g <<= 8; - dest_b <<= 8; - } - else - { - uint32_t dfactor = 256 - sfactor; - dest_r *= dfactor; - dest_g *= dfactor; - dest_b *= dfactor; - } - - uint32_t out_r, out_g, out_b; - if (ModeT::BlendOp == STYLEOP_Add) - { - if (ModeT::BlendDest == STYLEALPHA_One) - { - out_r = MIN((dest_r + src_r + 128) >> 8, 255); - out_g = MIN((dest_g + src_g + 128) >> 8, 255); - out_b = MIN((dest_b + src_b + 128) >> 8, 255); - } - else - { - out_r = (dest_r + src_r + 128) >> 8; - out_g = (dest_g + src_g + 128) >> 8; - out_b = (dest_b + src_b + 128) >> 8; - } - } - else if (ModeT::BlendOp == STYLEOP_RevSub) - { - out_r = MAX(static_cast(dest_r - src_r + 128) >> 8, 0); - out_g = MAX(static_cast(dest_g - src_g + 128) >> 8, 0); - out_b = MAX(static_cast(dest_b - src_b + 128) >> 8, 0); - } - else //if (ModeT::BlendOp == STYLEOP_Sub) - { - out_r = MAX(static_cast(src_r - dest_r + 128) >> 8, 0); - out_g = MAX(static_cast(src_g - dest_g + 128) >> 8, 0); - out_b = MAX(static_cast(src_b - dest_b + 128) >> 8, 0); - } - - destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; - } - } - - posU += stepU; - } - } -} - -template -void DrawRectOpt32(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread) -{ - using namespace TriScreenDrawerModes; - - int x0 = clamp((int)(args->X0() + 0.5f), 0, destWidth); - int x1 = clamp((int)(args->X1() + 0.5f), 0, destWidth); - int y0 = clamp((int)(args->Y0() + 0.5f), 0, destHeight); - int y1 = clamp((int)(args->Y1() + 0.5f), 0, destHeight); - - if (x1 <= x0 || y1 <= y0) - return; - - const uint32_t *texPixels, *translation; - int texWidth, texHeight; - uint32_t fillcolor; - int alpha; - uint32_t light; - uint32_t shade_fade_r, shade_fade_g, shade_fade_b, shade_light_r, shade_light_g, shade_light_b, desaturate, inv_desaturate; - - texPixels = (const uint32_t*)args->TexturePixels(); - translation = (const uint32_t*)args->Translation(); - texWidth = args->TextureWidth(); - texHeight = args->TextureHeight(); - fillcolor = args->Color(); - alpha = args->Alpha(); - light = args->Light(); - light += light >> 7; // 255 -> 256 - - if (OptT::Flags & SWOPT_ColoredFog) - { - shade_fade_r = args->ShadeFadeRed(); - shade_fade_g = args->ShadeFadeGreen(); - shade_fade_b = args->ShadeFadeBlue(); - shade_light_r = args->ShadeLightRed(); - shade_light_g = args->ShadeLightGreen(); - shade_light_b = args->ShadeLightBlue(); - desaturate = args->ShadeDesaturate(); - inv_desaturate = 256 - desaturate; - } - - fixed_t fuzzscale; - int _fuzzpos; - if (ModeT::BlendOp == STYLEOP_Fuzz) - { - fuzzscale = (200 << FRACBITS) / thread->dest_height; - _fuzzpos = swrenderer::fuzzpos; - } - - float fstepU = (args->U1() - args->U0()) / (args->X1() - args->X0()); - float fstepV = (args->V1() - args->V0()) / (args->Y1() - args->Y0()); - uint32_t startU = (int32_t)((args->U0() + (x0 + 0.5f - args->X0()) * fstepU) * 0x1000000); - uint32_t startV = (int32_t)((args->V0() + (y0 + 0.5f - args->Y0()) * fstepV) * 0x1000000); - uint32_t stepU = (int32_t)(fstepU * 0x1000000); - uint32_t stepV = (int32_t)(fstepV * 0x1000000); - - uint32_t posV = startV; - y1 = MIN(y1, thread->numa_end_y); - int num_cores = thread->num_cores; - int skip = thread->skipped_by_thread(y0); - posV += skip * stepV; - stepV *= num_cores; - for (int y = y0 + skip; y < y1; y += num_cores, posV += stepV) - { - uint32_t *destLine = ((uint32_t*)destOrg) + y * destPitch; - - uint32_t posU = startU; - for (int x = x0; x < x1; x++) - { - if (ModeT::BlendOp == STYLEOP_Fuzz) - { - using namespace swrenderer; - - uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16; - unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]); - sampleshadeout += sampleshadeout >> 7; // 255 -> 256 - - int scaled_x = (x * fuzzscale) >> FRACBITS; - int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + _fuzzpos; - - fixed_t fuzzcount = FUZZTABLE << FRACBITS; - fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount; - unsigned int alpha = fuzzoffset[fuzz >> FRACBITS]; - - sampleshadeout = (sampleshadeout * alpha) >> 5; - - uint32_t a = 256 - sampleshadeout; - - uint32_t dest = destLine[x]; - uint32_t out_r = (RPART(dest) * a) >> 8; - uint32_t out_g = (GPART(dest) * a) >> 8; - uint32_t out_b = (BPART(dest) * a) >> 8; - destLine[x] = MAKEARGB(255, out_r, out_g, out_b); - } - else - { - uint32_t fg = 0; - - if (ModeT::SWFlags & SWSTYLEF_Fill) - { - fg = fillcolor; - } - else if (ModeT::SWFlags & SWSTYLEF_FogBoundary) - { - fg = destLine[x]; - } - else - { - uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16; - - if (ModeT::SWFlags & SWSTYLEF_Translated) - { - fg = translation[((const uint8_t*)texPixels)[texelX * texHeight + texelY]]; - } - else if (ModeT::Flags & STYLEF_RedIsAlpha) - { - fg = ((const uint8_t*)texPixels)[texelX * texHeight + texelY]; - } - else - { - fg = texPixels[texelX * texHeight + texelY]; - } - } - - if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill)) - { - if (ModeT::Flags & STYLEF_RedIsAlpha) - fg = (fg << 24) | (fillcolor & 0x00ffffff); - else - fg = (fg & 0xff000000) | (fillcolor & 0x00ffffff); - } - - uint32_t fgalpha = fg >> 24; - - if (!(ModeT::Flags & STYLEF_Alpha1)) - { - fgalpha = (fgalpha * alpha) >> 8; - } - - int lightshade = light; - - uint32_t lit_r = 0, lit_g = 0, lit_b = 0; - - uint32_t shadedfg_r, shadedfg_g, shadedfg_b; - if (OptT::Flags & SWOPT_ColoredFog) - { - uint32_t fg_r = RPART(fg); - uint32_t fg_g = GPART(fg); - uint32_t fg_b = BPART(fg); - uint32_t intensity = ((fg_r * 77 + fg_g * 143 + fg_b * 37) >> 8) * desaturate; - shadedfg_r = (((shade_fade_r + ((fg_r * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_r) >> 8; - shadedfg_g = (((shade_fade_g + ((fg_g * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_g) >> 8; - shadedfg_b = (((shade_fade_b + ((fg_b * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_b) >> 8; - } - else - { - shadedfg_r = (RPART(fg) * lightshade) >> 8; - shadedfg_g = (GPART(fg) * lightshade) >> 8; - shadedfg_b = (BPART(fg) * lightshade) >> 8; - } - - if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero) - { - destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b); - } - else if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_One) - { - uint32_t dest = destLine[x]; - - if (ModeT::BlendOp == STYLEOP_Add) - { - uint32_t out_r = MIN(RPART(dest) + shadedfg_r, 255); - uint32_t out_g = MIN(GPART(dest) + shadedfg_g, 255); - uint32_t out_b = MIN(BPART(dest) + shadedfg_b, 255); - destLine[x] = MAKEARGB(255, out_r, out_g, out_b); - } - else if (ModeT::BlendOp == STYLEOP_RevSub) - { - uint32_t out_r = MAX(RPART(dest) - shadedfg_r, 0); - uint32_t out_g = MAX(GPART(dest) - shadedfg_g, 0); - uint32_t out_b = MAX(BPART(dest) - shadedfg_b, 0); - destLine[x] = MAKEARGB(255, out_r, out_g, out_b); - } - else //if (ModeT::BlendOp == STYLEOP_Sub) - { - uint32_t out_r = MAX(shadedfg_r - RPART(dest), 0); - uint32_t out_g = MAX(shadedfg_g - GPART(dest), 0); - uint32_t out_b = MAX(shadedfg_b - BPART(dest), 0); - destLine[x] = MAKEARGB(255, out_r, out_g, out_b); - } - } - else if (ModeT::SWFlags & SWSTYLEF_SrcColorOneMinusSrcColor) - { - uint32_t dest = destLine[x]; - - uint32_t sfactor_r = shadedfg_r; sfactor_r += sfactor_r >> 7; // 255 -> 256 - uint32_t sfactor_g = shadedfg_g; sfactor_g += sfactor_g >> 7; // 255 -> 256 - uint32_t sfactor_b = shadedfg_b; sfactor_b += sfactor_b >> 7; // 255 -> 256 - uint32_t sfactor_a = fgalpha; sfactor_a += sfactor_a >> 7; // 255 -> 256 - uint32_t dfactor_r = 256 - sfactor_r; - uint32_t dfactor_g = 256 - sfactor_g; - uint32_t dfactor_b = 256 - sfactor_b; - uint32_t out_r = (RPART(dest) * dfactor_r + shadedfg_r * sfactor_r + 128) >> 8; - uint32_t out_g = (GPART(dest) * dfactor_g + shadedfg_g * sfactor_g + 128) >> 8; - uint32_t out_b = (BPART(dest) * dfactor_b + shadedfg_b * sfactor_b + 128) >> 8; - - destLine[x] = MAKEARGB(255, out_r, out_g, out_b); - } - else if (ModeT::BlendSrc == STYLEALPHA_Src && ModeT::BlendDest == STYLEALPHA_InvSrc && fgalpha == 255) - { - destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b); - } - else if (ModeT::BlendSrc != STYLEALPHA_Src || ModeT::BlendDest != STYLEALPHA_InvSrc || fgalpha != 0) - { - uint32_t dest = destLine[x]; - - uint32_t sfactor = fgalpha; sfactor += sfactor >> 7; // 255 -> 256 - uint32_t src_r = shadedfg_r * sfactor; - uint32_t src_g = shadedfg_g * sfactor; - uint32_t src_b = shadedfg_b * sfactor; - uint32_t dest_r = RPART(dest); - uint32_t dest_g = GPART(dest); - uint32_t dest_b = BPART(dest); - if (ModeT::BlendDest == STYLEALPHA_One) - { - dest_r <<= 8; - dest_g <<= 8; - dest_b <<= 8; - } - else - { - uint32_t dfactor = 256 - sfactor; - dest_r *= dfactor; - dest_g *= dfactor; - dest_b *= dfactor; - } - - uint32_t out_r, out_g, out_b; - if (ModeT::BlendOp == STYLEOP_Add) - { - if (ModeT::BlendDest == STYLEALPHA_One) - { - out_r = MIN((dest_r + src_r + 128) >> 8, 255); - out_g = MIN((dest_g + src_g + 128) >> 8, 255); - out_b = MIN((dest_b + src_b + 128) >> 8, 255); - } - else - { - out_r = (dest_r + src_r + 128) >> 8; - out_g = (dest_g + src_g + 128) >> 8; - out_b = (dest_b + src_b + 128) >> 8; - } - } - else if (ModeT::BlendOp == STYLEOP_RevSub) - { - out_r = MAX(static_cast(dest_r - src_r + 128) >> 8, 0); - out_g = MAX(static_cast(dest_g - src_g + 128) >> 8, 0); - out_b = MAX(static_cast(dest_b - src_b + 128) >> 8, 0); - } - else //if (ModeT::BlendOp == STYLEOP_Sub) - { - out_r = MAX(static_cast(src_r - dest_r + 128) >> 8, 0); - out_g = MAX(static_cast(src_g - dest_g + 128) >> 8, 0); - out_b = MAX(static_cast(src_b - dest_b + 128) >> 8, 0); - } - - destLine[x] = MAKEARGB(255, out_r, out_g, out_b); - } - } - - posU += stepU; - } - } -} - -template -void DrawRect32(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread) -{ - using namespace TriScreenDrawerModes; - - if (args->SimpleShade()) - DrawRectOpt32(destOrg, destWidth, destHeight, destPitch, args, thread); - else - DrawRectOpt32(destOrg, destWidth, destHeight, destPitch, args, thread); -} -#endif - void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *, PolyTriangleThreadData *) = { &DrawSpan8, @@ -2130,6 +1661,7 @@ void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs * &DrawSpan8, &DrawSpan8, &DrawSpan8, + &DrawSpan8, &DrawSpan8, &DrawSpan8, &DrawSpan8, @@ -2163,6 +1695,7 @@ void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs &DrawSpan32, &DrawSpan32, &DrawSpan32, + &DrawSpan32, &DrawSpan32, &DrawSpan32, &DrawSpan32, @@ -2187,72 +1720,6 @@ void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs &DrawSpan32 }; -#if 0 -void(*ScreenTriangle::RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *) = -{ - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8, - &DrawRect8 -}; - -void(*ScreenTriangle::RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *) = -{ - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32, - &DrawRect32 -}; -#endif - void(*ScreenTriangle::TriangleDrawers[])(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread, int16_t *edges, int topY, int bottomY) = { &DrawTriangle, diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.h b/src/rendering/polyrenderer/drawers/screen_triangle.h index 3e9bef620..151cdfcea 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.h +++ b/src/rendering/polyrenderer/drawers/screen_triangle.h @@ -106,6 +106,7 @@ enum class TriBlendMode Fill, FillTranslucent, Normal, + AlphaTest, Fuzzy, Stencil, Translucent, @@ -139,10 +140,6 @@ 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; }; @@ -155,7 +152,8 @@ namespace TriScreenDrawerModes SWSTYLEF_Skycap = 2, SWSTYLEF_FogBoundary = 4, SWSTYLEF_Fill = 8, - SWSTYLEF_SrcColorOneMinusSrcColor = 16 + SWSTYLEF_SrcColorOneMinusSrcColor = 16, + SWSTYLEF_AlphaTest = 32 }; struct StyleOpaque { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = 0; }; @@ -166,6 +164,7 @@ namespace TriScreenDrawerModes struct StyleFillTranslucent { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Fill; }; struct StyleNormal { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = 0; }; + struct StyleAlphaTest { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_AlphaTest; }; struct StyleFuzzy { static const int BlendOp = STYLEOP_Fuzz, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; }; struct StyleStencil { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1 | STYLEF_ColorIsFixed, SWFlags = 0; }; struct StyleTranslucent { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; }; From 91ec1463b87a26f3f0394743b1dd9d199cb7c51e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 31 May 2019 08:49:08 +0200 Subject: [PATCH 24/60] - add line drawer --- .../polyrenderer/backend/poly_renderstate.cpp | 10 +- .../polyrenderer/drawers/poly_draw_args.h | 2 + .../polyrenderer/drawers/poly_triangle.cpp | 144 +++++++++++++++++- .../polyrenderer/drawers/poly_triangle.h | 2 + 4 files changed, 151 insertions(+), 7 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 25690564e..4adf4a59b 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -17,11 +17,11 @@ static PolyDrawMode dtToDrawMode[] = { - PolyDrawMode::Triangles, // DT_Points - PolyDrawMode::Triangles, // DT_Lines - PolyDrawMode::Triangles, // DT_Triangles - PolyDrawMode::TriangleFan, // DT_TriangleFan - PolyDrawMode::TriangleStrip, // DT_TriangleStrip + PolyDrawMode::Points, + PolyDrawMode::Lines, + PolyDrawMode::Triangles, + PolyDrawMode::TriangleFan, + PolyDrawMode::TriangleStrip, }; PolyRenderState::PolyRenderState() diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.h b/src/rendering/polyrenderer/drawers/poly_draw_args.h index 83df64421..3a15c3a31 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.h +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.h @@ -32,6 +32,8 @@ class Mat4f; enum class PolyDrawMode { + Points, + Lines, Triangles, TriangleFan, TriangleStrip diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 022ca963f..c9584b187 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -520,7 +520,7 @@ void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode dra std::swap(vert[1], vert[2]); } } - else // TriangleDrawMode::TriangleStrip + else if (drawmode == PolyDrawMode::TriangleStrip) { bool toggleccw = ccw; *vert[0] = ShadeVertex(*(elements++)); @@ -536,6 +536,23 @@ void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode dra toggleccw = !toggleccw; } } + else if (drawmode == PolyDrawMode::Lines) + { + for (int i = 0; i < vcount / 2; i++) + { + *vert[0] = ShadeVertex(*(elements++)); + *vert[1] = ShadeVertex(*(elements++)); + DrawShadedLine(vert); + } + } + else if (drawmode == PolyDrawMode::Points) + { + for (int i = 0; i < vcount; i++) + { + *vert[0] = ShadeVertex(*(elements++)); + DrawShadedPoint(vert); + } + } } void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode) @@ -570,7 +587,7 @@ void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode) std::swap(vert[1], vert[2]); } } - else // TriangleDrawMode::TriangleStrip + else if (drawmode == PolyDrawMode::TriangleStrip) { bool toggleccw = ccw; *vert[0] = ShadeVertex(vinput++); @@ -586,6 +603,23 @@ void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode) toggleccw = !toggleccw; } } + else if (drawmode == PolyDrawMode::Lines) + { + for (int i = 0; i < vcount / 2; i++) + { + *vert[0] = ShadeVertex(vinput++); + *vert[1] = ShadeVertex(vinput++); + DrawShadedLine(vert); + } + } + else if (drawmode == PolyDrawMode::Points) + { + for (int i = 0; i < vcount; i++) + { + *vert[0] = ShadeVertex(vinput++); + DrawShadedPoint(vert); + } + } } ShadedTriVertex PolyTriangleThreadData::ShadeVertex(int index) @@ -647,6 +681,112 @@ bool PolyTriangleThreadData::IsFrontfacing(TriDrawTriangleArgs *args) return a <= 0.0f; } +void PolyTriangleThreadData::DrawShadedPoint(const ShadedTriVertex *const* vertex) +{ +} + +void PolyTriangleThreadData::DrawShadedLine(const ShadedTriVertex *const* vert) +{ + static const int numclipdistances = 9; + float clipdistance[numclipdistances * 2]; + float *clipd = clipdistance; + for (int i = 0; i < 2; i++) + { + const auto &v = *vert[i]; + clipd[0] = v.gl_Position.X + v.gl_Position.W; + clipd[1] = v.gl_Position.W - v.gl_Position.X; + clipd[2] = v.gl_Position.Y + v.gl_Position.W; + clipd[3] = v.gl_Position.W - v.gl_Position.Y; + clipd[4] = v.gl_Position.Z + v.gl_Position.W; + clipd[5] = v.gl_Position.W - v.gl_Position.Z; + clipd[6] = v.gl_ClipDistance[0]; + clipd[7] = v.gl_ClipDistance[1]; + clipd[8] = v.gl_ClipDistance[2]; + clipd += numclipdistances; + } + + float t1 = 0.0f; + float t2 = 1.0f; + for (int p = 0; p < numclipdistances; p++) + { + float clipdistance1 = clipdistance[0 * numclipdistances + p]; + float clipdistance2 = clipdistance[1 * numclipdistances + p]; + if (clipdistance1 < 0.0f) t1 = MAX(-clipdistance1 / (clipdistance2 - clipdistance1), t1); + if (clipdistance2 < 0.0f) t2 = MIN(1.0f + clipdistance2 / (clipdistance1 - clipdistance2), t2); + if (t1 >= t2) + return; + } + + float weights[] = { 1.0f - t1, t1, 1.0f - t2, t2 }; + + ScreenTriVertex clippedvert[2]; + for (int i = 0; i < 2; i++) + { + auto &v = clippedvert[i]; + memset(&v, 0, sizeof(ScreenTriVertex)); + for (int w = 0; w < 2; w++) + { + float weight = weights[i * 2 + w]; + v.x += vert[w]->gl_Position.X * weight; + v.y += vert[w]->gl_Position.Y * weight; + v.z += vert[w]->gl_Position.Z * weight; + v.w += vert[w]->gl_Position.W * weight; + v.u += vert[w]->vTexCoord.X * weight; + v.v += vert[w]->vTexCoord.Y * weight; + v.worldX += vert[w]->pixelpos.X * weight; + v.worldY += vert[w]->pixelpos.Y * weight; + v.worldZ += vert[w]->pixelpos.Z * weight; + } + + // Calculate normalized device coordinates: + v.w = 1.0f / v.w; + v.x *= v.w; + v.y *= v.w; + v.z *= v.w; + + // Apply viewport scale to get screen coordinates: + v.x = viewport_x + viewport_width * (1.0f + v.x) * 0.5f; + v.y = viewport_y + viewport_height * (1.0f - v.y) * 0.5f; + } + + uint32_t color = vert[0]->vColor; + + // Slow and naive implementation. Hopefully fast enough.. + + float x1 = clippedvert[0].x; + float y1 = clippedvert[0].y; + float x2 = clippedvert[1].x; + float y2 = clippedvert[1].y; + float dx = x2 - x1; + float dy = y2 - y1; + float step = (abs(dx) >= abs(dy)) ? abs(dx) : abs(dy); + dx /= step; + dy /= step; + float x = x1; + float y = y1; + int istep = (int)step; + int pixelsize = dest_bgra ? 4 : 1; + for (int i = 0; i <= istep; i++) + { + int scrx = (int)x; + int scry = (int)y; + if (scrx >= clip.left && scrx < clip.right && scry >= clip.top && scry < clip.bottom && !line_skipped_by_thread(scry)) + { + uint8_t *destpixel = dest + (scrx + scry * dest_width) * pixelsize; + if (pixelsize == 4) + { + *reinterpret_cast(destpixel) = color; + } + else + { + *destpixel = color; + } + } + x += dx; + y += dy; + } +} + void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* vert, bool ccw, TriDrawTriangleArgs *args) { // Reject triangle if degenerate diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index f3ffaee7c..683ebbd40 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -246,6 +246,8 @@ public: private: ShadedTriVertex ShadeVertex(int index); + void DrawShadedPoint(const ShadedTriVertex *const* vertex); + void DrawShadedLine(const ShadedTriVertex *const* vertices); void DrawShadedTriangle(const ShadedTriVertex *const* vertices, bool ccw, TriDrawTriangleArgs *args); static bool IsDegenerate(const ShadedTriVertex *const* vertices); static bool IsFrontfacing(TriDrawTriangleArgs *args); From 5dd06de48c89946c7d0959f3721c722b29ca2ce1 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 10 Jun 2019 22:46:13 +0200 Subject: [PATCH 25/60] - fix compile error --- src/rendering/polyrenderer/backend/poly_framebuffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index 37e658d9f..a74e15f5f 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -55,7 +55,7 @@ void I_PolyPresentDeinit(); #else void I_PolyPresentInit() { } uint8_t *I_PolyPresentLock(int w, int h, int &pitch) { pitch = 0; return nullptr; } -void I_PolyPresentUnlock() { } +void I_PolyPresentUnlock(int x, int y, int w, int h) { } void I_PolyPresentDeinit() { } #endif From 82ebcc494663e04f1b958ce66c3a0e267619c4cc Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 10 Jun 2019 23:00:15 +0200 Subject: [PATCH 26/60] - fix compile errors --- .../polyrenderer/backend/poly_buffers.cpp | 9 ++---- .../polyrenderer/backend/poly_buffers.h | 3 +- .../polyrenderer/backend/poly_framebuffer.cpp | 32 +++++++++---------- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_buffers.cpp b/src/rendering/polyrenderer/backend/poly_buffers.cpp index 526c5279c..d99056b9c 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.cpp +++ b/src/rendering/polyrenderer/backend/poly_buffers.cpp @@ -113,12 +113,7 @@ void PolyVertexInputAssembly::Load(PolyTriangleThreadData *thread, const void *v ///////////////////////////////////////////////////////////////////////////// -void PolyDataBuffer::BindRange(size_t start, size_t length) +void PolyDataBuffer::BindRange(FRenderState *state, size_t start, size_t length) { - GetPolyFrameBuffer()->GetRenderState()->Bind(this, (uint32_t)start, (uint32_t)length); -} - -void PolyDataBuffer::BindBase() -{ - GetPolyFrameBuffer()->GetRenderState()->Bind(this, 0, (uint32_t)buffersize); + static_cast(state)->Bind(this, (uint32_t)start, (uint32_t)length); } diff --git a/src/rendering/polyrenderer/backend/poly_buffers.h b/src/rendering/polyrenderer/backend/poly_buffers.h index 1d8c38e82..53585e95e 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.h +++ b/src/rendering/polyrenderer/backend/poly_buffers.h @@ -75,8 +75,7 @@ public: { } - void BindRange(size_t start, size_t length) override; - void BindBase() override; + void BindRange(FRenderState *state, size_t start, size_t length) override; int bindingpoint; }; diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index a74e15f5f..c5b689abe 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -87,7 +87,7 @@ PolyFrameBuffer::~PolyFrameBuffer() void PolyFrameBuffer::InitializeState() { - gl_vendorstring = "Poly"; + vendorstring = "Poly"; hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE; glslversion = 4.50f; uniformblockalignment = 1; @@ -97,7 +97,7 @@ void PolyFrameBuffer::InitializeState() mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight()); mSkyData = new FSkyVertexBuffer; - mViewpoints = new GLViewpointBuffer; + mViewpoints = new HWViewpointBuffer; mLights = new FLightBuffer(); CheckCanvas(); @@ -200,8 +200,8 @@ sector_t *PolyFrameBuffer::RenderView(player_t *player) { // To do: this is virtually identical to FGLRenderer::RenderView and should be merged. - mRenderState->SetVertexBuffer(screen->mVertexData); - screen->mVertexData->Reset(); + mRenderState->SetVertexBuffer(mVertexData); + mVertexData->Reset(); sector_t *retsec; if (!V_IsHardwareRenderer()) @@ -224,8 +224,8 @@ sector_t *PolyFrameBuffer::RenderView(player_t *player) if (cl_capfps || r_NoInterpolate) r_viewpoint.TicFrac = 1.; else r_viewpoint.TicFrac = I_GetTimeFrac(); - screen->mLights->Clear(); - screen->mViewpoints->Clear(); + mLights->Clear(); + mViewpoints->Clear(); // NoInterpolateView should have no bearing on camera textures, but needs to be preserved for the main view below. bool saved_niv = NoInterpolateView; @@ -281,7 +281,7 @@ sector_t *PolyFrameBuffer::RenderViewpoint(FRenderViewpoint &mainvp, AActor * ca for (int eye_ix = 0; eye_ix < vrmode->mEyeCount; ++eye_ix) { const auto &eye = vrmode->mEyes[eye_ix]; - screen->SetViewportRects(bounds); + SetViewportRects(bounds); if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao { @@ -400,20 +400,20 @@ void PolyFrameBuffer::DrawScene(HWDrawInfo *di, int drawmode) } GetRenderState()->SetDepthMask(true); - if (!gl_no_skyclear) screen->mPortalState->RenderFirstSkyPortal(recursion, di, *GetRenderState()); + if (!gl_no_skyclear) mPortalState->RenderFirstSkyPortal(recursion, di, *GetRenderState()); di->RenderScene(*GetRenderState()); if (applySSAO && GetRenderState()->GetPassType() == GBUFFER_PASS) { //mPostprocess->AmbientOccludeScene(di->VPUniforms.mProjectionMatrix.get()[5]); - //screen->mViewpoints->Bind(*GetRenderState(), di->vpIndex); + //mViewpoints->Bind(*GetRenderState(), di->vpIndex); } // Handle all portals after rendering the opaque objects but before // doing all translucent stuff recursion++; - screen->mPortalState->EndFrame(di, *GetRenderState()); + mPortalState->EndFrame(di, *GetRenderState()); recursion--; di->RenderTranslucent(*GetRenderState()); } @@ -511,11 +511,12 @@ void PolyFrameBuffer::UpdatePalette() FTexture *PolyFrameBuffer::WipeStartScreen() { - const auto &viewport = screen->mScreenViewport; - auto tex = new FWrapperTexture(viewport.width, viewport.height, 1); + SetViewportRects(nullptr); + + auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1); auto systex = static_cast(tex->GetSystemTexture()); - systex->CreateWipeTexture(viewport.width, viewport.height, "WipeStartScreen"); + systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeStartScreen"); return tex; } @@ -525,11 +526,10 @@ FTexture *PolyFrameBuffer::WipeEndScreen() Draw2D(); Clear2D(); - const auto &viewport = screen->mScreenViewport; - auto tex = new FWrapperTexture(viewport.width, viewport.height, 1); + auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1); auto systex = static_cast(tex->GetSystemTexture()); - systex->CreateWipeTexture(viewport.width, viewport.height, "WipeEndScreen"); + systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeEndScreen"); return tex; } From e59c5cb9471efb9479708f01708ab5158163bf0e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 23 Jun 2019 21:24:37 +0200 Subject: [PATCH 27/60] - fix missing font glyphs --- src/rendering/polyrenderer/drawers/poly_triangle.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index c9584b187..10d68396d 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -658,6 +658,7 @@ void PolySWInputAssembly::Load(PolyTriangleThreadData *thread, const void *verti bool PolyTriangleThreadData::IsDegenerate(const ShadedTriVertex *const* vert) { + return false; // A degenerate triangle has a zero cross product for two of its sides. float ax = vert[1]->gl_Position.X - vert[0]->gl_Position.X; float ay = vert[1]->gl_Position.Y - vert[0]->gl_Position.Y; @@ -669,7 +670,7 @@ bool PolyTriangleThreadData::IsDegenerate(const ShadedTriVertex *const* vert) float crossy = az * bx - ax * bz; float crossz = ax * by - ay * bx; float crosslengthsqr = crossx * crossx + crossy * crossy + crossz * crossz; - return crosslengthsqr <= 1.e-6f; + return crosslengthsqr <= 1.e-8f; } bool PolyTriangleThreadData::IsFrontfacing(TriDrawTriangleArgs *args) From 557206131cdc5c2c3d4e571cf17176ade05e5855 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 23 Jun 2019 23:53:42 +0200 Subject: [PATCH 28/60] - remove debug statement --- src/rendering/polyrenderer/drawers/poly_triangle.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 10d68396d..f87c01960 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -658,7 +658,6 @@ void PolySWInputAssembly::Load(PolyTriangleThreadData *thread, const void *verti bool PolyTriangleThreadData::IsDegenerate(const ShadedTriVertex *const* vert) { - return false; // A degenerate triangle has a zero cross product for two of its sides. float ax = vert[1]->gl_Position.X - vert[0]->gl_Position.X; float ay = vert[1]->gl_Position.Y - vert[0]->gl_Position.Y; From 9da46d0e0acef6659f4ca46c8fb105fd6a473cd6 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 24 Jul 2019 21:45:37 +0200 Subject: [PATCH 29/60] - force this branch to always use the poly backend --- src/win32/hardware.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/win32/hardware.cpp b/src/win32/hardware.cpp index ba95ae680..faaf08ce4 100644 --- a/src/win32/hardware.cpp +++ b/src/win32/hardware.cpp @@ -130,10 +130,9 @@ void I_InitGraphics () // are the active app. Huh? } - if (vid_enablevulkan == 2) - { - Video = new Win32PolyVideo(); - } +#if 1 // always use poly backend on this branch, for now. + Video = new Win32PolyVideo(); +#else #ifdef HAVE_VULKAN else if (vid_enablevulkan == 1) { @@ -153,6 +152,7 @@ void I_InitGraphics () { Video = new Win32GLVideo(); } +#endif if (Video == NULL) I_FatalError ("Failed to initialize display"); From ec82f994f727ea35ac4b0acc3bb38d2dfa119191 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 24 Jul 2019 22:13:00 +0200 Subject: [PATCH 30/60] - hook up software renderer --- .../polyrenderer/backend/poly_framebuffer.h | 4 +- src/rendering/swrenderer/r_swscene.cpp | 70 +++++++++++-------- src/rendering/v_video.h | 3 + 3 files changed, 47 insertions(+), 30 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.h b/src/rendering/polyrenderer/backend/poly_framebuffer.h index b779beb58..8e2eae427 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.h +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.h @@ -17,7 +17,7 @@ class PolyFrameBuffer : public SystemBaseFrameBuffer public: RenderMemory *GetFrameMemory() { return &mFrameMemory; } PolyRenderState *GetRenderState() { return mRenderState.get(); } - DCanvas *GetCanvas() { return mCanvas.get(); } + DCanvas *GetCanvas() override { return mCanvas.get(); } PolyDepthStencil *GetDepthStencil() { return mDepthStencil.get(); } const DrawerCommandQueuePtr &GetDrawCommands(); void FlushDrawCommands(); @@ -31,6 +31,8 @@ public: void Update(); + bool IsPoly() override { return true; } + void InitializeState() override; void CleanForRestart() override; diff --git a/src/rendering/swrenderer/r_swscene.cpp b/src/rendering/swrenderer/r_swscene.cpp index cf4a54ecb..fcabe745c 100644 --- a/src/rendering/swrenderer/r_swscene.cpp +++ b/src/rendering/swrenderer/r_swscene.cpp @@ -86,41 +86,53 @@ SWSceneDrawer::~SWSceneDrawer() sector_t *SWSceneDrawer::RenderView(player_t *player) { - // Avoid using the pixel buffer from the last frame - FBTextureIndex = (FBTextureIndex + 1) % 2; - auto &fbtex = FBTexture[FBTextureIndex]; - - if (fbtex == nullptr || fbtex->GetSystemTexture() == nullptr || - fbtex->GetDisplayWidth() != screen->GetWidth() || - fbtex->GetDisplayHeight() != screen->GetHeight() || - (V_IsTrueColor() ? 1:0) != fbtex->GetColorFormat()) + if (!screen->IsPoly()) { - // This manually constructs its own material here. - fbtex.reset(); - fbtex.reset(new FWrapperTexture(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor())); - fbtex->GetSystemTexture()->AllocateBuffer(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor() ? 4 : 1); - auto mat = FMaterial::ValidateTexture(fbtex.get(), false); - mat->AddTextureLayer(PaletteTexture); + // Avoid using the pixel buffer from the last frame + FBTextureIndex = (FBTextureIndex + 1) % 2; + auto &fbtex = FBTexture[FBTextureIndex]; - Canvas.reset(); - Canvas.reset(new DCanvas(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor())); + if (fbtex == nullptr || fbtex->GetSystemTexture() == nullptr || + fbtex->GetDisplayWidth() != screen->GetWidth() || + fbtex->GetDisplayHeight() != screen->GetHeight() || + (V_IsTrueColor() ? 1:0) != fbtex->GetColorFormat()) + { + // This manually constructs its own material here. + fbtex.reset(); + fbtex.reset(new FWrapperTexture(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor())); + fbtex->GetSystemTexture()->AllocateBuffer(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor() ? 4 : 1); + auto mat = FMaterial::ValidateTexture(fbtex.get(), false); + mat->AddTextureLayer(PaletteTexture); + + Canvas.reset(); + Canvas.reset(new DCanvas(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor())); + } + + IHardwareTexture *systemTexture = fbtex->GetSystemTexture(); + auto buf = systemTexture->MapBuffer(); + if (!buf) I_FatalError("Unable to map buffer for software rendering"); + SWRenderer->RenderView(player, Canvas.get(), buf, systemTexture->GetBufferPitch()); + systemTexture->CreateTexture(nullptr, screen->GetWidth(), screen->GetHeight(), 0, false, 0, "swbuffer"); + + auto map = swrenderer::CameraLight::Instance()->ShaderColormap(); + screen->DrawTexture(fbtex.get(), 0, 0, DTA_SpecialColormap, map, TAG_DONE); + screen->Draw2D(); + screen->Clear2D(); + screen->PostProcessScene(CM_DEFAULT, [&]() { + SWRenderer->DrawRemainingPlayerSprites(); + screen->Draw2D(); + screen->Clear2D(); + }); } - - IHardwareTexture *systemTexture = fbtex->GetSystemTexture(); - auto buf = systemTexture->MapBuffer(); - if (!buf) I_FatalError("Unable to map buffer for software rendering"); - SWRenderer->RenderView(player, Canvas.get(), buf, systemTexture->GetBufferPitch()); - systemTexture->CreateTexture(nullptr, screen->GetWidth(), screen->GetHeight(), 0, false, 0, "swbuffer"); - - auto map = swrenderer::CameraLight::Instance()->ShaderColormap(); - screen->DrawTexture(fbtex.get(), 0, 0, DTA_SpecialColormap, map, TAG_DONE); - screen->Draw2D(); - screen->Clear2D(); - screen->PostProcessScene(CM_DEFAULT, [&]() { + else + { + DCanvas *canvas = screen->GetCanvas(); + SWRenderer->RenderView(player, canvas, canvas->GetPixels(), canvas->GetPitch()); + // To do: apply swrenderer::CameraLight::Instance()->ShaderColormap(); SWRenderer->DrawRemainingPlayerSprites(); screen->Draw2D(); screen->Clear2D(); - }); + } return r_viewpoint.sector; } diff --git a/src/rendering/v_video.h b/src/rendering/v_video.h index fb2227ffc..f6324826b 100644 --- a/src/rendering/v_video.h +++ b/src/rendering/v_video.h @@ -394,6 +394,9 @@ public: virtual ~DFrameBuffer(); virtual void InitializeState() = 0; // For stuff that needs 'screen' set. virtual bool IsVulkan() { return false; } + virtual bool IsPoly() { return false; } + + virtual DCanvas* GetCanvas() { return nullptr; } void SetSize(int width, int height); void SetVirtualSize(int width, int height) From a55412fcf625bc9d27e695ea06dcf173c4b9465e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 24 Jul 2019 23:25:48 +0200 Subject: [PATCH 31/60] - fix crash when rendering models --- src/rendering/polyrenderer/backend/poly_buffers.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rendering/polyrenderer/backend/poly_buffers.cpp b/src/rendering/polyrenderer/backend/poly_buffers.cpp index d99056b9c..392684532 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.cpp +++ b/src/rendering/polyrenderer/backend/poly_buffers.cpp @@ -65,6 +65,8 @@ void PolyBuffer::Unmap() void *PolyBuffer::Lock(unsigned int size) { + if (mData.size() < (size_t)size) + Resize(size); return map; } From 97a4f2577133306e0f6126e0777d8904b711bc4c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 25 Jul 2019 04:19:05 +0200 Subject: [PATCH 32/60] - hook up dynamic lights --- .../hwrenderer/dynlights/hw_lightbuffer.cpp | 2 +- .../polyrenderer/backend/poly_buffers.cpp | 40 ++++++++++++++---- .../polyrenderer/backend/poly_framebuffer.cpp | 7 +++- .../polyrenderer/backend/poly_framebuffer.h | 2 + .../polyrenderer/drawers/poly_triangle.cpp | 42 +++++++++++++++++++ .../polyrenderer/drawers/poly_triangle.h | 16 +++++++ .../polyrenderer/drawers/poly_vertex_shader.h | 4 +- 7 files changed, 101 insertions(+), 12 deletions(-) diff --git a/src/rendering/hwrenderer/dynlights/hw_lightbuffer.cpp b/src/rendering/hwrenderer/dynlights/hw_lightbuffer.cpp index 68a1fad2d..30326155f 100644 --- a/src/rendering/hwrenderer/dynlights/hw_lightbuffer.cpp +++ b/src/rendering/hwrenderer/dynlights/hw_lightbuffer.cpp @@ -44,7 +44,7 @@ FLightBuffer::FLightBuffer() // Hack alert: On Intel's GL driver SSBO's perform quite worse than UBOs. // We only want to disable using SSBOs for lights but not disable the feature entirely. // Note that using an uniform buffer here will limit the number of lights per surface so it isn't done for NVidia and AMD. - if (screen->IsVulkan() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && !strstr(screen->vendorstring, "Intel"))) + if (screen->IsVulkan() || screen->IsPoly() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && !strstr(screen->vendorstring, "Intel"))) { mBufferType = true; mBlockAlign = 0; diff --git a/src/rendering/polyrenderer/backend/poly_buffers.cpp b/src/rendering/polyrenderer/backend/poly_buffers.cpp index 392684532..5aa713d84 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.cpp +++ b/src/rendering/polyrenderer/backend/poly_buffers.cpp @@ -89,19 +89,13 @@ void PolyVertexInputAssembly::Load(PolyTriangleThreadData *thread, const void *v const float *attrVertex = reinterpret_cast(vertex + mOffsets[VATTR_VERTEX]); const float *attrTexcoord = reinterpret_cast(vertex + mOffsets[VATTR_TEXCOORD]); const uint8_t *attrColor = reinterpret_cast(vertex + mOffsets[VATTR_COLOR]); + const uint32_t* attrNormal = reinterpret_cast(vertex + mOffsets[VATTR_NORMAL]); + const uint32_t* attrNormal2 = reinterpret_cast(vertex + mOffsets[VATTR_NORMAL2]); thread->mainVertexShader.aPosition = { attrVertex[0], attrVertex[1], attrVertex[2], 1.0f }; thread->mainVertexShader.aTexCoord = { attrTexcoord[0], attrTexcoord[1] }; - if (UseVertexData) - { - uint32_t r = attrColor[0]; - uint32_t g = attrColor[1]; - uint32_t b = attrColor[2]; - uint32_t a = attrColor[3]; - thread->mainVertexShader.aColor = MAKEARGB(a, r, g, b); - } - else + if ((UseVertexData & 1) == 0) { const auto &c = thread->mainVertexShader.Data.uVertexColor; thread->mainVertexShader.aColor = MAKEARGB( @@ -111,6 +105,34 @@ void PolyVertexInputAssembly::Load(PolyTriangleThreadData *thread, const void *v static_cast(c.Z * 255.0f + 0.5f) ); } + else + { + uint32_t r = attrColor[0]; + uint32_t g = attrColor[1]; + uint32_t b = attrColor[2]; + uint32_t a = attrColor[3]; + thread->mainVertexShader.aColor = MAKEARGB(a, r, g, b); + } + + if ((UseVertexData & 2) == 0) + { + const auto &n = thread->mainVertexShader.Data.uVertexNormal; + thread->mainVertexShader.aNormal = Vec4f(n.X, n.Y, n.Z, 1.0); + thread->mainVertexShader.aNormal2 = thread->mainVertexShader.aNormal; + } + else + { + int n = *attrNormal; + int n2 = *attrNormal2; + float x = ((n << 22) >> 22) / 512.0f; + float y = ((n << 12) >> 22) / 512.0f; + float z = ((n << 2) >> 22) / 512.0f; + float x2 = ((n2 << 22) >> 22) / 512.0f; + float y2 = ((n2 << 12) >> 22) / 512.0f; + float z2 = ((n2 << 2) >> 22) / 512.0f; + thread->mainVertexShader.aNormal = Vec4f(x, y, z, 0.0f); + thread->mainVertexShader.aNormal2 = Vec4f(x2, y2, z2, 0.0f); + } } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index c5b689abe..023298806 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -100,6 +100,8 @@ void PolyFrameBuffer::InitializeState() mViewpoints = new HWViewpointBuffer; mLights = new FLightBuffer(); + PolyTriangleDrawer::SetLightBuffer(GetDrawCommands(), mLightBuffer->Memory()); + CheckCanvas(); } @@ -485,7 +487,10 @@ IIndexBuffer *PolyFrameBuffer::CreateIndexBuffer() IDataBuffer *PolyFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) { - return new PolyDataBuffer(bindingpoint, ssbo, needsresize); + IDataBuffer *buffer = new PolyDataBuffer(bindingpoint, ssbo, needsresize); + if (bindingpoint == LIGHTBUF_BINDINGPOINT) + mLightBuffer = buffer; + return buffer; } void PolyFrameBuffer::SetTextureFilterMode() diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.h b/src/rendering/polyrenderer/backend/poly_framebuffer.h index 8e2eae427..08494a117 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.h +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.h @@ -76,6 +76,8 @@ private: void CheckCanvas(); + IDataBuffer *mLightBuffer = nullptr; + std::unique_ptr mRenderState; std::unique_ptr mCanvas; std::unique_ptr mDepthStencil; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index f87c01960..11c20564e 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -108,6 +108,11 @@ void PolyTriangleDrawer::SetIndexBuffer(const DrawerCommandQueuePtr &queue, cons queue->Push(elements); } +void PolyTriangleDrawer::SetLightBuffer(const DrawerCommandQueuePtr& queue, const void *lights) +{ + queue->Push(lights); +} + void PolyTriangleDrawer::PushDrawArgs(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args) { queue->Push(args); @@ -309,6 +314,42 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu drawargs.SetLight(GetColorTable(cm), 255, mainVertexShader.Viewpoint->mGlobVis * 32.0f, true); } + int numLights = 0; + if (constants.uLightIndex >= 0) + { + const FVector4 &lightRange = lights[constants.uLightIndex]; + static_assert(sizeof(FVector4) == 16, "sizeof(FVector4) is not 16 bytes"); + if (lightRange.Y > lightRange.X) + { + int start = constants.uLightIndex + 1; + int modulatedStart = static_cast(lightRange.X) + start; + int modulatedEnd = static_cast(lightRange.Y) + start; + for (int i = modulatedStart; i < modulatedEnd; i += 4) + { + if (numLights == maxPolyLights) + break; + + auto &lightpos = lights[i]; + auto &lightcolor = lights[i + 1]; + //auto &lightspot1 = lights[i + 2]; + //auto &lightspot2 = lights[i + 3]; + uint32_t r = (int)clamp(lightcolor.X * 255.0f, 0.0f, 255.0f); + uint32_t g = (int)clamp(lightcolor.Y * 255.0f, 0.0f, 255.0f); + uint32_t b = (int)clamp(lightcolor.Z * 255.0f, 0.0f, 255.0f); + + auto& polylight = polyLights[numLights++]; + polylight.x = lightpos.X; + polylight.y = lightpos.Y; + polylight.z = lightpos.Z; + polylight.radius = 256.0f / lightpos.W; + polylight.color = (r << 16) | (g << 8) | b; + if (lightcolor.W < 0.0f) + polylight.radius = -polylight.radius; + } + } + } + drawargs.SetLights(polyLights, numLights); + if (SpecialEffect != EFF_NONE) { // To do: need new drawers for these @@ -794,6 +835,7 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve return; drawargs.SetColor(vert[0]->vColor, 0); + drawargs.SetNormal(FVector3(vert[0]->vWorldNormal.X, vert[0]->vWorldNormal.Y, vert[0]->vWorldNormal.Z)); // Cull, clip and generate additional vertices as needed ScreenTriVertex clippedvert[max_additional_vertices]; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 683ebbd40..d1e2f6fcb 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -42,6 +42,7 @@ public: static void SetInputAssembly(const DrawerCommandQueuePtr &queue, PolyInputAssembly *input); static void SetVertexBuffer(const DrawerCommandQueuePtr &queue, const void *vertices); static void SetIndexBuffer(const DrawerCommandQueuePtr &queue, const void *elements); + static void SetLightBuffer(const DrawerCommandQueuePtr& queue, const void *lights); static void SetViewpointUniforms(const DrawerCommandQueuePtr &queue, const HWViewpointUniforms *uniforms); static void SetDepthClamp(const DrawerCommandQueuePtr &queue, bool on); static void SetDepthMask(const DrawerCommandQueuePtr &queue, bool on); @@ -143,6 +144,7 @@ public: void SetInputAssembly(PolyInputAssembly *input) { inputAssembly = input; } void SetVertexBuffer(const void *data) { vertices = data; } void SetIndexBuffer(const void *data) { elements = (const unsigned int *)data; } + void SetLightBuffer(const void *data) { lights = (const FVector4 *)data; } void SetViewpointUniforms(const HWViewpointUniforms *uniforms); void SetDepthClamp(bool on); void SetDepthMask(bool on); @@ -237,6 +239,10 @@ public: const void *vertices = nullptr; const unsigned int *elements = nullptr; + const FVector4 *lights = nullptr; + + enum { maxPolyLights = 16 }; + PolyLight polyLights[maxPolyLights]; PolyMainVertexShader mainVertexShader; @@ -455,6 +461,16 @@ private: const void *indices; }; +class PolySetLightBufferCommand : public PolyDrawerCommand +{ +public: + PolySetLightBufferCommand(const void *lights) : lights(lights) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetLightBuffer(lights); } + +private: + const void *lights; +}; + class PolySetInputAssemblyCommand : public PolyDrawerCommand { public: diff --git a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h index a431f8941..6c080552f 100644 --- a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h +++ b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h @@ -17,6 +17,7 @@ public: Vec4f vTexCoord; uint32_t vColor; Vec4f pixelpos; + Vec4f vWorldNormal; }; class PolyMainVertexShader : public ShadedTriVertex @@ -33,7 +34,6 @@ public: // Output Vec3f glowdist; Vec3f gradientdist; - Vec4f vWorldNormal; Vec4f vEyeNormal; // Defines @@ -245,6 +245,8 @@ public: vColor = drawargs->Color(); + vWorldNormal = { drawargs->Normal().X, drawargs->Normal().Y, drawargs->Normal().Z }; + // Calculate gl_ClipDistance[i] for (int i = 0; i < 3; i++) { From ebe377e5dea8a7a5e8e32cebdc32ad7be020c62c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 4 Aug 2019 02:57:08 +0200 Subject: [PATCH 33/60] - remove TriDrawTriangleArgs::uniforms as it is redundant --- .../polyrenderer/drawers/poly_triangle.cpp | 4 +- .../polyrenderer/drawers/screen_triangle.cpp | 92 +++++++++---------- .../polyrenderer/drawers/screen_triangle.h | 4 - 3 files changed, 47 insertions(+), 53 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 11c20564e..0476d882b 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -537,7 +537,6 @@ void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode dra elements += index; TriDrawTriangleArgs args; - args.uniforms = &drawargs; ShadedTriVertex vertbuffer[3]; ShadedTriVertex *vert[3] = { &vertbuffer[0], &vertbuffer[1], &vertbuffer[2] }; @@ -602,7 +601,6 @@ void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode) return; TriDrawTriangleArgs args; - args.uniforms = &drawargs; int vinput = index; @@ -913,7 +911,7 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve // Keep varyings in -128 to 128 range if possible // But don't do this for the skycap mode since the V texture coordinate is used for blending - if (numclipvert > 0 && args->uniforms->BlendMode() != TriBlendMode::Skycap) + if (numclipvert > 0 && drawargs.BlendMode() != TriBlendMode::Skycap) { float newOriginU = floorf(clippedvert[0].u * 0.1f) * 10.0f; float newOriginV = floorf(clippedvert[0].v * 0.1f) * 10.0f; diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 23838bb9c..9f778e3e8 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -142,11 +142,11 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat } int opt = 0; - if (args->uniforms->DepthTest()) opt |= SWTRI_DepthTest; - if (args->uniforms->StencilTest()) opt |= SWTRI_StencilTest; - if (args->uniforms->WriteColor()) opt |= SWTRI_WriteColor; - if (args->uniforms->WriteDepth()) opt |= SWTRI_WriteDepth; - if (args->uniforms->WriteStencil()) opt |= SWTRI_WriteStencil; + if (thread->drawargs.DepthTest()) opt |= SWTRI_DepthTest; + if (thread->drawargs.StencilTest()) opt |= SWTRI_StencilTest; + if (thread->drawargs.WriteColor()) opt |= SWTRI_WriteColor; + if (thread->drawargs.WriteDepth()) opt |= SWTRI_WriteDepth; + if (thread->drawargs.WriteStencil()) opt |= SWTRI_WriteStencil; TriangleDrawers[opt](args, thread, edges, topY, bottomY); } @@ -194,7 +194,7 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa if (OptT::Flags & SWTRI_WriteColor) { - int bmode = (int)args->uniforms->BlendMode(); + int bmode = (int)thread->drawargs.BlendMode(); drawfunc = thread->dest_bgra ? ScreenTriangle::SpanDrawers32[bmode] : ScreenTriangle::SpanDrawers8[bmode]; } @@ -216,10 +216,10 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa pitch = thread->depthstencil->Width(); if (OptT::Flags & SWTRI_StencilTest) - stencilTestValue = args->uniforms->StencilTestValue(); + stencilTestValue = thread->drawargs.StencilTestValue(); if (OptT::Flags & SWTRI_WriteStencil) - stencilWriteValue = args->uniforms->StencilWriteValue(); + stencilWriteValue = thread->drawargs.StencilWriteValue(); float depthbias; if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_WriteDepth)) @@ -547,8 +547,8 @@ void StepSpan(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriang if (!(ModeT::SWFlags & SWSTYLEF_Fill) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary)) { - texWidth = args->uniforms->TextureWidth(); - texHeight = args->uniforms->TextureHeight(); + texWidth = thread->drawargs.TextureWidth(); + texHeight = thread->drawargs.TextureHeight(); } if (OptT::Flags & SWOPT_DynLights) @@ -566,9 +566,9 @@ void StepSpan(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriang if (!(OptT::Flags & SWOPT_FixedLight)) { - float globVis = args->uniforms->GlobVis() * (1.0f / 32.0f); + float globVis = thread->drawargs.GlobVis() * (1.0f / 32.0f); - light = args->uniforms->Light(); + light = thread->drawargs.Light(); shade = (fixed_t)((2.0f - (light + 12.0f) / 128.0f) * (float)FRACUNIT); lightpos = (fixed_t)(globVis * posW * (float)FRACUNIT); lightstep = (fixed_t)(globVis * stepW * (float)FRACUNIT); @@ -730,12 +730,12 @@ void StepSpan(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriang float worldnormalX, worldnormalY, worldnormalZ; uint32_t dynlightcolor; - lights = args->uniforms->Lights(); - num_lights = args->uniforms->NumLights(); - worldnormalX = args->uniforms->Normal().X; - worldnormalY = args->uniforms->Normal().Y; - worldnormalZ = args->uniforms->Normal().Z; - dynlightcolor = args->uniforms->DynLightColor(); + lights = thread->drawargs.Lights(); + num_lights = thread->drawargs.NumLights(); + worldnormalX = thread->drawargs.Normal().X; + worldnormalY = thread->drawargs.Normal().Y; + worldnormalZ = thread->drawargs.Normal().Z; + dynlightcolor = thread->drawargs.DynLightColor(); // The normal vector cannot be uniform when drawing models. Calculate and use the face normal: if (worldnormalX == 0.0f && worldnormalY == 0.0f && worldnormalZ == 0.0f) @@ -899,39 +899,39 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyT if (!(ModeT::SWFlags & SWSTYLEF_Fill) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary)) { - texPixels = (const uint32_t*)args->uniforms->TexturePixels(); + texPixels = (const uint32_t*)thread->drawargs.TexturePixels(); } if (ModeT::SWFlags & SWSTYLEF_Translated) { - translation = (const uint32_t*)args->uniforms->Translation(); + translation = (const uint32_t*)thread->drawargs.Translation(); } if ((ModeT::SWFlags & SWSTYLEF_Fill) || (ModeT::SWFlags & SWSTYLEF_Skycap) || (ModeT::Flags & STYLEF_ColorIsFixed)) { - fillcolor = args->uniforms->Color(); + fillcolor = thread->drawargs.Color(); } if (!(ModeT::Flags & STYLEF_Alpha1)) { - actoralpha = args->uniforms->Alpha(); + actoralpha = thread->drawargs.Alpha(); } if (OptT::Flags & SWOPT_FixedLight) { - fixedlight = args->uniforms->Light(); + fixedlight = thread->drawargs.Light(); fixedlight += fixedlight >> 7; // 255 -> 256 } if (OptT::Flags & SWOPT_ColoredFog) { - shade_fade_r = args->uniforms->ShadeFadeRed(); - shade_fade_g = args->uniforms->ShadeFadeGreen(); - shade_fade_b = args->uniforms->ShadeFadeBlue(); - shade_light_r = args->uniforms->ShadeLightRed(); - shade_light_g = args->uniforms->ShadeLightGreen(); - shade_light_b = args->uniforms->ShadeLightBlue(); - desaturate = args->uniforms->ShadeDesaturate(); + shade_fade_r = thread->drawargs.ShadeFadeRed(); + shade_fade_g = thread->drawargs.ShadeFadeGreen(); + shade_fade_b = thread->drawargs.ShadeFadeBlue(); + shade_light_r = thread->drawargs.ShadeLightRed(); + shade_light_g = thread->drawargs.ShadeLightGreen(); + shade_light_b = thread->drawargs.ShadeLightBlue(); + desaturate = thread->drawargs.ShadeDesaturate(); inv_desaturate = 256 - desaturate; } @@ -1286,18 +1286,18 @@ void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTria { using namespace TriScreenDrawerModes; - if (args->uniforms->NumLights() == 0 && args->uniforms->DynLightColor() == 0) + if (thread->drawargs.NumLights() == 0 && thread->drawargs.DynLightColor() == 0) { - if (!args->uniforms->FixedLight()) + if (!thread->drawargs.FixedLight()) { - if (args->uniforms->SimpleShade()) + if (thread->drawargs.SimpleShade()) DrawSpanOpt32(y, x0, x1, args, thread); else DrawSpanOpt32(y, x0, x1, args, thread); } else { - if (args->uniforms->SimpleShade()) + if (thread->drawargs.SimpleShade()) DrawSpanOpt32(y, x0, x1, args, thread); else DrawSpanOpt32(y, x0, x1, args, thread); @@ -1305,16 +1305,16 @@ void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTria } else { - if (!args->uniforms->FixedLight()) + if (!thread->drawargs.FixedLight()) { - if (args->uniforms->SimpleShade()) + if (thread->drawargs.SimpleShade()) DrawSpanOpt32(y, x0, x1, args, thread); else DrawSpanOpt32(y, x0, x1, args, thread); } else { - if (args->uniforms->SimpleShade()) + if (thread->drawargs.SimpleShade()) DrawSpanOpt32(y, x0, x1, args, thread); else DrawSpanOpt32(y, x0, x1, args, thread); @@ -1341,26 +1341,26 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTr uint16_t *lightarray = thread->lightarray; uint32_t *dynlights = thread->dynlights; - colormaps = args->uniforms->BaseColormap(); + colormaps = thread->drawargs.BaseColormap(); if (!(ModeT::SWFlags & SWSTYLEF_Fill) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary)) { - texPixels = args->uniforms->TexturePixels(); + texPixels = thread->drawargs.TexturePixels(); } if (ModeT::SWFlags & SWSTYLEF_Translated) { - translation = args->uniforms->Translation(); + translation = thread->drawargs.Translation(); } if ((ModeT::SWFlags & SWSTYLEF_Fill) || (ModeT::SWFlags & SWSTYLEF_Skycap) || (ModeT::Flags & STYLEF_ColorIsFixed)) { - fillcolor = args->uniforms->Color(); + fillcolor = thread->drawargs.Color(); } if (!(ModeT::Flags & STYLEF_Alpha1)) { - actoralpha = args->uniforms->Alpha(); + actoralpha = thread->drawargs.Alpha(); } if (ModeT::SWFlags & SWSTYLEF_Skycap) @@ -1368,7 +1368,7 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTr if (OptT::Flags & SWOPT_FixedLight) { - fixedlight = args->uniforms->Light(); + fixedlight = thread->drawargs.Light(); fixedlight += fixedlight >> 7; // 255 -> 256 fixedlight = ((256 - fixedlight) * NUMCOLORMAPS) & 0xffffff00; } @@ -1636,16 +1636,16 @@ void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTrian { using namespace TriScreenDrawerModes; - if (args->uniforms->NumLights() == 0 && args->uniforms->DynLightColor() == 0) + if (thread->drawargs.NumLights() == 0 && thread->drawargs.DynLightColor() == 0) { - if (!args->uniforms->FixedLight()) + if (!thread->drawargs.FixedLight()) DrawSpanOpt8(y, x0, x1, args, thread); else DrawSpanOpt8(y, x0, x1, args, thread); } else { - if (!args->uniforms->FixedLight()) + if (!thread->drawargs.FixedLight()) DrawSpanOpt8(y, x0, x1, args, thread); else DrawSpanOpt8(y, x0, x1, args, thread); diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.h b/src/rendering/polyrenderer/drawers/screen_triangle.h index 151cdfcea..f0275d8a9 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.h +++ b/src/rendering/polyrenderer/drawers/screen_triangle.h @@ -28,7 +28,6 @@ #include "rendering/swrenderer/drawers/r_draw.h" class FString; -class PolyDrawArgs; class PolyTriangleThreadData; struct ScreenTriVertex @@ -49,7 +48,6 @@ struct TriDrawTriangleArgs ScreenTriVertex *v1; ScreenTriVertex *v2; ScreenTriVertex *v3; - const PolyDrawArgs *uniforms; ScreenTriangleStepVariables gradientX; ScreenTriangleStepVariables gradientY; @@ -95,8 +93,6 @@ private: } }; -class RectDrawArgs; - enum class TriBlendMode { Opaque, From f73470dcf4181efab22312beb6d0b7cbc2d9c687 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 5 Aug 2019 03:23:04 +0200 Subject: [PATCH 34/60] - rewrite screen triangle drawer to be more modular and better support the hwrenderer shaders --- .../polyrenderer/drawers/poly_triangle.cpp | 2 + .../polyrenderer/drawers/poly_triangle.h | 24 +- .../polyrenderer/drawers/screen_triangle.cpp | 346 ++++++++++++++++++ .../polyrenderer/drawers/screen_triangle.h | 27 ++ 4 files changed, 389 insertions(+), 10 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 0476d882b..e676a3506 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -909,6 +909,7 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve } #endif +#if 0 // Keep varyings in -128 to 128 range if possible // But don't do this for the skycap mode since the V texture coordinate is used for blending if (numclipvert > 0 && drawargs.BlendMode() != TriBlendMode::Skycap) @@ -921,6 +922,7 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve clippedvert[i].v -= newOriginV; } } +#endif if (twosided && numclipvert > 2) { diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index d1e2f6fcb..4f365ca04 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -198,16 +198,20 @@ public: return MAX(c, 0); } - // Varyings - float worldposX[MAXWIDTH]; - float worldposY[MAXWIDTH]; - float worldposZ[MAXWIDTH]; - uint32_t texel[MAXWIDTH]; - int32_t texelV[MAXWIDTH]; - uint16_t lightarray[MAXWIDTH]; - uint32_t dynlights[MAXWIDTH]; - float depthvalues[MAXWIDTH]; - uint8_t alphatestbuffer[MAXWIDTH]; + struct Scanline + { + float W[MAXWIDTH]; + float U[MAXWIDTH]; + float V[MAXWIDTH]; + float WorldX[MAXWIDTH]; + float WorldY[MAXWIDTH]; + float WorldZ[MAXWIDTH]; + uint32_t FragColor[MAXWIDTH]; +#if 0 + uint16_t lightarray[MAXWIDTH]; + uint32_t dynlights[MAXWIDTH]; +#endif + } scanline; static PolyTriangleThreadData *Get(DrawerThread *thread); diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 9f778e3e8..ae189ad8f 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -38,6 +38,350 @@ #include "screen_triangle.h" #include "x86.h" +static void WriteW(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) +{ + float startX = x0 + (0.5f - args->v1->x); + float startY = y + (0.5f - args->v1->y); + + float posW = args->v1->w + args->gradientX.W * startX + args->gradientY.W * startY; + float stepW = args->gradientX.W; + float* w = thread->scanline.W; + for (int x = x0; x < x1; x++) + { + w[x] = 1.0f / posW; + posW += stepW; + } +} + +static void WriteVarying(float pos, float step, int x0, int x1, const float* w, float* varying) +{ + for (int x = x0; x < x1; x++) + { + varying[x] = pos * w[x]; + pos += step; + } +} + +static void WriteVaryings(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) +{ + float startX = x0 + (0.5f - args->v1->x); + float startY = y + (0.5f - args->v1->y); + + WriteVarying(args->v1->u * args->v1->w + args->gradientX.U * startX + args->gradientY.U * startY, args->gradientX.U, x0, x1, thread->scanline.W, thread->scanline.U); + WriteVarying(args->v1->v * args->v1->w + args->gradientX.V * startX + args->gradientY.V * startY, args->gradientX.V, x0, x1, thread->scanline.W, thread->scanline.V); + WriteVarying(args->v1->worldX * args->v1->w + args->gradientX.WorldX * startX + args->gradientY.WorldX * startY, args->gradientX.WorldX, x0, x1, thread->scanline.W, thread->scanline.WorldX); + WriteVarying(args->v1->worldY * args->v1->w + args->gradientX.WorldY * startX + args->gradientY.WorldY * startY, args->gradientX.WorldY, x0, x1, thread->scanline.W, thread->scanline.WorldY); + WriteVarying(args->v1->worldZ * args->v1->w + args->gradientX.WorldZ * startX + args->gradientY.WorldZ * startY, args->gradientX.WorldZ, x0, x1, thread->scanline.W, thread->scanline.WorldZ); +} + +static void WriteBlend(int y, int x0, int x1, PolyTriangleThreadData* thread) +{ + uint32_t* dest = (uint32_t*)thread->dest; + uint32_t* line = dest + y * (ptrdiff_t)thread->dest_pitch; + + if (!thread->AlphaTest) + { + for (int x = x0; x < x1; x++) + { + line[x] = thread->scanline.FragColor[x]; + } + } + else + { + uint32_t* fragcolor = thread->scanline.FragColor; + for (int x = x0; x < x1; x++) + { + if (fragcolor[x] > 0x7f000000) + line[x] = thread->scanline.FragColor[x]; + } + } +} + +static void WriteDepth(int y, int x0, int x1, PolyTriangleThreadData* thread) +{ + size_t pitch = thread->depthstencil->Width(); + float* line = thread->depthstencil->DepthValues() + pitch * y; + float* w = thread->scanline.W; + + if (!thread->AlphaTest) + { + for (int x = x0; x < x1; x++) + { + line[x] = w[x]; + } + } + else + { + uint32_t* fragcolor = thread->scanline.FragColor; + for (int x = x0; x < x1; x++) + { + if (fragcolor[x] > 0x7f000000) + line[x] = w[x]; + } + } +} + +static void WriteStencil(int y, int x0, int x1, PolyTriangleThreadData* thread) +{ + size_t pitch = thread->depthstencil->Width(); + uint8_t* line = thread->depthstencil->StencilValues() + pitch * y; + uint8_t value = thread->drawargs.StencilWriteValue(); + if (!thread->AlphaTest) + { + for (int x = x0; x < x1; x++) + { + line[x] = value; + } + } + else + { + uint32_t* fragcolor = thread->scanline.FragColor; + for (int x = x0; x < x1; x++) + { + if (fragcolor[x] > 0x7f000000) + line[x] = value; + } + } +} + +static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) +{ + int texWidth = thread->drawargs.TextureWidth(); + int texHeight = thread->drawargs.TextureHeight(); + const uint32_t* texPixels = (const uint32_t*)thread->drawargs.TexturePixels(); + + for (int x = x0; x < x1; x++) + { + float u = thread->scanline.U[x]; + float v = thread->scanline.V[x]; + u -= std::floor(u); + v -= std::floor(v); + + int texelX = (int)(u * texWidth); + int texelY = (int)(v * texHeight); + uint32_t fg = texPixels[texelX * texHeight + texelY]; + thread->scanline.FragColor[x] = fg; + } +} + +static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) +{ + if (thread->drawargs.BlendMode() == TriBlendMode::Fill || thread->drawargs.BlendMode() == TriBlendMode::FillTranslucent) + return; + + WriteVaryings(y, x0, x1, args, thread); + RunShader(x0, x1, thread); + + if (thread->drawargs.WriteColor()) + WriteBlend(y, x0, x1, thread); + if (thread->drawargs.WriteDepth()) + WriteDepth(y, x0, x1, thread); + if (thread->drawargs.WriteStencil()) + WriteStencil(y, x0, x1, thread); +} + +template +static void TestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) +{ + using namespace TriScreenDrawerModes; + + WriteW(y, x0, x1, args, thread); + + if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_StencilTest)) + { + size_t pitch = thread->depthstencil->Width(); + + uint8_t* stencilbuffer; + uint8_t* stencilLine; + uint8_t stencilTestValue; + if (OptT::Flags & SWTRI_StencilTest) + { + stencilbuffer = thread->depthstencil->StencilValues(); + stencilLine = stencilbuffer + pitch * y; + stencilTestValue = thread->drawargs.StencilTestValue(); + } + + float* zbuffer; + float* zbufferLine; + float* w; + float depthbias; + if (OptT::Flags & SWTRI_DepthTest) + { + zbuffer = thread->depthstencil->DepthValues(); + zbufferLine = zbuffer + pitch * y; + w = thread->scanline.W; + depthbias = thread->depthbias; + } + + int x = x0; + int xend = x1; + while (x < xend) + { + int xstart = x; + + if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) + { + while (zbufferLine[x] >= w[x] + depthbias && stencilLine[x] == stencilTestValue && x < xend) + x++; + } + else if (OptT::Flags & SWTRI_DepthTest) + { + while (zbufferLine[x] >= w[x] + depthbias && x < xend) + x++; + } + else if (OptT::Flags & SWTRI_StencilTest) + { + while (stencilLine[x] == stencilTestValue && x < xend) + x++; + } + else + { + x = xend; + } + + if (x > xstart) + { + DrawSpan(y, xstart, x, args, thread); + } + + if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) + { + while ((zbufferLine[x] < w[x] + depthbias || stencilLine[x] != stencilTestValue) && x < xend) + x++; + } + else if (OptT::Flags & SWTRI_DepthTest) + { + while (zbufferLine[x] < w[x] + depthbias && x < xend) + x++; + } + else if (OptT::Flags & SWTRI_StencilTest) + { + while (stencilLine[x] != stencilTestValue && x < xend) + x++; + } + } + } + else + { + DrawSpan(y, x0, x1, args, thread); + } +} + +static void SortVertices(const TriDrawTriangleArgs* args, ScreenTriVertex** sortedVertices) +{ + sortedVertices[0] = args->v1; + sortedVertices[1] = args->v2; + sortedVertices[2] = args->v3; + + if (sortedVertices[1]->y < sortedVertices[0]->y) + std::swap(sortedVertices[0], sortedVertices[1]); + if (sortedVertices[2]->y < sortedVertices[0]->y) + std::swap(sortedVertices[0], sortedVertices[2]); + if (sortedVertices[2]->y < sortedVertices[1]->y) + std::swap(sortedVertices[1], sortedVertices[2]); +} + +void ScreenTriangle::Draw(const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) +{ + // Sort vertices by Y position + ScreenTriVertex* sortedVertices[3]; + SortVertices(args, sortedVertices); + + int clipleft = thread->clip.left; + int cliptop = MAX(thread->clip.top, thread->numa_start_y); + int clipright = thread->clip.right; + int clipbottom = MIN(thread->clip.bottom, thread->numa_end_y); + + int topY = (int)(sortedVertices[0]->y + 0.5f); + int midY = (int)(sortedVertices[1]->y + 0.5f); + int bottomY = (int)(sortedVertices[2]->y + 0.5f); + + topY = MAX(topY, cliptop); + midY = MIN(midY, clipbottom); + bottomY = MIN(bottomY, clipbottom); + + if (topY >= bottomY) + return; + + void(*testfunc)(int y, int x0, int x1, const TriDrawTriangleArgs * args, PolyTriangleThreadData * thread); + + int opt = 0; + if (thread->drawargs.DepthTest()) opt |= TriScreenDrawerModes::SWTRI_DepthTest; + if (thread->drawargs.StencilTest()) opt |= TriScreenDrawerModes::SWTRI_StencilTest; + testfunc = ScreenTriangle::TestSpanOpts[opt]; + + topY += thread->skipped_by_thread(topY); + int num_cores = thread->num_cores; + + // Find start/end X positions for each line covered by the triangle: + + int y = topY; + + float longDX = sortedVertices[2]->x - sortedVertices[0]->x; + float longDY = sortedVertices[2]->y - sortedVertices[0]->y; + float longStep = longDX / longDY; + float longPos = sortedVertices[0]->x + longStep * (y + 0.5f - sortedVertices[0]->y) + 0.5f; + longStep *= num_cores; + + if (y < midY) + { + float shortDX = sortedVertices[1]->x - sortedVertices[0]->x; + float shortDY = sortedVertices[1]->y - sortedVertices[0]->y; + float shortStep = shortDX / shortDY; + float shortPos = sortedVertices[0]->x + shortStep * (y + 0.5f - sortedVertices[0]->y) + 0.5f; + shortStep *= num_cores; + + while (y < midY) + { + int x0 = (int)shortPos; + int x1 = (int)longPos; + if (x1 < x0) std::swap(x0, x1); + x0 = clamp(x0, clipleft, clipright); + x1 = clamp(x1, clipleft, clipright); + + testfunc(y, x0, x1, args, thread); + + shortPos += shortStep; + longPos += longStep; + y += num_cores; + } + } + + if (y < bottomY) + { + float shortDX = sortedVertices[2]->x - sortedVertices[1]->x; + float shortDY = sortedVertices[2]->y - sortedVertices[1]->y; + float shortStep = shortDX / shortDY; + float shortPos = sortedVertices[1]->x + shortStep * (y + 0.5f - sortedVertices[1]->y) + 0.5f; + shortStep *= num_cores; + + while (y < bottomY) + { + int x0 = (int)shortPos; + int x1 = (int)longPos; + if (x1 < x0) std::swap(x0, x1); + x0 = clamp(x0, clipleft, clipright); + x1 = clamp(x1, clipleft, clipright); + + testfunc(y, x0, x1, args, thread); + + shortPos += shortStep; + longPos += longStep; + y += num_cores; + } + } +} + +void(*ScreenTriangle::TestSpanOpts[])(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) = +{ + &TestSpan, + &TestSpan, + &TestSpan, + &TestSpan +}; + +#if 0 + static void SortVertices(const TriDrawTriangleArgs *args, ScreenTriVertex **sortedVertices) { sortedVertices[0] = args->v1; @@ -1757,3 +2101,5 @@ void(*ScreenTriangle::TriangleDrawers[])(const TriDrawTriangleArgs *args, PolyTr }; int ScreenTriangle::FuzzStart = 0; + +#endif diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.h b/src/rendering/polyrenderer/drawers/screen_triangle.h index f0275d8a9..8da0eca89 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.h +++ b/src/rendering/polyrenderer/drawers/screen_triangle.h @@ -127,6 +127,31 @@ enum class TriBlendMode AddShadedTranslated }; +class ScreenTriangle +{ +public: + static void Draw(const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread); + +private: + static void(*TestSpanOpts[])(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread); +}; + +namespace TriScreenDrawerModes +{ + enum SWTestSpan + { + SWTRI_DepthTest = 1, + SWTRI_StencilTest = 2 + }; + + struct TestSpanOpt0 { static const int Flags = 0; }; + struct TestSpanOpt1 { static const int Flags = 1; }; + struct TestSpanOpt2 { static const int Flags = 2; }; + struct TestSpanOpt3 { static const int Flags = 3; }; +} + +#if 0 + class ScreenTriangle { public: @@ -252,3 +277,5 @@ namespace TriScreenDrawerModes struct TriangleOpt30 { static const int Flags = 30; }; struct TriangleOpt31 { static const int Flags = 31; }; } + +#endif From b17351cda478cbea32810c6e477a2e17c30f7b60 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 5 Aug 2019 08:37:22 +0200 Subject: [PATCH 35/60] - implement blend functions --- .../polyrenderer/drawers/poly_draw_args.h | 69 -------------- .../polyrenderer/drawers/screen_triangle.cpp | 93 +++++++++++++++++-- 2 files changed, 84 insertions(+), 78 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.h b/src/rendering/polyrenderer/drawers/poly_draw_args.h index 3a15c3a31..a681b5f37 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.h +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.h @@ -168,72 +168,3 @@ private: FVector3 mNormal; uint32_t mDynLightColor = 0; }; - -#if 0 -class RectDrawArgs -{ -public: - void SetTexture(FSoftwareTexture *texture, FRenderStyle style); - void SetTexture(FSoftwareTexture *texture, uint32_t translationID, FRenderStyle style); - void SetLight(FSWColormap *basecolormap, uint32_t lightlevel); - void SetStyle(TriBlendMode blendmode, double alpha = 1.0) { mBlendMode = blendmode; mAlpha = (uint32_t)(alpha * 256.0 + 0.5); } - void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FSoftwareTexture *texture, bool fullbright); - void SetColor(uint32_t bgra, uint8_t palindex); - void Draw(PolyRenderThread *thread, double x0, double x1, double y0, double y1, double u0, double u1, double v0, double v1); - - FSoftwareTexture *Texture() const { return mTexture; } - const uint8_t *TexturePixels() const { return mTexturePixels; } - int TextureWidth() const { return mTextureWidth; } - int TextureHeight() const { return mTextureHeight; } - const uint8_t *Translation() const { return mTranslation; } - - TriBlendMode BlendMode() const { return mBlendMode; } - uint32_t Color() const { return mColor; } - uint32_t Alpha() const { return mAlpha; } - - uint32_t Light() const { return mLight; } - const uint8_t *BaseColormap() const { return mColormaps; } - uint16_t ShadeLightAlpha() const { return mLightAlpha; } - uint16_t ShadeLightRed() const { return mLightRed; } - uint16_t ShadeLightGreen() const { return mLightGreen; } - uint16_t ShadeLightBlue() const { return mLightBlue; } - uint16_t ShadeFadeAlpha() const { return mFadeAlpha; } - uint16_t ShadeFadeRed() const { return mFadeRed; } - uint16_t ShadeFadeGreen() const { return mFadeGreen; } - uint16_t ShadeFadeBlue() const { return mFadeBlue; } - uint16_t ShadeDesaturate() const { return mDesaturate; } - bool SimpleShade() const { return mSimpleShade; } - - float X0() const { return mX0; } - float X1() const { return mX1; } - float Y0() const { return mY0; } - float Y1() const { return mY1; } - float U0() const { return mU0; } - float U1() const { return mU1; } - float V0() const { return mV0; } - float V1() const { return mV1; } - -private: - FSoftwareTexture *mTexture = nullptr; - const uint8_t *mTexturePixels = nullptr; - int mTextureWidth = 0; - int mTextureHeight = 0; - const uint8_t *mTranslation = nullptr; - const uint8_t *mColormaps = nullptr; - TriBlendMode mBlendMode = TriBlendMode::Fill; - uint32_t mLight = 0; - uint32_t mColor = 0; - uint32_t mAlpha = 0; - uint16_t mLightAlpha = 0; - uint16_t mLightRed = 0; - uint16_t mLightGreen = 0; - uint16_t mLightBlue = 0; - uint16_t mFadeAlpha = 0; - uint16_t mFadeRed = 0; - uint16_t mFadeGreen = 0; - uint16_t mFadeBlue = 0; - uint16_t mDesaturate = 0; - bool mSimpleShade = true; - float mX0, mX1, mY0, mY1, mU0, mU1, mV0, mV1; -}; -#endif diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index ae189ad8f..7d74f564e 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -74,25 +74,100 @@ static void WriteVaryings(int y, int x0, int x1, const TriDrawTriangleArgs* args WriteVarying(args->v1->worldZ * args->v1->w + args->gradientX.WorldZ * startX + args->gradientY.WorldZ * startY, args->gradientX.WorldZ, x0, x1, thread->scanline.W, thread->scanline.WorldZ); } -static void WriteBlend(int y, int x0, int x1, PolyTriangleThreadData* thread) +static uint32_t BlendColor(FRenderStyle style, uint32_t fg, uint32_t bg) +{ + static const int shiftTable[] = { + 0, 0, 0, 0, // STYLEALPHA_Zero + 0, 0, 0, 0, // STYLEALPHA_One + 24, 24, 24, 24, // STYLEALPHA_Src + 24, 24, 24, 24, // STYLEALPHA_InvSrc + 24, 16, 8, 0, // STYLEALPHA_SrcCol + 24, 16, 8, 0, // STYLEALPHA_InvSrcCol + 24, 16, 8, 0, // STYLEALPHA_DstCol + 24, 16, 8, 0 // STYLEALPHA_InvDstCol + }; + + bool invsrc = style.SrcAlpha & 1; + bool invdst = style.DestAlpha & 1; + + int srcinput = style.SrcAlpha <= STYLEALPHA_One ? 0 : (style.SrcAlpha >= STYLEALPHA_DstCol ? bg : fg); + int dstinput = style.DestAlpha <= STYLEALPHA_One ? 0 : (style.DestAlpha >= STYLEALPHA_DstCol ? bg : fg); + + const int* shiftsrc = shiftTable + (style.SrcAlpha << 2); + const int* shiftdst = shiftTable + (style.DestAlpha << 2); + + int32_t src[4], dst[4]; + for (int i = 0; i < 4; i++) + { + // Grab component for scale factors + src[i] = (srcinput >> shiftsrc[i]) & 0xff; + dst[i] = (dstinput >> shiftdst[i]) & 0xff; + + // Inverse if needed + src[i] = invsrc ? 0xff - src[i] : src[i]; + dst[i] = invdst ? 0xff - dst[i] : dst[i]; + + // Rescale 0-255 to 0-256 + src[i] = src[i] + (src[i] >> 7); + dst[i] = dst[i] + (dst[i] >> 7); + + // Multiply with input + src[i] = src[i] * ((fg >> (24 - (i << 3))) & 0xff); + dst[i] = dst[i] * ((bg >> (24 - (i << 3))) & 0xff); + } + + uint32_t out[4]; + switch (style.BlendOp) + { + default: + case STYLEOP_Add: for (int i = 0; i < 4; i++) out[i] = clamp((src[i] + dst[i] + 127) >> 8, 0, 255); break; + case STYLEOP_Sub: for (int i = 0; i < 4; i++) out[i] = clamp((src[i] - dst[i] + 127) >> 8, 0, 255); break; + case STYLEOP_RevSub: for (int i = 0; i < 4; i++) out[i] = clamp((dst[i] - src[i] + 127) >> 8, 0, 255); break; + } + return MAKEARGB(out[0], out[1], out[2], out[3]); +} + +static void WriteColor(int y, int x0, int x1, PolyTriangleThreadData* thread) { uint32_t* dest = (uint32_t*)thread->dest; uint32_t* line = dest + y * (ptrdiff_t)thread->dest_pitch; + FRenderStyle style = thread->RenderStyle; + uint32_t* fragcolor = thread->scanline.FragColor; - if (!thread->AlphaTest) + if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero) { - for (int x = x0; x < x1; x++) + if (!thread->AlphaTest) { - line[x] = thread->scanline.FragColor[x]; + for (int x = x0; x < x1; x++) + { + line[x] = fragcolor[x]; + } + } + else + { + for (int x = x0; x < x1; x++) + { + if (fragcolor[x] > 0x7f000000) + line[x] = fragcolor[x]; + } } } else { - uint32_t* fragcolor = thread->scanline.FragColor; - for (int x = x0; x < x1; x++) + if (!thread->AlphaTest) { - if (fragcolor[x] > 0x7f000000) - line[x] = thread->scanline.FragColor[x]; + for (int x = x0; x < x1; x++) + { + line[x] = BlendColor(style, fragcolor[x], line[x]); + } + } + else + { + for (int x = x0; x < x1; x++) + { + if (fragcolor[x] > 0x7f000000) + line[x] = BlendColor(style, fragcolor[x], line[x]); + } } } } @@ -173,7 +248,7 @@ static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, Pol RunShader(x0, x1, thread); if (thread->drawargs.WriteColor()) - WriteBlend(y, x0, x1, thread); + WriteColor(y, x0, x1, thread); if (thread->drawargs.WriteDepth()) WriteDepth(y, x0, x1, thread); if (thread->drawargs.WriteStencil()) From 82a17572ef835e2dce10b48662a000c2c9381a9c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 5 Aug 2019 19:32:54 +0200 Subject: [PATCH 36/60] - implement getTexel part of main.fp --- .../polyrenderer/drawers/poly_triangle.cpp | 81 +--------- .../polyrenderer/drawers/poly_triangle.h | 1 + .../polyrenderer/drawers/screen_triangle.cpp | 145 ++++++++++++++++-- 3 files changed, 145 insertions(+), 82 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index e676a3506..e5e6c1404 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -303,16 +303,7 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu mainVertexShader.Data = data; mainVertexShader.uClipSplit = constants.uClipSplit; - FColormap cm; - cm.Clear(); - if (constants.uLightLevel >= 0.0f) - { - drawargs.SetLight(GetColorTable(cm), (int)(constants.uLightLevel * 255.0f), mainVertexShader.Viewpoint->mGlobVis * 32.0f, false); - } - else - { - drawargs.SetLight(GetColorTable(cm), 255, mainVertexShader.Viewpoint->mGlobVis * 32.0f, true); - } + PushConstants = &constants; int numLights = 0; if (constants.uLightIndex >= 0) @@ -350,74 +341,18 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu } drawargs.SetLights(polyLights, numLights); - if (SpecialEffect != EFF_NONE) +#if 0 + FColormap cm; + cm.Clear(); + if (constants.uLightLevel >= 0.0f) { - // To do: need new drawers for these - switch (SpecialEffect) - { - default: break; - case EFF_FOGBOUNDARY: drawargs.SetStyle(TriBlendMode::FogBoundary); break; - case EFF_SPHEREMAP: drawargs.SetStyle(TriBlendMode::Fill); break; - case EFF_BURN: drawargs.SetStyle(TriBlendMode::Fill); break; - case EFF_STENCIL: drawargs.SetStyle(TriBlendMode::Fill); break; - } + drawargs.SetLight(GetColorTable(cm), (int)(constants.uLightLevel * 255.0f), mainVertexShader.Viewpoint->mGlobVis * 32.0f, false); } else { - switch (EffectState) - { - default: - break; - case SHADER_Paletted: - break; - case SHADER_NoTexture: - drawargs.SetStyle(TriBlendMode::FillTranslucent); - return; - case SHADER_BasicFuzz: - case SHADER_SmoothFuzz: - case SHADER_SwirlyFuzz: - case SHADER_TranslucentFuzz: - case SHADER_JaggedFuzz: - case SHADER_NoiseFuzz: - case SHADER_SmoothNoiseFuzz: - case SHADER_SoftwareFuzz: - drawargs.SetStyle(TriBlendMode::Fuzzy); - return; - } - - auto style = RenderStyle; - if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero) - { - drawargs.SetStyle(AlphaTest ? TriBlendMode::AlphaTest : TriBlendMode::Opaque); - } - else if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_Src && style.DestAlpha == STYLEALPHA_InvSrc) - { - drawargs.SetStyle(TriBlendMode::Normal); - } - else if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_SrcCol && style.DestAlpha == STYLEALPHA_One) - { - drawargs.SetStyle(TriBlendMode::SrcColor); - } - else - { - if (style == LegacyRenderStyles[STYLE_Normal]) drawargs.SetStyle(TriBlendMode::Normal); - else if (style == LegacyRenderStyles[STYLE_Stencil]) drawargs.SetStyle(TriBlendMode::Stencil); - else if (style == LegacyRenderStyles[STYLE_Translucent]) drawargs.SetStyle(TriBlendMode::Translucent); - else if (style == LegacyRenderStyles[STYLE_Add]) drawargs.SetStyle(TriBlendMode::Add); - //else if (style == LegacyRenderStyles[STYLE_Shaded]) drawargs.SetStyle(TriBlendMode::Shaded); - else if (style == LegacyRenderStyles[STYLE_TranslucentStencil]) drawargs.SetStyle(TriBlendMode::TranslucentStencil); - else if (style == LegacyRenderStyles[STYLE_Shadow]) drawargs.SetStyle(TriBlendMode::Shadow); - else if (style == LegacyRenderStyles[STYLE_Subtract]) drawargs.SetStyle(TriBlendMode::Subtract); - else if (style == LegacyRenderStyles[STYLE_AddStencil]) drawargs.SetStyle(TriBlendMode::AddStencil); - else if (style == LegacyRenderStyles[STYLE_AddShaded]) drawargs.SetStyle(TriBlendMode::AddShaded); - //else if (style == LegacyRenderStyles[STYLE_Multiply]) drawargs.SetStyle(TriBlendMode::Multiply); - //else if (style == LegacyRenderStyles[STYLE_InverseMultiply]) drawargs.SetStyle(TriBlendMode::InverseMultiply); - //else if (style == LegacyRenderStyles[STYLE_ColorBlend]) drawargs.SetStyle(TriBlendMode::ColorBlend); - else if (style == LegacyRenderStyles[STYLE_Source]) drawargs.SetStyle(TriBlendMode::Opaque); - //else if (style == LegacyRenderStyles[STYLE_ColorAdd]) drawargs.SetStyle(TriBlendMode::ColorAdd); - else drawargs.SetStyle(TriBlendMode::Opaque); - } + drawargs.SetLight(GetColorTable(cm), 255, mainVertexShader.Viewpoint->mGlobVis * 32.0f, true); } +#endif } void PolyTriangleThreadData::PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 4f365ca04..4bf2e4a1c 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -238,6 +238,7 @@ public: int SpecialEffect = EFF_NONE; int EffectState = 0; bool AlphaTest = false; + const PolyPushConstants* PushConstants = nullptr; PolyDrawArgs drawargs; diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 7d74f564e..28b120e98 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -37,6 +37,7 @@ #include "swrenderer/drawers/r_draw_rgba.h" #include "screen_triangle.h" #include "x86.h" +#include static void WriteW(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) { @@ -219,29 +220,155 @@ static void WriteStencil(int y, int x0, int x1, PolyTriangleThreadData* thread) } } +static float wrap(float value) +{ + return value - std::floor(value); +} + +static uint32_t sampleTexture(float u, float v, const uint32_t* texPixels, int texWidth, int texHeight) +{ + int texelX = static_cast(wrap(u) * texWidth); + int texelY = static_cast(wrap(v) * texHeight); + return texPixels[texelX * texHeight + texelY]; +} + static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) { int texWidth = thread->drawargs.TextureWidth(); int texHeight = thread->drawargs.TextureHeight(); const uint32_t* texPixels = (const uint32_t*)thread->drawargs.TexturePixels(); + auto constants = thread->PushConstants; + uint32_t* fragcolor = thread->scanline.FragColor; + float* u = thread->scanline.U; + float* v = thread->scanline.V; + switch (constants->uTextureMode) + { + default: + case TM_NORMAL: + case TM_FOGLAYER: + for (int x = x0; x < x1; x++) + { + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + fragcolor[x] = texel; + } + break; + case TM_STENCIL: // TM_STENCIL + for (int x = x0; x < x1; x++) + { + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + fragcolor[x] = texel | 0x00ffffff; + } + break; + case TM_OPAQUE: + for (int x = x0; x < x1; x++) + { + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + fragcolor[x] = texel | 0xff000000; + } + break; + case TM_INVERSE: + for (int x = x0; x < x1; x++) + { + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + fragcolor[x] = MAKEARGB(APART(texel), 0xff - RPART(texel), 0xff - BPART(texel), 0xff - GPART(texel)); + } + break; + case TM_ALPHATEXTURE: + for (int x = x0; x < x1; x++) + { + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + uint32_t gray = (RPART(texel) * 77 + GPART(texel) * 143 + BPART(texel) * 37) >> 8; + uint32_t alpha = APART(texel); + alpha += alpha >> 7; + alpha = (alpha * gray + 127) >> 8; + texel = (alpha << 24) | 0x00ffffff; + fragcolor[x] = texel; + } + break; + case TM_CLAMPY: + for (int x = x0; x < x1; x++) + { + if (v[x] >= 0.0 && v[x] <= 1.0) + fragcolor[x] = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + else + fragcolor[x] = 0; + } + break; + case TM_INVERTOPAQUE: + for (int x = x0; x < x1; x++) + { + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + fragcolor[x] = MAKEARGB(0xff, 0xff - RPART(texel), 0xff - BPART(texel), 0xff - GPART(texel)); + } + } + +#if 0 + if (constants->uTextureMode != TM_FOGLAYER) + { + texel.rgb += uAddColor.rgb; + + if (uObjectColor2.a == 0.0) texel *= uObjectColor; + else texel *= mix(uObjectColor, uObjectColor2, gradientdist.z); + texel = desaturate(texel); + } +#endif + +#if 0 for (int x = x0; x < x1; x++) { - float u = thread->scanline.U[x]; - float v = thread->scanline.V[x]; - u -= std::floor(u); - v -= std::floor(v); + uint32_t texel = fragcolor[x]; - int texelX = (int)(u * texWidth); - int texelY = (int)(v * texHeight); - uint32_t fg = texPixels[texelX * texHeight + texelY]; - thread->scanline.FragColor[x] = fg; + //#ifndef NO_ALPHATEST + //if (texel.a <= uAlphaThreshold) discard; + //#endif + + if (constants->uFogEnabled != -3) // check for special 2D 'fog' mode. + { + float fogdist = 0.0f; + float fogfactor = 0.0f; + + // calculate fog factor + if (constants->uFogEnabled != 0) + { + if (constants->uFogEnabled == 1 || constants->uFogEnabled == -1) + fogdist = max(16.0, pixelpos.w); + else + fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz)); + fogfactor = exp2(constants->uFogDensity * fogdist); + } + + if (constants->uTextureMode != 7) + { + texel = getLightColor(texel, fogdist, fogfactor); + if (constants->uFogEnabled < 0) + texel = applyFog(texel, fogfactor); + } + else + { + texel = vec4(uFogColor.rgb, (1.0 - fogfactor) * texel.a * 0.75 * vColor.a); + } + } + else // simple 2D (uses the fog color to add a color overlay) + { + if (constants->uTextureMode == 7) + { + float gray = grayscale(texel); + vec4 cm = (uObjectColor + gray * (uAddColor - uObjectColor)) * 2; + texel = vec4(clamp(cm.rgb, 0.0, 1.0), texel.a); + } + texel = texel * ProcessLight(texel, vColor); + texel.rgb = texel.rgb + uFogColor.rgb; + } + + fragcolor[x] = texel; } +#endif } static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) { - if (thread->drawargs.BlendMode() == TriBlendMode::Fill || thread->drawargs.BlendMode() == TriBlendMode::FillTranslucent) + if (thread->SpecialEffect != EFF_NONE || !(thread->EffectState == SHADER_Default || thread->EffectState == SHADER_Brightmap)) return; WriteVaryings(y, x0, x1, args, thread); From 4e24fdacf0a104e6578f548c81732601966a288a Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 5 Aug 2019 23:31:56 +0200 Subject: [PATCH 37/60] - implement more of the default shader --- .../polyrenderer/drawers/screen_triangle.cpp | 140 +++++++++++------- 1 file changed, 88 insertions(+), 52 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 28b120e98..80d61d8ee 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -238,6 +238,7 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) int texHeight = thread->drawargs.TextureHeight(); const uint32_t* texPixels = (const uint32_t*)thread->drawargs.TexturePixels(); auto constants = thread->PushConstants; + auto& streamdata = thread->mainVertexShader.Data; uint32_t* fragcolor = thread->scanline.FragColor; float* u = thread->scanline.U; float* v = thread->scanline.V; @@ -303,67 +304,102 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) } } -#if 0 if (constants->uTextureMode != TM_FOGLAYER) { - texel.rgb += uAddColor.rgb; + if (streamdata.uAddColor.r != 0.0f || streamdata.uAddColor.g != 0.0f || streamdata.uAddColor.b != 0.0f) + { + uint32_t r = (int)(streamdata.uAddColor.r * 255.0f); + uint32_t g = (int)(streamdata.uAddColor.g * 255.0f); + uint32_t b = (int)(streamdata.uAddColor.b * 255.0f); + for (int x = x0; x < x1; x++) + { + uint32_t texel = fragcolor[x]; + fragcolor[x] = MAKEARGB( + APART(texel), + MIN(r + RPART(texel), (uint32_t)255), + MIN(g + GPART(texel), (uint32_t)255), + MIN(b + BPART(texel), (uint32_t)255)); + } + } - if (uObjectColor2.a == 0.0) texel *= uObjectColor; - else texel *= mix(uObjectColor, uObjectColor2, gradientdist.z); - texel = desaturate(texel); + if (streamdata.uObjectColor2.a == 0.0f) + { + if (streamdata.uObjectColor.r != 0.0f || streamdata.uObjectColor.g != 0.0f || streamdata.uObjectColor.b != 0.0f) + { + uint32_t r = (int)(streamdata.uObjectColor.r * 256.0f); + uint32_t g = (int)(streamdata.uObjectColor.g * 256.0f); + uint32_t b = (int)(streamdata.uObjectColor.b * 256.0f); + for (int x = x0; x < x1; x++) + { + uint32_t texel = fragcolor[x]; + fragcolor[x] = MAKEARGB( + APART(texel), + MIN((r * RPART(texel)) >> 8, (uint32_t)255), + MIN((g * GPART(texel)) >> 8, (uint32_t)255), + MIN((b * BPART(texel)) >> 8, (uint32_t)255)); + } + } + } + else + { + float t = thread->mainVertexShader.gradientdist.Z; + float inv_t = 1.0f - t; + uint32_t r = (int)((streamdata.uObjectColor.r * inv_t + streamdata.uObjectColor2.r * t) * 256.0f); + uint32_t g = (int)((streamdata.uObjectColor.g * inv_t + streamdata.uObjectColor2.r * t) * 256.0f); + uint32_t b = (int)((streamdata.uObjectColor.b * inv_t + streamdata.uObjectColor2.r * t) * 256.0f); + for (int x = x0; x < x1; x++) + { + uint32_t texel = fragcolor[x]; + fragcolor[x] = MAKEARGB( + APART(texel), + MIN((r * RPART(texel)) >> 8, (uint32_t)255), + MIN((g * GPART(texel)) >> 8, (uint32_t)255), + MIN((b * BPART(texel)) >> 8, (uint32_t)255)); + } + } + + if (streamdata.uDesaturationFactor > 0.0f) + { + uint32_t t = (int)(streamdata.uDesaturationFactor * 256.0f); + uint32_t inv_t = 256 - t; + for (int x = x0; x < x1; x++) + { + uint32_t texel = fragcolor[x]; + uint32_t gray = (RPART(texel) * 77 + GPART(texel) * 143 + BPART(texel) * 37) >> 8; + fragcolor[x] = MAKEARGB( + APART(texel), + (RPART(texel) * inv_t + gray * t + 127) >> 8, + (GPART(texel) * inv_t + gray * t + 127) >> 8, + (BPART(texel) * inv_t + gray * t + 127) >> 8); + } + } } -#endif -#if 0 - for (int x = x0; x < x1; x++) + if (thread->mainVertexShader.vColor != 0xffffffff) { - uint32_t texel = fragcolor[x]; - - //#ifndef NO_ALPHATEST - //if (texel.a <= uAlphaThreshold) discard; - //#endif - - if (constants->uFogEnabled != -3) // check for special 2D 'fog' mode. + uint32_t a = APART(thread->mainVertexShader.vColor); + uint32_t r = RPART(thread->mainVertexShader.vColor); + uint32_t g = GPART(thread->mainVertexShader.vColor); + uint32_t b = BPART(thread->mainVertexShader.vColor); + a += a >> 7; + r += r >> 7; + g += g >> 7; + b += b >> 7; + for (int x = x0; x < x1; x++) { - float fogdist = 0.0f; - float fogfactor = 0.0f; - - // calculate fog factor - if (constants->uFogEnabled != 0) - { - if (constants->uFogEnabled == 1 || constants->uFogEnabled == -1) - fogdist = max(16.0, pixelpos.w); - else - fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz)); - fogfactor = exp2(constants->uFogDensity * fogdist); - } - - if (constants->uTextureMode != 7) - { - texel = getLightColor(texel, fogdist, fogfactor); - if (constants->uFogEnabled < 0) - texel = applyFog(texel, fogfactor); - } - else - { - texel = vec4(uFogColor.rgb, (1.0 - fogfactor) * texel.a * 0.75 * vColor.a); - } + uint32_t texel = fragcolor[x]; + fragcolor[x] = MAKEARGB( + (APART(texel) * a + 127) >> 8, + (RPART(texel) * r + 127) >> 8, + (GPART(texel) * g + 127) >> 8, + (BPART(texel) * b + 127) >> 8); } - else // simple 2D (uses the fog color to add a color overlay) - { - if (constants->uTextureMode == 7) - { - float gray = grayscale(texel); - vec4 cm = (uObjectColor + gray * (uAddColor - uObjectColor)) * 2; - texel = vec4(clamp(cm.rgb, 0.0, 1.0), texel.a); - } - texel = texel * ProcessLight(texel, vColor); - texel.rgb = texel.rgb + uFogColor.rgb; - } - - fragcolor[x] = texel; } -#endif + + if (constants->uLightLevel >= 0.0f) + { + // To do: apply diminishing light and fog + } } static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) From eb127d0dacc2411b360131597dcdd0a7c5e419f3 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 6 Aug 2019 04:51:37 +0200 Subject: [PATCH 38/60] - implement more shaders --- .../polyrenderer/drawers/poly_triangle.cpp | 2 + .../polyrenderer/drawers/screen_triangle.cpp | 259 +++++++++++------- 2 files changed, 156 insertions(+), 105 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index e5e6c1404..6a2aff9b3 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -599,6 +599,8 @@ void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode) ShadedTriVertex PolyTriangleThreadData::ShadeVertex(int index) { inputAssembly->Load(this, vertices, index); + mainVertexShader.SIMPLE = (SpecialEffect == EFF_BURN) || (SpecialEffect == EFF_STENCIL); + mainVertexShader.SPHEREMAP = (SpecialEffect == EFF_SPHEREMAP); mainVertexShader.main(); return mainVertexShader; } diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 80d61d8ee..0168c073b 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -234,101 +234,170 @@ static uint32_t sampleTexture(float u, float v, const uint32_t* texPixels, int t static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) { - int texWidth = thread->drawargs.TextureWidth(); - int texHeight = thread->drawargs.TextureHeight(); - const uint32_t* texPixels = (const uint32_t*)thread->drawargs.TexturePixels(); auto constants = thread->PushConstants; auto& streamdata = thread->mainVertexShader.Data; uint32_t* fragcolor = thread->scanline.FragColor; float* u = thread->scanline.U; float* v = thread->scanline.V; - - switch (constants->uTextureMode) + + if (thread->SpecialEffect == EFF_FOGBOUNDARY) // fogboundary.fp + { + /*float fogdist = pixelpos.w; + float fogfactor = exp2(uFogDensity * fogdist); + FragColor = vec4(uFogColor.rgb, 1.0 - fogfactor);*/ + return; + } + else if (thread->SpecialEffect == EFF_BURN) // burn.fp + { + /*vec4 frag = vColor; + vec4 t1 = texture(tex, vTexCoord.xy); + vec4 t2 = texture(texture2, vec2(vTexCoord.x, 1.0-vTexCoord.y)); + FragColor = frag * vec4(t1.rgb, t2.a);*/ + return; + } + else if (thread->SpecialEffect == EFF_STENCIL) // stencil.fp { - default: - case TM_NORMAL: - case TM_FOGLAYER: for (int x = x0; x < x1; x++) { - uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); - fragcolor[x] = texel; + fragcolor[x] = 0x00ffffff; } - break; - case TM_STENCIL: // TM_STENCIL - for (int x = x0; x < x1; x++) + return; + } + else if (thread->EffectState == SHADER_NoTexture) // func_notexture + { + uint32_t a = (int)(streamdata.uObjectColor.a * 255.0f); + uint32_t r = (int)(streamdata.uObjectColor.r * 255.0f); + uint32_t g = (int)(streamdata.uObjectColor.g * 255.0f); + uint32_t b = (int)(streamdata.uObjectColor.b * 255.0f); + uint32_t texel = MAKEARGB(a, r, g, b); + + if (streamdata.uDesaturationFactor > 0.0f) { - uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); - fragcolor[x] = texel | 0x00ffffff; - } - break; - case TM_OPAQUE: - for (int x = x0; x < x1; x++) - { - uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); - fragcolor[x] = texel | 0xff000000; - } - break; - case TM_INVERSE: - for (int x = x0; x < x1; x++) - { - uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); - fragcolor[x] = MAKEARGB(APART(texel), 0xff - RPART(texel), 0xff - BPART(texel), 0xff - GPART(texel)); - } - break; - case TM_ALPHATEXTURE: - for (int x = x0; x < x1; x++) - { - uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + uint32_t t = (int)(streamdata.uDesaturationFactor * 256.0f); + uint32_t inv_t = 256 - t; uint32_t gray = (RPART(texel) * 77 + GPART(texel) * 143 + BPART(texel) * 37) >> 8; - uint32_t alpha = APART(texel); - alpha += alpha >> 7; - alpha = (alpha * gray + 127) >> 8; - texel = (alpha << 24) | 0x00ffffff; + texel = MAKEARGB( + APART(texel), + (RPART(texel) * inv_t + gray * t + 127) >> 8, + (GPART(texel) * inv_t + gray * t + 127) >> 8, + (BPART(texel) * inv_t + gray * t + 127) >> 8); + } + + for (int x = x0; x < x1; x++) + { fragcolor[x] = texel; } - break; - case TM_CLAMPY: - for (int x = x0; x < x1; x++) - { - if (v[x] >= 0.0 && v[x] <= 1.0) - fragcolor[x] = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); - else - fragcolor[x] = 0; - } - break; - case TM_INVERTOPAQUE: - for (int x = x0; x < x1; x++) - { - uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); - fragcolor[x] = MAKEARGB(0xff, 0xff - RPART(texel), 0xff - BPART(texel), 0xff - GPART(texel)); - } } - - if (constants->uTextureMode != TM_FOGLAYER) + else // func_normal { - if (streamdata.uAddColor.r != 0.0f || streamdata.uAddColor.g != 0.0f || streamdata.uAddColor.b != 0.0f) + int texWidth = thread->drawargs.TextureWidth(); + int texHeight = thread->drawargs.TextureHeight(); + const uint32_t* texPixels = (const uint32_t*)thread->drawargs.TexturePixels(); + + switch (constants->uTextureMode) { - uint32_t r = (int)(streamdata.uAddColor.r * 255.0f); - uint32_t g = (int)(streamdata.uAddColor.g * 255.0f); - uint32_t b = (int)(streamdata.uAddColor.b * 255.0f); + default: + case TM_NORMAL: + case TM_FOGLAYER: for (int x = x0; x < x1; x++) { - uint32_t texel = fragcolor[x]; - fragcolor[x] = MAKEARGB( - APART(texel), - MIN(r + RPART(texel), (uint32_t)255), - MIN(g + GPART(texel), (uint32_t)255), - MIN(b + BPART(texel), (uint32_t)255)); + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + fragcolor[x] = texel; + } + break; + case TM_STENCIL: // TM_STENCIL + for (int x = x0; x < x1; x++) + { + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + fragcolor[x] = texel | 0x00ffffff; + } + break; + case TM_OPAQUE: + for (int x = x0; x < x1; x++) + { + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + fragcolor[x] = texel | 0xff000000; + } + break; + case TM_INVERSE: + for (int x = x0; x < x1; x++) + { + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + fragcolor[x] = MAKEARGB(APART(texel), 0xff - RPART(texel), 0xff - BPART(texel), 0xff - GPART(texel)); + } + break; + case TM_ALPHATEXTURE: + for (int x = x0; x < x1; x++) + { + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + uint32_t gray = (RPART(texel) * 77 + GPART(texel) * 143 + BPART(texel) * 37) >> 8; + uint32_t alpha = APART(texel); + alpha += alpha >> 7; + alpha = (alpha * gray + 127) >> 8; + texel = (alpha << 24) | 0x00ffffff; + fragcolor[x] = texel; + } + break; + case TM_CLAMPY: + for (int x = x0; x < x1; x++) + { + if (v[x] >= 0.0 && v[x] <= 1.0) + fragcolor[x] = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + else + fragcolor[x] = 0; + } + break; + case TM_INVERTOPAQUE: + for (int x = x0; x < x1; x++) + { + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + fragcolor[x] = MAKEARGB(0xff, 0xff - RPART(texel), 0xff - BPART(texel), 0xff - GPART(texel)); } } - if (streamdata.uObjectColor2.a == 0.0f) + if (constants->uTextureMode != TM_FOGLAYER) { - if (streamdata.uObjectColor.r != 0.0f || streamdata.uObjectColor.g != 0.0f || streamdata.uObjectColor.b != 0.0f) + if (streamdata.uAddColor.r != 0.0f || streamdata.uAddColor.g != 0.0f || streamdata.uAddColor.b != 0.0f) { - uint32_t r = (int)(streamdata.uObjectColor.r * 256.0f); - uint32_t g = (int)(streamdata.uObjectColor.g * 256.0f); - uint32_t b = (int)(streamdata.uObjectColor.b * 256.0f); + uint32_t r = (int)(streamdata.uAddColor.r * 255.0f); + uint32_t g = (int)(streamdata.uAddColor.g * 255.0f); + uint32_t b = (int)(streamdata.uAddColor.b * 255.0f); + for (int x = x0; x < x1; x++) + { + uint32_t texel = fragcolor[x]; + fragcolor[x] = MAKEARGB( + APART(texel), + MIN(r + RPART(texel), (uint32_t)255), + MIN(g + GPART(texel), (uint32_t)255), + MIN(b + BPART(texel), (uint32_t)255)); + } + } + + if (streamdata.uObjectColor2.a == 0.0f) + { + if (streamdata.uObjectColor.r != 0.0f || streamdata.uObjectColor.g != 0.0f || streamdata.uObjectColor.b != 0.0f) + { + uint32_t r = (int)(streamdata.uObjectColor.r * 256.0f); + uint32_t g = (int)(streamdata.uObjectColor.g * 256.0f); + uint32_t b = (int)(streamdata.uObjectColor.b * 256.0f); + for (int x = x0; x < x1; x++) + { + uint32_t texel = fragcolor[x]; + fragcolor[x] = MAKEARGB( + APART(texel), + MIN((r * RPART(texel)) >> 8, (uint32_t)255), + MIN((g * GPART(texel)) >> 8, (uint32_t)255), + MIN((b * BPART(texel)) >> 8, (uint32_t)255)); + } + } + } + else + { + float t = thread->mainVertexShader.gradientdist.Z; + float inv_t = 1.0f - t; + uint32_t r = (int)((streamdata.uObjectColor.r * inv_t + streamdata.uObjectColor2.r * t) * 256.0f); + uint32_t g = (int)((streamdata.uObjectColor.g * inv_t + streamdata.uObjectColor2.r * t) * 256.0f); + uint32_t b = (int)((streamdata.uObjectColor.b * inv_t + streamdata.uObjectColor2.r * t) * 256.0f); for (int x = x0; x < x1; x++) { uint32_t texel = fragcolor[x]; @@ -339,38 +408,21 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) MIN((b * BPART(texel)) >> 8, (uint32_t)255)); } } - } - else - { - float t = thread->mainVertexShader.gradientdist.Z; - float inv_t = 1.0f - t; - uint32_t r = (int)((streamdata.uObjectColor.r * inv_t + streamdata.uObjectColor2.r * t) * 256.0f); - uint32_t g = (int)((streamdata.uObjectColor.g * inv_t + streamdata.uObjectColor2.r * t) * 256.0f); - uint32_t b = (int)((streamdata.uObjectColor.b * inv_t + streamdata.uObjectColor2.r * t) * 256.0f); - for (int x = x0; x < x1; x++) - { - uint32_t texel = fragcolor[x]; - fragcolor[x] = MAKEARGB( - APART(texel), - MIN((r * RPART(texel)) >> 8, (uint32_t)255), - MIN((g * GPART(texel)) >> 8, (uint32_t)255), - MIN((b * BPART(texel)) >> 8, (uint32_t)255)); - } - } - if (streamdata.uDesaturationFactor > 0.0f) - { - uint32_t t = (int)(streamdata.uDesaturationFactor * 256.0f); - uint32_t inv_t = 256 - t; - for (int x = x0; x < x1; x++) + if (streamdata.uDesaturationFactor > 0.0f) { - uint32_t texel = fragcolor[x]; - uint32_t gray = (RPART(texel) * 77 + GPART(texel) * 143 + BPART(texel) * 37) >> 8; - fragcolor[x] = MAKEARGB( - APART(texel), - (RPART(texel) * inv_t + gray * t + 127) >> 8, - (GPART(texel) * inv_t + gray * t + 127) >> 8, - (BPART(texel) * inv_t + gray * t + 127) >> 8); + uint32_t t = (int)(streamdata.uDesaturationFactor * 256.0f); + uint32_t inv_t = 256 - t; + for (int x = x0; x < x1; x++) + { + uint32_t texel = fragcolor[x]; + uint32_t gray = (RPART(texel) * 77 + GPART(texel) * 143 + BPART(texel) * 37) >> 8; + fragcolor[x] = MAKEARGB( + APART(texel), + (RPART(texel) * inv_t + gray * t + 127) >> 8, + (GPART(texel) * inv_t + gray * t + 127) >> 8, + (BPART(texel) * inv_t + gray * t + 127) >> 8); + } } } } @@ -404,9 +456,6 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) { - if (thread->SpecialEffect != EFF_NONE || !(thread->EffectState == SHADER_Default || thread->EffectState == SHADER_Brightmap)) - return; - WriteVaryings(y, x0, x1, args, thread); RunShader(x0, x1, thread); From b34658d4d8227072142ebc0222531ea8d9c155d7 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 6 Aug 2019 06:21:37 +0200 Subject: [PATCH 39/60] - fix out of bounds crash --- src/rendering/polyrenderer/drawers/screen_triangle.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 0168c073b..83dccffc5 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -227,8 +227,8 @@ static float wrap(float value) static uint32_t sampleTexture(float u, float v, const uint32_t* texPixels, int texWidth, int texHeight) { - int texelX = static_cast(wrap(u) * texWidth); - int texelY = static_cast(wrap(v) * texHeight); + int texelX = MIN(static_cast(wrap(u) * texWidth), texWidth - 1); + int texelY = MIN(static_cast(wrap(v) * texHeight), texHeight - 1); return texPixels[texelX * texHeight + texelY]; } @@ -257,10 +257,10 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) } else if (thread->SpecialEffect == EFF_STENCIL) // stencil.fp { - for (int x = x0; x < x1; x++) + /*for (int x = x0; x < x1; x++) { fragcolor[x] = 0x00ffffff; - } + }*/ return; } else if (thread->EffectState == SHADER_NoTexture) // func_notexture From 7746b2c6fd4d6315556cae539f16e5426c04dfd6 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 6 Aug 2019 07:15:07 +0200 Subject: [PATCH 40/60] - add light array --- .../polyrenderer/drawers/poly_triangle.cpp | 13 --- .../polyrenderer/drawers/poly_triangle.h | 4 +- .../polyrenderer/drawers/screen_triangle.cpp | 81 ++++++++++++++++++- 3 files changed, 81 insertions(+), 17 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 6a2aff9b3..650784485 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -340,19 +340,6 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu } } drawargs.SetLights(polyLights, numLights); - -#if 0 - FColormap cm; - cm.Clear(); - if (constants.uLightLevel >= 0.0f) - { - drawargs.SetLight(GetColorTable(cm), (int)(constants.uLightLevel * 255.0f), mainVertexShader.Viewpoint->mGlobVis * 32.0f, false); - } - else - { - drawargs.SetLight(GetColorTable(cm), 255, mainVertexShader.Viewpoint->mGlobVis * 32.0f, true); - } -#endif } void PolyTriangleThreadData::PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 4bf2e4a1c..619cf6c16 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -207,10 +207,8 @@ public: float WorldY[MAXWIDTH]; float WorldZ[MAXWIDTH]; uint32_t FragColor[MAXWIDTH]; -#if 0 uint16_t lightarray[MAXWIDTH]; - uint32_t dynlights[MAXWIDTH]; -#endif + //uint32_t dynlights[MAXWIDTH]; } scanline; static PolyTriangleThreadData *Get(DrawerThread *thread); diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 83dccffc5..ddbb5ce2c 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -54,6 +54,69 @@ static void WriteW(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyT } } +static void WriteLightArray(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) +{ + float startX = x0 + (0.5f - args->v1->x); + float startY = y + (0.5f - args->v1->y); + float posW = args->v1->w + args->gradientX.W * startX + args->gradientY.W * startY; + float stepW = args->gradientX.W; + + float globVis = thread->mainVertexShader.Viewpoint->mGlobVis; + + uint32_t light = (int)(thread->PushConstants->uLightLevel * 255.0f); + fixed_t shade = (fixed_t)((2.0f - (light + 12.0f) / 128.0f) * (float)FRACUNIT); + fixed_t lightpos = (fixed_t)(globVis * posW * (float)FRACUNIT); + fixed_t lightstep = (fixed_t)(globVis * stepW * (float)FRACUNIT); + + fixed_t maxvis = 24 * FRACUNIT / 32; + fixed_t maxlight = 31 * FRACUNIT / 32; + + uint16_t *lightarray = thread->scanline.lightarray; + + fixed_t lightend = lightpos + lightstep * (x1 - x0); + if (lightpos < maxvis && shade >= lightpos && shade - lightpos <= maxlight && + lightend < maxvis && shade >= lightend && shade - lightend <= maxlight) + { + //if (BitsPerPixel == 32) + { + lightpos += FRACUNIT - shade; + for (int x = x0; x < x1; x++) + { + lightarray[x] = lightpos >> 8; + lightpos += lightstep; + } + } + /*else + { + lightpos = shade - lightpos; + for (int x = x0; x < x1; x++) + { + lightarray[x] = (lightpos >> 3) & 0xffffff00; + lightpos -= lightstep; + } + }*/ + } + else + { + //if (BitsPerPixel == 32) + { + for (int x = x0; x < x1; x++) + { + lightarray[x] = (FRACUNIT - clamp(shade - MIN(maxvis, lightpos), 0, maxlight)) >> 8; + lightpos += lightstep; + } + } + /*else + { + for (int x = x0; x < x1; x++) + { + lightarray[x] = (clamp(shade - MIN(maxvis, lightpos), 0, maxlight) >> 3) & 0xffffff00; + lightpos += lightstep; + } + }*/ + } +} + static void WriteVarying(float pos, float step, int x0, int x1, const float* w, float* varying) { for (int x = x0; x < x1; x++) @@ -450,13 +513,29 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) if (constants->uLightLevel >= 0.0f) { - // To do: apply diminishing light and fog + uint16_t* lightarray = thread->scanline.lightarray; + for (int x = x0; x < x1; x++) + { + uint32_t fg = fragcolor[x]; + int lightshade = lightarray[x]; + fragcolor[x] = MAKEARGB( + APART(fg), + (RPART(fg) * lightshade) >> 8, + (GPART(fg) * lightshade) >> 8, + (BPART(fg) * lightshade) >> 8); + } + + // To do: apply fog } } static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) { WriteVaryings(y, x0, x1, args, thread); + + if (thread->PushConstants->uLightLevel >= 0.0f) + WriteLightArray(y, x0, x1, args, thread); + RunShader(x0, x1, thread); if (thread->drawargs.WriteColor()) From 2c751d214f3a71e6199226eae7c4a29b55e0b77a Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 1 Dec 2019 20:23:41 +0100 Subject: [PATCH 41/60] Hook up some SSE2 --- .../polyrenderer/drawers/screen_triangle.cpp | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index ddbb5ce2c..8faf2af63 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -39,6 +39,7 @@ #include "x86.h" #include +#ifdef NO_SSE static void WriteW(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) { float startX = x0 + (0.5f - args->v1->x); @@ -53,6 +54,36 @@ static void WriteW(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyT posW += stepW; } } +#else +static void WriteW(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) +{ + float startX = x0 + (0.5f - args->v1->x); + float startY = y + (0.5f - args->v1->y); + + float posW = args->v1->w + args->gradientX.W * startX + args->gradientY.W * startY; + float stepW = args->gradientX.W; + float* w = thread->scanline.W; + + int ssecount = ((x1 - x0) & 3); + int sseend = x0 + ssecount; + + __m128 mstepW = _mm_set1_ps(stepW * 4.0f); + __m128 mposW = _mm_setr_ps(posW, posW + stepW, posW + stepW + stepW, posW + stepW + stepW + stepW); + + for (int x = x0; x < sseend; x += 4) + { + _mm_storeu_ps(w + x, _mm_rcp_ps(mposW)); + mposW = _mm_add_ps(mposW, mstepW); + } + + posW += ssecount * stepW; + for (int x = sseend; x < x1; x++) + { + w[x] = 1.0f / posW; + posW += stepW; + } +} +#endif static void WriteLightArray(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) { @@ -117,6 +148,7 @@ static void WriteLightArray(int y, int x0, int x1, const TriDrawTriangleArgs* ar } } +#ifdef NO_SSE static void WriteVarying(float pos, float step, int x0, int x1, const float* w, float* varying) { for (int x = x0; x < x1; x++) @@ -125,6 +157,29 @@ static void WriteVarying(float pos, float step, int x0, int x1, const float* w, pos += step; } } +#else +static void WriteVarying(float pos, float step, int x0, int x1, const float* w, float* varying) +{ + int ssecount = ((x1 - x0) & 3); + int sseend = x0 + ssecount; + + __m128 mstep = _mm_set1_ps(step * 4.0f); + __m128 mpos = _mm_setr_ps(pos, pos + step, pos + step + step, pos + step + step + step); + + for (int x = x0; x < sseend; x += 4) + { + _mm_storeu_ps(varying + x, _mm_mul_ps(mpos, _mm_loadu_ps(w + x))); + mpos = _mm_add_ps(mpos, mstep); + } + + pos += ssecount * step; + for (int x = sseend; x < x1; x++) + { + varying[x] = pos * w[x]; + pos += step; + } +} +#endif static void WriteVaryings(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) { @@ -283,10 +338,18 @@ static void WriteStencil(int y, int x0, int x1, PolyTriangleThreadData* thread) } } +#ifdef NO_SSE static float wrap(float value) { return value - std::floor(value); } +#else +static float wrap(float value) +{ + __m128 mvalue = _mm_set_ss(value); + return _mm_cvtss_f32(_mm_sub_ss(mvalue, _mm_floor_ss(_mm_setzero_ps(), mvalue))); +} +#endif static uint32_t sampleTexture(float u, float v, const uint32_t* texPixels, int texWidth, int texHeight) { From 1b9479ea45ae8e349523a5a7a9e7e1341ed079f3 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 1 Dec 2019 21:44:44 +0100 Subject: [PATCH 42/60] Implement burn.fp and second texture binding --- .../polyrenderer/backend/poly_renderstate.cpp | 12 ++++++- .../polyrenderer/drawers/poly_draw_args.cpp | 7 ++++ .../polyrenderer/drawers/poly_draw_args.h | 8 +++++ .../polyrenderer/drawers/poly_triangle.cpp | 11 ++++--- .../polyrenderer/drawers/poly_triangle.h | 9 ++--- .../polyrenderer/drawers/screen_triangle.cpp | 33 ++++++++++++++++--- 6 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 4adf4a59b..046a5c467 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -233,7 +233,17 @@ void PolyRenderState::ApplyMaterial() if (base) { DCanvas *texcanvas = base->GetImage(mMaterial); - PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth()); + PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), 0, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth()); + + int numLayers = mMaterial.mMaterial->GetLayers(); + for (int i = 1; i < numLayers; i++) + { + FTexture* layer; + auto systex = static_cast(mMaterial.mMaterial->GetLayer(i, 0, &layer)); + + texcanvas = systex->GetImage(mMaterial); + PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), i, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth()); + } } mMaterial.mChanged = false; diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.cpp b/src/rendering/polyrenderer/drawers/poly_draw_args.cpp index 50e8a82ae..b18619b74 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.cpp @@ -59,6 +59,13 @@ void PolyDrawArgs::SetTexture(FSoftwareTexture *texture, FRenderStyle style) mTranslation = nullptr; } +void PolyDrawArgs::SetTexture2(const uint8_t* texels, int width, int height) +{ + mTexture2Pixels = texels; + mTexture2Width = width; + mTexture2Height = height; +} + void PolyDrawArgs::SetTexture(FSoftwareTexture *texture, uint32_t translationID, FRenderStyle style) { // Alphatexture overrides translations. diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.h b/src/rendering/polyrenderer/drawers/poly_draw_args.h index a681b5f37..2b89f9d1e 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.h +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.h @@ -71,6 +71,7 @@ public: void SetTexture(const uint8_t *texels, int width, int height); void SetTexture(FSoftwareTexture *texture, FRenderStyle style); void SetTexture(FSoftwareTexture *texture, uint32_t translationID, FRenderStyle style); + void SetTexture2(const uint8_t* texels, int width, int height); void SetLight(FSWColormap *basecolormap, uint32_t lightlevel, double globVis, bool fixed); void SetNoColormap() { mLight = 255; mFixedLight = true; mLightRed = 256; mLightGreen = 256; mLightBlue = 256; mLightAlpha = 256; mFadeRed = 0; mFadeGreen = 0; mFadeBlue = 0; mFadeAlpha = 0; mDesaturate = 0; mSimpleShade = true; mColormaps = nullptr; } void SetDepthTest(bool enable) { mDepthTest = enable; } @@ -95,6 +96,10 @@ public: int TextureHeight() const { return mTextureHeight; } const uint8_t *Translation() const { return mTranslation; } + const uint8_t* Texture2Pixels() const { return mTexture2Pixels; } + int Texture2Width() const { return mTexture2Width; } + int Texture2Height() const { return mTexture2Height; } + bool WriteStencil() const { return mWriteStencil; } bool StencilTest() const { return mStencilTest; } uint8_t StencilTestValue() const { return mStencilTestValue; } @@ -142,6 +147,9 @@ private: int mTextureWidth = 0; int mTextureHeight = 0; const uint8_t *mTranslation = nullptr; + const uint8_t* mTexture2Pixels = nullptr; + int mTexture2Width = 0; + int mTexture2Height = 0; uint8_t mStencilTestValue = 0; uint8_t mStencilWriteValue = 0; const uint8_t *mColormaps = nullptr; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 650784485..0afe496a5 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -183,9 +183,9 @@ void PolyTriangleDrawer::SetRenderStyle(const DrawerCommandQueuePtr &queue, FRen queue->Push(style); } -void PolyTriangleDrawer::SetTexture(const DrawerCommandQueuePtr &queue, void *pixels, int width, int height) +void PolyTriangleDrawer::SetTexture(const DrawerCommandQueuePtr &queue, int unit, void *pixels, int width, int height) { - queue->Push(pixels, width, height); + queue->Push(unit, pixels, width, height); } void PolyTriangleDrawer::SetShader(const DrawerCommandQueuePtr &queue, int specialEffect, int effectState, bool alphaTest) @@ -446,9 +446,12 @@ void PolyTriangleThreadData::SetShader(int specialEffect, int effectState, bool AlphaTest = alphaTest; } -void PolyTriangleThreadData::SetTexture(void *pixels, int width, int height) +void PolyTriangleThreadData::SetTexture(int unit, void *pixels, int width, int height) { - drawargs.SetTexture((uint8_t*)pixels, width, height); + if (unit == 0) + drawargs.SetTexture((uint8_t*)pixels, width, height); + else if (unit == 1) + drawargs.SetTexture2((uint8_t*)pixels, width, height); } void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode drawmode) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 619cf6c16..1e3cb1467 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -57,7 +57,7 @@ public: static void SetScissor(const DrawerCommandQueuePtr &queue, int x, int y, int w, int h); static void EnableDepthTest(const DrawerCommandQueuePtr &queue, bool on); static void SetRenderStyle(const DrawerCommandQueuePtr &queue, FRenderStyle style); - static void SetTexture(const DrawerCommandQueuePtr &queue, void *pixels, int width, int height); + static void SetTexture(const DrawerCommandQueuePtr &queue, int unit, void *pixels, int width, int height); static void SetShader(const DrawerCommandQueuePtr &queue, int specialEffect, int effectState, bool alphaTest); static void PushStreamData(const DrawerCommandQueuePtr &queue, const StreamData &data, const PolyPushConstants &constants); static void PushMatrices(const DrawerCommandQueuePtr &queue, const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); @@ -159,7 +159,7 @@ public: void SetScissor(int x, int y, int w, int h); void EnableDepthTest(bool on); void SetRenderStyle(FRenderStyle style); - void SetTexture(void *pixels, int width, int height); + void SetTexture(int unit, void *pixels, int width, int height); void SetShader(int specialEffect, int effectState, bool alphaTest); void UpdateClip(); @@ -423,10 +423,11 @@ private: class PolySetTextureCommand : public PolyDrawerCommand { public: - PolySetTextureCommand(void *pixels, int width, int height) : pixels(pixels), width(width), height(height) { } - void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetTexture(pixels, width, height); } + PolySetTextureCommand(int unit, void *pixels, int width, int height) : unit(unit), pixels(pixels), width(width), height(height) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetTexture(unit, pixels, width, height); } private: + int unit; void *pixels; int width; int height; diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 8faf2af63..66f3c9869 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -375,10 +375,35 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) } else if (thread->SpecialEffect == EFF_BURN) // burn.fp { - /*vec4 frag = vColor; - vec4 t1 = texture(tex, vTexCoord.xy); - vec4 t2 = texture(texture2, vec2(vTexCoord.x, 1.0-vTexCoord.y)); - FragColor = frag * vec4(t1.rgb, t2.a);*/ + int texWidth = thread->drawargs.TextureWidth(); + int texHeight = thread->drawargs.TextureHeight(); + const uint32_t* texPixels = (const uint32_t*)thread->drawargs.TexturePixels(); + + int tex2Width = thread->drawargs.Texture2Width(); + int tex2Height = thread->drawargs.Texture2Height(); + const uint32_t* tex2Pixels = (const uint32_t*)thread->drawargs.Texture2Pixels(); + + uint32_t frag = thread->mainVertexShader.vColor; + uint32_t frag_r = RPART(frag); + uint32_t frag_g = GPART(frag); + uint32_t frag_b = BPART(frag); + uint32_t frag_a = APART(frag); + frag_r += frag_r >> 7; // 255 -> 256 + frag_g += frag_g >> 7; // 255 -> 256 + frag_b += frag_b >> 7; // 255 -> 256 + frag_a += frag_a >> 7; // 255 -> 256 + for (int x = x0; x < x1; x++) + { + uint32_t t1 = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + uint32_t t2 = sampleTexture(u[x], 1.0f - v[x], tex2Pixels, tex2Width, tex2Height); + + uint32_t r = (frag_r * RPART(t1)) >> 8; + uint32_t g = (frag_g * GPART(t1)) >> 8; + uint32_t b = (frag_b * BPART(t1)) >> 8; + uint32_t a = (frag_a * APART(t2)) >> 8; + + fragcolor[x] = MAKEARGB(a, r, g, b); + } return; } else if (thread->SpecialEffect == EFF_STENCIL) // stencil.fp From 8ca05fe30ab9a3313e6b1016dc673cc76548fdc3 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 1 Dec 2019 22:05:10 +0100 Subject: [PATCH 43/60] Implement crossfade --- .../polyrenderer/backend/poly_hwtexture.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp index cd3102b53..a16b58287 100644 --- a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp +++ b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp @@ -121,6 +121,22 @@ void PolyHardwareTexture::CreateWipeTexture(int w, int h, const char *name) mCanvas.reset(new DCanvas(0, 0, true)); mCanvas->Resize(w, h, false); } + + auto fb = static_cast(screen); + + fb->FlushDrawCommands(); + DrawerThreads::WaitForWorkers(); + + uint32_t* dest = (uint32_t*)mCanvas->GetPixels(); + uint32_t* src = (uint32_t*)fb->GetCanvas()->GetPixels(); + int dpitch = mCanvas->GetPitch(); + int spitch = fb->GetCanvas()->GetPitch(); + int pixelsize = 4; + + for (int y = 0; y < h; y++) + { + memcpy(dest + dpitch * (h - 1 - y), src + spitch * y, w * pixelsize); + } } void PolyHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) From bdc7329d32af2e7dab3d17fc0e16e1321618a1bb Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 1 Dec 2019 16:06:36 -0500 Subject: [PATCH 44/60] - replace vid_enablevulkan with vid_preferbackend - disabled startup window selector for this (will replace when the startup screen changes are done) --- src/rendering/v_video.cpp | 6 +++++- src/win32/hardware.cpp | 16 ++++++++++------ src/win32/i_system.cpp | 3 ++- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/rendering/v_video.cpp b/src/rendering/v_video.cpp index f587d3d7f..9beb8e36b 100644 --- a/src/rendering/v_video.cpp +++ b/src/rendering/v_video.cpp @@ -108,12 +108,16 @@ CUSTOM_CVAR(Int, vid_rendermode, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOIN // No further checks needed. All this changes now is which scene drawer the render backend calls. } -CUSTOM_CVAR(Int, vid_enablevulkan, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +CUSTOM_CVAR(Int, vid_preferbackend, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { // [SP] This may seem pointless - but I don't want to implement live switching just // yet - I'm pretty sure it's going to require a lot of reinits and destructions to // do it right without memory leaks + // 0 - OpenGL + // 1 - Vulkan + // 2 - SoftPoly v2 + Printf("Changing the video backend requires a restart for " GAMENAME ".\n"); } diff --git a/src/win32/hardware.cpp b/src/win32/hardware.cpp index 4b3016834..af6ab1188 100644 --- a/src/win32/hardware.cpp +++ b/src/win32/hardware.cpp @@ -51,7 +51,7 @@ #include "i_system.h" #include "swrenderer/r_swrenderer.h" -EXTERN_CVAR(Int, vid_enablevulkan) +EXTERN_CVAR(Int, vid_preferbackend) extern HWND Window; @@ -129,11 +129,12 @@ void I_InitGraphics () // are the active app. Huh? } -#if 1 // always use poly backend on this branch, for now. - Video = new Win32PolyVideo(); -#else + if (vid_preferbackend == 2) + { + Video = new Win32PolyVideo(); + } #ifdef HAVE_VULKAN - else if (vid_enablevulkan == 1) + else if (vid_preferbackend == 1) { // first try Vulkan, if that fails OpenGL try @@ -151,8 +152,11 @@ void I_InitGraphics () { Video = new Win32GLVideo(); } -#endif + if (Video == NULL) + Video = new Win32PolyVideo(); + + // we somehow STILL don't have a display!! if (Video == NULL) I_FatalError ("Failed to initialize display"); diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index 13859176d..36e042b1f 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -119,7 +119,8 @@ EXTERN_CVAR (Bool, queryiwad); EXTERN_CVAR (Bool, disableautoload) EXTERN_CVAR (Bool, autoloadlights) EXTERN_CVAR (Bool, autoloadbrightmaps) -EXTERN_CVAR (Int, vid_enablevulkan) +//EXTERN_CVAR (Int, vid_enablevulkan) // hack - we're just disabling it for now, this code does nothing +uint32_t vid_enablevulkan = 0; extern HWND Window, ConWindow, GameTitleWindow; extern HANDLE StdOut; From 3059b8f5c83a290ad74f01d39e971309ccdbe8da Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 1 Dec 2019 23:23:25 +0100 Subject: [PATCH 45/60] Remove old softpoly drawer implementation --- .../polyrenderer/drawers/screen_triangle.cpp | 1724 ----------------- .../polyrenderer/drawers/screen_triangle.h | 130 -- 2 files changed, 1854 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 66f3c9869..9e3e3a202 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -833,1727 +833,3 @@ void(*ScreenTriangle::TestSpanOpts[])(int y, int x0, int x1, const TriDrawTriang &TestSpan, &TestSpan }; - -#if 0 - -static void SortVertices(const TriDrawTriangleArgs *args, ScreenTriVertex **sortedVertices) -{ - sortedVertices[0] = args->v1; - sortedVertices[1] = args->v2; - sortedVertices[2] = args->v3; - - if (sortedVertices[1]->y < sortedVertices[0]->y) - std::swap(sortedVertices[0], sortedVertices[1]); - if (sortedVertices[2]->y < sortedVertices[0]->y) - std::swap(sortedVertices[0], sortedVertices[2]); - if (sortedVertices[2]->y < sortedVertices[1]->y) - std::swap(sortedVertices[1], sortedVertices[2]); -} - -void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread) -{ - using namespace TriScreenDrawerModes; - - // Sort vertices by Y position - ScreenTriVertex *sortedVertices[3]; - SortVertices(args, sortedVertices); - - int clipleft = thread->clip.left; - int cliptop = MAX(thread->clip.top, thread->numa_start_y); - int clipright = thread->clip.right; - int clipbottom = MIN(thread->clip.bottom, thread->numa_end_y); - - int topY = (int)(sortedVertices[0]->y + 0.5f); - int midY = (int)(sortedVertices[1]->y + 0.5f); - int bottomY = (int)(sortedVertices[2]->y + 0.5f); - - topY = MAX(topY, cliptop); - midY = MIN(midY, clipbottom); - bottomY = MIN(bottomY, clipbottom); - - if (topY >= bottomY) - return; - - topY += thread->skipped_by_thread(topY); - int num_cores = thread->num_cores; - - // Find start/end X positions for each line covered by the triangle: - - int16_t edges[MAXHEIGHT * 2]; - - int y = topY; - - float longDX = sortedVertices[2]->x - sortedVertices[0]->x; - float longDY = sortedVertices[2]->y - sortedVertices[0]->y; - float longStep = longDX / longDY; - float longPos = sortedVertices[0]->x + longStep * (y + 0.5f - sortedVertices[0]->y) + 0.5f; - longStep *= num_cores; - - if (y < midY) - { - float shortDX = sortedVertices[1]->x - sortedVertices[0]->x; - float shortDY = sortedVertices[1]->y - sortedVertices[0]->y; - float shortStep = shortDX / shortDY; - float shortPos = sortedVertices[0]->x + shortStep * (y + 0.5f - sortedVertices[0]->y) + 0.5f; - shortStep *= num_cores; - - while (y < midY) - { - int x0 = (int)shortPos; - int x1 = (int)longPos; - if (x1 < x0) std::swap(x0, x1); - x0 = clamp(x0, clipleft, clipright); - x1 = clamp(x1, clipleft, clipright); - - edges[y << 1] = x0; - edges[(y << 1) + 1] = x1; - - shortPos += shortStep; - longPos += longStep; - y += num_cores; - } - } - - if (y < bottomY) - { - float shortDX = sortedVertices[2]->x - sortedVertices[1]->x; - float shortDY = sortedVertices[2]->y - sortedVertices[1]->y; - float shortStep = shortDX / shortDY; - float shortPos = sortedVertices[1]->x + shortStep * (y + 0.5f - sortedVertices[1]->y) + 0.5f; - shortStep *= num_cores; - - while (y < bottomY) - { - int x0 = (int)shortPos; - int x1 = (int)longPos; - if (x1 < x0) std::swap(x0, x1); - x0 = clamp(x0, clipleft, clipright); - x1 = clamp(x1, clipleft, clipright); - - edges[y << 1] = x0; - edges[(y << 1) + 1] = x1; - - shortPos += shortStep; - longPos += longStep; - y += num_cores; - } - } - - int opt = 0; - if (thread->drawargs.DepthTest()) opt |= SWTRI_DepthTest; - if (thread->drawargs.StencilTest()) opt |= SWTRI_StencilTest; - if (thread->drawargs.WriteColor()) opt |= SWTRI_WriteColor; - if (thread->drawargs.WriteDepth()) opt |= SWTRI_WriteDepth; - if (thread->drawargs.WriteStencil()) opt |= SWTRI_WriteStencil; - - TriangleDrawers[opt](args, thread, edges, topY, bottomY); -} - -static void FillDepthValues(float *depthvalues, float posXW, float stepXW, int count, float depthbias) -{ -#ifndef NO_SSE - __m128 mstepXW = _mm_set1_ps(stepXW * 4.0f); - __m128 mfirstStepXW = _mm_setr_ps(0.0f, stepXW, stepXW + stepXW, stepXW + stepXW + stepXW); - __m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW); - __m128 mdepthbias = _mm_set1_ps(depthbias); - while (count > 0) - { - _mm_storeu_ps(depthvalues, _mm_add_ps(_mm_rcp_ps(mposXW), mdepthbias)); - mposXW = _mm_add_ps(mposXW, mstepXW); - depthvalues += 4; - count -= 4; - } -#else - while (count > 0) - { - *(depthvalues++) = 1.0f / posXW + depthbias; - posXW += stepXW; - count--; - } -#endif -} - -template -void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread, int16_t *edges, int topY, int bottomY) -{ - using namespace TriScreenDrawerModes; - - void(*drawfunc)(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); - float stepXW, v1X, v1Y, v1W; - uint8_t stencilTestValue, stencilWriteValue; - float *zbuffer; - float *zbufferLine; - uint8_t *stencilbuffer; - uint8_t *stencilLine; - int pitch; - - bool alphatest = thread->AlphaTest; - uint8_t *alphatestbuf = thread->alphatestbuffer; - - if (OptT::Flags & SWTRI_WriteColor) - { - int bmode = (int)thread->drawargs.BlendMode(); - drawfunc = thread->dest_bgra ? ScreenTriangle::SpanDrawers32[bmode] : ScreenTriangle::SpanDrawers8[bmode]; - } - - if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_WriteDepth)) - { - stepXW = args->gradientX.W; - v1X = args->v1->x; - v1Y = args->v1->y; - v1W = args->v1->w; - zbuffer = thread->depthstencil->DepthValues(); - } - - if ((OptT::Flags & SWTRI_StencilTest) || (OptT::Flags & SWTRI_WriteStencil)) - { - stencilbuffer = thread->depthstencil->StencilValues(); - } - - if ((OptT::Flags & SWTRI_StencilTest) || (OptT::Flags & SWTRI_WriteStencil) || (OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_WriteDepth)) - pitch = thread->depthstencil->Width(); - - if (OptT::Flags & SWTRI_StencilTest) - stencilTestValue = thread->drawargs.StencilTestValue(); - - if (OptT::Flags & SWTRI_WriteStencil) - stencilWriteValue = thread->drawargs.StencilWriteValue(); - - float depthbias; - if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_WriteDepth)) - { - depthbias = thread->depthbias; - } - - float *depthvalues = thread->depthvalues; - - int num_cores = thread->num_cores; - for (int y = topY; y < bottomY; y += num_cores) - { - int x = edges[y << 1]; - int xend = edges[(y << 1) + 1]; - - if ((OptT::Flags & SWTRI_StencilTest) || (OptT::Flags & SWTRI_WriteStencil)) - stencilLine = stencilbuffer + pitch * y; - - if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_WriteDepth)) - { - zbufferLine = zbuffer + pitch * y; - - float startX = x + (0.5f - v1X); - float startY = y + (0.5f - v1Y); - float posXW = v1W + stepXW * startX + args->gradientY.W * startY; - FillDepthValues(depthvalues + x, posXW, stepXW, xend - x, depthbias); - } - -#ifndef NO_SSE - while (x < xend) - { - int xstart = x; - - if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) - { - int xendsse = x + ((xend - x) / 4); - __m128 mposXW; - while (x < xendsse && - _mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 15 && - stencilLine[x] == stencilTestValue && - stencilLine[x + 1] == stencilTestValue && - stencilLine[x + 2] == stencilTestValue && - stencilLine[x + 3] == stencilTestValue) - { - if (!alphatest && (OptT::Flags & SWTRI_WriteDepth)) - _mm_storeu_ps(zbufferLine + x, mposXW); - x += 4; - } - - while (zbufferLine[x] >= depthvalues[x] && stencilLine[x] == stencilTestValue && x < xend) - { - if (!alphatest && (OptT::Flags & SWTRI_WriteDepth)) - zbufferLine[x] = depthvalues[x]; - x++; - } - } - else if (OptT::Flags & SWTRI_DepthTest) - { - int xendsse = x + ((xend - x) / 4); - __m128 mposXW; - while (x < xendsse && _mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 15) - { - if (!alphatest && (OptT::Flags & SWTRI_WriteDepth)) - _mm_storeu_ps(zbufferLine + x, mposXW); - x += 4; - } - - while (zbufferLine[x] >= depthvalues[x] && x < xend) - { - if (!alphatest && (OptT::Flags & SWTRI_WriteDepth)) - zbufferLine[x] = depthvalues[x]; - x++; - } - } - else if (OptT::Flags & SWTRI_StencilTest) - { - int xendsse = x + ((xend - x) / 16); - while (x < xendsse && _mm_movemask_epi8(_mm_cmpeq_epi8(_mm_loadu_si128((const __m128i*)&stencilLine[x]), _mm_set1_epi8(stencilTestValue))) == 0xffff) - { - x += 16; - } - - while (stencilLine[x] == stencilTestValue && x < xend) - x++; - } - else - { - x = xend; - } - - if (x > xstart) - { - if (OptT::Flags & SWTRI_WriteColor) - drawfunc(y, xstart, x, args, thread); - - if (alphatest) - { - if (OptT::Flags & SWTRI_WriteStencil) - { - for (int i = xstart; i < x; i++) - { - if (alphatestbuf[i] > 127) - stencilLine[i++] = stencilWriteValue; - } - } - - if (OptT::Flags & SWTRI_WriteDepth) - { - for (int i = xstart; i < x; i++) - { - if (alphatestbuf[i] > 127) - zbufferLine[i] = depthvalues[i]; - } - } - } - else - { - if (OptT::Flags & SWTRI_WriteStencil) - { - int i = xstart; - int xendsse = xstart + ((x - xstart) / 16); - while (i < xendsse) - { - _mm_storeu_si128((__m128i*)&stencilLine[i], _mm_set1_epi8(stencilWriteValue)); - i += 16; - } - - while (i < x) - stencilLine[i++] = stencilWriteValue; - } - - if (!(OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_WriteDepth)) - { - for (int i = xstart; i < x; i++) - { - zbufferLine[i] = depthvalues[i]; - } - } - } - } - - if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) - { - int xendsse = x + ((xend - x) / 4); - __m128 mposXW; - while (x < xendsse && - (_mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 0 || - stencilLine[x] != stencilTestValue || - stencilLine[x + 1] != stencilTestValue || - stencilLine[x + 2] != stencilTestValue || - stencilLine[x + 3] != stencilTestValue)) - { - x += 4; - } - - while ((zbufferLine[x] < depthvalues[x] || stencilLine[x] != stencilTestValue) && x < xend) - { - x++; - } - } - else if (OptT::Flags & SWTRI_DepthTest) - { - int xendsse = x + ((xend - x) / 4); - __m128 mposXW; - while (x < xendsse && _mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 0) - { - x += 4; - } - - while (zbufferLine[x] < depthvalues[x] && x < xend) - { - x++; - } - } - else if (OptT::Flags & SWTRI_StencilTest) - { - int xendsse = x + ((xend - x) / 16); - while (x < xendsse && _mm_movemask_epi8(_mm_cmpeq_epi8(_mm_loadu_si128((const __m128i*)&stencilLine[x]), _mm_set1_epi8(stencilTestValue))) == 0) - { - x += 16; - } - - while (stencilLine[x] != stencilTestValue && x < xend) - { - x++; - } - } - } -#else - while (x < xend) - { - int xstart = x; - - if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) - { - while (zbufferLine[x] >= depthvalues[x] && stencilLine[x] == stencilTestValue && x < xend) - { - if (!alphatest && (OptT::Flags & SWTRI_WriteDepth)) - zbufferLine[x] = depthvalues[x]; - x++; - } - } - else if (OptT::Flags & SWTRI_DepthTest) - { - while (zbufferLine[x] >= depthvalues[x] && x < xend) - { - if (!alphatest && (OptT::Flags & SWTRI_WriteDepth)) - zbufferLine[x] = depthvalues[x]; - x++; - } - } - else if (OptT::Flags & SWTRI_StencilTest) - { - while (stencilLine[x] == stencilTestValue && x < xend) - x++; - } - else - { - x = xend; - } - - if (x > xstart) - { - if (OptT::Flags & SWTRI_WriteColor) - drawfunc(y, xstart, x, args, thread); - - if (alphatest) - { - if (OptT::Flags & SWTRI_WriteStencil) - { - for (int i = xstart; i < x; i++) - { - if (alphatestbuf[i] > 127) - stencilLine[i++] = stencilWriteValue; - } - } - - if (OptT::Flags & SWTRI_WriteDepth) - { - for (int i = xstart; i < x; i++) - { - if (alphatestbuf[i] > 127) - zbufferLine[i] = depthvalues[i]; - } - } - } - else - { - if (OptT::Flags & SWTRI_WriteStencil) - { - for (int i = xstart; i < x; i++) - stencilLine[i] = stencilWriteValue; - } - - if (!(OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_WriteDepth)) - { - for (int i = xstart; i < x; i++) - { - zbufferLine[i] = depthvalues[i]; - } - } - } - } - - if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) - { - while ((zbufferLine[x] < depthvalues[x] || stencilLine[x] != stencilTestValue) && x < xend) - { - x++; - } - } - else if (OptT::Flags & SWTRI_DepthTest) - { - while (zbufferLine[x] < depthvalues[x] && x < xend) - { - x++; - } - } - else if (OptT::Flags & SWTRI_StencilTest) - { - while (stencilLine[x] != stencilTestValue && x < xend) - { - x++; - } - } - } -#endif - } -} - -template -void StepSpan(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread) -{ - using namespace TriScreenDrawerModes; - - float v1X, v1Y, v1W, v1U, v1V, v1WorldX, v1WorldY, v1WorldZ; - float startX, startY; - float stepW, stepU, stepV, stepWorldX, stepWorldY, stepWorldZ; - float posW, posU, posV, posWorldX, posWorldY, posWorldZ; - int texWidth, texHeight; - uint32_t light; - fixed_t shade, lightpos, lightstep; - - float *worldposX = thread->worldposX; - float *worldposY = thread->worldposY; - float *worldposZ = thread->worldposZ; - uint32_t *texel = thread->texel; - int32_t *texelV = thread->texelV; - uint16_t *lightarray = thread->lightarray; - uint32_t *dynlights = thread->dynlights; - - v1X = args->v1->x; - v1Y = args->v1->y; - v1W = args->v1->w; - v1U = args->v1->u * v1W; - v1V = args->v1->v * v1W; - startX = x0 + (0.5f - v1X); - startY = y + (0.5f - v1Y); - stepW = args->gradientX.W; - stepU = args->gradientX.U; - stepV = args->gradientX.V; - posW = v1W + stepW * startX + args->gradientY.W * startY; - posU = v1U + stepU * startX + args->gradientY.U * startY; - posV = v1V + stepV * startX + args->gradientY.V * startY; - - if (!(ModeT::SWFlags & SWSTYLEF_Fill) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary)) - { - texWidth = thread->drawargs.TextureWidth(); - texHeight = thread->drawargs.TextureHeight(); - } - - if (OptT::Flags & SWOPT_DynLights) - { - v1WorldX = args->v1->worldX * v1W; - v1WorldY = args->v1->worldY * v1W; - v1WorldZ = args->v1->worldZ * v1W; - stepWorldX = args->gradientX.WorldX; - stepWorldY = args->gradientX.WorldY; - stepWorldZ = args->gradientX.WorldZ; - posWorldX = v1WorldX + stepWorldX * startX + args->gradientY.WorldX * startY; - posWorldY = v1WorldY + stepWorldY * startX + args->gradientY.WorldY * startY; - posWorldZ = v1WorldZ + stepWorldZ * startX + args->gradientY.WorldZ * startY; - } - - if (!(OptT::Flags & SWOPT_FixedLight)) - { - float globVis = thread->drawargs.GlobVis() * (1.0f / 32.0f); - - light = thread->drawargs.Light(); - shade = (fixed_t)((2.0f - (light + 12.0f) / 128.0f) * (float)FRACUNIT); - lightpos = (fixed_t)(globVis * posW * (float)FRACUNIT); - lightstep = (fixed_t)(globVis * stepW * (float)FRACUNIT); - - fixed_t maxvis = 24 * FRACUNIT / 32; - fixed_t maxlight = 31 * FRACUNIT / 32; - - fixed_t lightend = lightpos + lightstep * (x1 - x0); - if (lightpos < maxvis && shade >= lightpos && shade - lightpos <= maxlight && - lightend < maxvis && shade >= lightend && shade - lightend <= maxlight) - { - if (BitsPerPixel == 32) - { - lightpos += FRACUNIT - shade; - for (int x = x0; x < x1; x++) - { - lightarray[x] = lightpos >> 8; - lightpos += lightstep; - } - } - else - { - lightpos = shade - lightpos; - for (int x = x0; x < x1; x++) - { - lightarray[x] = (lightpos >> 3) & 0xffffff00; - lightpos -= lightstep; - } - } - } - else - { - if (BitsPerPixel == 32) - { - for (int x = x0; x < x1; x++) - { - lightarray[x] = (FRACUNIT - clamp(shade - MIN(maxvis, lightpos), 0, maxlight)) >> 8; - lightpos += lightstep; - } - } - else - { - for (int x = x0; x < x1; x++) - { - lightarray[x] = (clamp(shade - MIN(maxvis, lightpos), 0, maxlight) >> 3) & 0xffffff00; - lightpos += lightstep; - } - } - } - } - -#ifndef NO_SSE - __m128 mposW, mposU, mposV, mstepW, mstepU, mstepV; - __m128 mposWorldX, mposWorldY, mposWorldZ, mstepWorldX, mstepWorldY, mstepWorldZ; - __m128i mtexMul1, mtexMul2; - - #define SETUP_STEP_SSE(mpos,mstep,pos,step) \ - mstep = _mm_load_ss(&step); \ - mpos = _mm_load_ss(&pos); \ - mpos = _mm_shuffle_ps(mpos, mpos, _MM_SHUFFLE(2, 1, 0, 0)); \ - mpos = _mm_add_ss(mpos, mstep); \ - mpos = _mm_shuffle_ps(mpos, mpos, _MM_SHUFFLE(2, 1, 0, 0)); \ - mpos = _mm_add_ss(mpos, mstep); \ - mpos = _mm_shuffle_ps(mpos, mpos, _MM_SHUFFLE(2, 1, 0, 0)); \ - mpos = _mm_add_ss(mpos, mstep); \ - mpos = _mm_shuffle_ps(mpos, mpos, _MM_SHUFFLE(0, 1, 2, 3)); \ - mstep = _mm_mul_ss(mstep, _mm_set1_ps(4.0f)); \ - mstep = _mm_shuffle_ps(mstep, mstep, _MM_SHUFFLE(0, 0, 0, 0)); - - SETUP_STEP_SSE(mposW, mstepW, posW, stepW); - - if (OptT::Flags & SWOPT_DynLights) - { - SETUP_STEP_SSE(mposWorldX, mstepWorldX, posWorldX, stepWorldX); - SETUP_STEP_SSE(mposWorldY, mstepWorldY, posWorldY, stepWorldY); - SETUP_STEP_SSE(mposWorldZ, mstepWorldZ, posWorldZ, stepWorldZ); - } - - if (!(ModeT::SWFlags & SWSTYLEF_Fill) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary)) - { - SETUP_STEP_SSE(mposU, mstepU, posU, stepU); - SETUP_STEP_SSE(mposV, mstepV, posV, stepV); - - mtexMul1 = _mm_setr_epi16(texWidth, texWidth, texWidth, texWidth, texHeight, texHeight, texHeight, texHeight); - mtexMul2 = _mm_setr_epi16(texHeight, texHeight, texHeight, texHeight, 1, 1, 1, 1); - } - - #undef SETUP_STEP_SSE - - for (int x = x0; x < x1; x += 4) - { - __m128 rcp_posW = _mm_div_ps(_mm_set1_ps(1.0f), mposW); // precision of _mm_rcp_ps(mposW) is terrible! - - if (OptT::Flags & SWOPT_DynLights) - { - _mm_storeu_ps(&worldposX[x], _mm_mul_ps(mposWorldX, rcp_posW)); - _mm_storeu_ps(&worldposY[x], _mm_mul_ps(mposWorldY, rcp_posW)); - _mm_storeu_ps(&worldposZ[x], _mm_mul_ps(mposWorldZ, rcp_posW)); - mposWorldX = _mm_add_ps(mposWorldX, mstepWorldX); - mposWorldY = _mm_add_ps(mposWorldY, mstepWorldY); - mposWorldZ = _mm_add_ps(mposWorldZ, mstepWorldZ); - } - if (!(ModeT::SWFlags & SWSTYLEF_Fill) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary)) - { - __m128 rcpW = _mm_mul_ps(_mm_set1_ps(0x01000000), rcp_posW); - __m128i u = _mm_cvtps_epi32(_mm_mul_ps(mposU, rcpW)); - __m128i v = _mm_cvtps_epi32(_mm_mul_ps(mposV, rcpW)); - _mm_storeu_si128((__m128i*)&texelV[x], v); - - __m128i texelX = _mm_srli_epi32(_mm_slli_epi32(u, 8), 17); - __m128i texelY = _mm_srli_epi32(_mm_slli_epi32(v, 8), 17); - __m128i texelXY = _mm_mulhi_epu16(_mm_slli_epi16(_mm_packs_epi32(texelX, texelY), 1), mtexMul1); - __m128i texlo = _mm_mullo_epi16(texelXY, mtexMul2); - __m128i texhi = _mm_mulhi_epi16(texelXY, mtexMul2); - texelX = _mm_unpacklo_epi16(texlo, texhi); - texelY = _mm_unpackhi_epi16(texlo, texhi); - _mm_storeu_si128((__m128i*)&texel[x], _mm_add_epi32(texelX, texelY)); - - mposU = _mm_add_ps(mposU, mstepU); - mposV = _mm_add_ps(mposV, mstepV); - } - - mposW = _mm_add_ps(mposW, mstepW); - } -#else - for (int x = x0; x < x1; x++) - { - if (OptT::Flags & SWOPT_DynLights) - { - float rcp_posW = 1.0f / posW; - worldposX[x] = posWorldX * rcp_posW; - worldposY[x] = posWorldY * rcp_posW; - worldposZ[x] = posWorldZ * rcp_posW; - posWorldX += stepWorldX; - posWorldY += stepWorldY; - posWorldZ += stepWorldZ; - } - if (!(ModeT::SWFlags & SWSTYLEF_Fill) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary)) - { - float rcpW = 0x01000000 / posW; - int32_t u = (int32_t)(posU * rcpW); - int32_t v = (int32_t)(posV * rcpW); - uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - texel[x] = texelX * texHeight + texelY; - texelV[x] = v; - posU += stepU; - posV += stepV; - } - - posW += stepW; - } -#endif - - if (OptT::Flags & SWOPT_DynLights) - { - PolyLight *lights; - int num_lights; - float worldnormalX, worldnormalY, worldnormalZ; - uint32_t dynlightcolor; - - lights = thread->drawargs.Lights(); - num_lights = thread->drawargs.NumLights(); - worldnormalX = thread->drawargs.Normal().X; - worldnormalY = thread->drawargs.Normal().Y; - worldnormalZ = thread->drawargs.Normal().Z; - dynlightcolor = thread->drawargs.DynLightColor(); - - // The normal vector cannot be uniform when drawing models. Calculate and use the face normal: - if (worldnormalX == 0.0f && worldnormalY == 0.0f && worldnormalZ == 0.0f) - { - float dx1 = args->v2->worldX - args->v1->worldX; - float dy1 = args->v2->worldY - args->v1->worldY; - float dz1 = args->v2->worldZ - args->v1->worldZ; - float dx2 = args->v3->worldX - args->v1->worldX; - float dy2 = args->v3->worldY - args->v1->worldY; - float dz2 = args->v3->worldZ - args->v1->worldZ; - worldnormalX = dy1 * dz2 - dz1 * dy2; - worldnormalY = dz1 * dx2 - dx1 * dz2; - worldnormalZ = dx1 * dy2 - dy1 * dx2; - float lensqr = worldnormalX * worldnormalX + worldnormalY * worldnormalY + worldnormalZ * worldnormalZ; -#ifndef NO_SSE - float rcplen = _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(lensqr))); -#else - float rcplen = 1.0f / sqrt(lensqr); -#endif - worldnormalX *= rcplen; - worldnormalY *= rcplen; - worldnormalZ *= rcplen; - } - -#ifndef NO_SSE - __m128 mworldnormalX = _mm_set1_ps(worldnormalX); - __m128 mworldnormalY = _mm_set1_ps(worldnormalY); - __m128 mworldnormalZ = _mm_set1_ps(worldnormalZ); - for (int x = x0; x < x1; x += 4) - { - __m128i litlo = _mm_shuffle_epi32(_mm_unpacklo_epi8(_mm_cvtsi32_si128(dynlightcolor), _mm_setzero_si128()), _MM_SHUFFLE(1, 0, 1, 0)); - __m128i lithi = litlo; - - for (int i = 0; i < num_lights; i++) - { - __m128 lightposX = _mm_set1_ps(lights[i].x); - __m128 lightposY = _mm_set1_ps(lights[i].y); - __m128 lightposZ = _mm_set1_ps(lights[i].z); - __m128 light_radius = _mm_set1_ps(lights[i].radius); - __m128i light_color = _mm_shuffle_epi32(_mm_unpacklo_epi8(_mm_cvtsi32_si128(lights[i].color), _mm_setzero_si128()), _MM_SHUFFLE(1, 0, 1, 0)); - - __m128 is_attenuated = _mm_cmplt_ps(light_radius, _mm_setzero_ps()); - light_radius = _mm_andnot_ps(_mm_set1_ps(-0.0f), light_radius); // clear sign bit - - // L = light-pos - // dist = sqrt(dot(L, L)) - // distance_attenuation = 1 - MIN(dist * (1/radius), 1) - __m128 Lx = _mm_sub_ps(lightposX, _mm_loadu_ps(&worldposX[x])); - __m128 Ly = _mm_sub_ps(lightposY, _mm_loadu_ps(&worldposY[x])); - __m128 Lz = _mm_sub_ps(lightposZ, _mm_loadu_ps(&worldposZ[x])); - __m128 dist2 = _mm_add_ps(_mm_mul_ps(Lx, Lx), _mm_add_ps(_mm_mul_ps(Ly, Ly), _mm_mul_ps(Lz, Lz))); - __m128 rcp_dist = _mm_rsqrt_ps(dist2); - __m128 dist = _mm_mul_ps(dist2, rcp_dist); - __m128 distance_attenuation = _mm_sub_ps(_mm_set1_ps(256.0f), _mm_min_ps(_mm_mul_ps(dist, light_radius), _mm_set1_ps(256.0f))); - - // The simple light type - __m128 simple_attenuation = distance_attenuation; - - // The point light type - // diffuse = max(dot(N,normalize(L)),0) * attenuation - Lx = _mm_mul_ps(Lx, rcp_dist); - Ly = _mm_mul_ps(Ly, rcp_dist); - Lz = _mm_mul_ps(Lz, rcp_dist); - __m128 dotNL = _mm_add_ps(_mm_add_ps(_mm_mul_ps(mworldnormalX, Lx), _mm_mul_ps(mworldnormalY, Ly)), _mm_mul_ps(mworldnormalZ, Lz)); - __m128 point_attenuation = _mm_mul_ps(_mm_max_ps(dotNL, _mm_setzero_ps()), distance_attenuation); - - __m128i attenuation = _mm_cvtps_epi32(_mm_or_ps(_mm_and_ps(is_attenuated, point_attenuation), _mm_andnot_ps(is_attenuated, simple_attenuation))); - - attenuation = _mm_shufflehi_epi16(_mm_shufflelo_epi16(attenuation, _MM_SHUFFLE(2, 2, 0, 0)), _MM_SHUFFLE(2, 2, 0, 0)); - __m128i attenlo = _mm_shuffle_epi32(attenuation, _MM_SHUFFLE(1, 1, 0, 0)); - __m128i attenhi = _mm_shuffle_epi32(attenuation, _MM_SHUFFLE(3, 3, 2, 2)); - - litlo = _mm_add_epi16(litlo, _mm_srli_epi16(_mm_mullo_epi16(light_color, attenlo), 8)); - lithi = _mm_add_epi16(lithi, _mm_srli_epi16(_mm_mullo_epi16(light_color, attenhi), 8)); - } - - _mm_storeu_si128((__m128i*)&dynlights[x], _mm_packus_epi16(litlo, lithi)); - } -#else - for (int x = x0; x < x1; x++) - { - uint32_t lit_r = RPART(dynlightcolor); - uint32_t lit_g = GPART(dynlightcolor); - uint32_t lit_b = BPART(dynlightcolor); - - for (int i = 0; i < num_lights; i++) - { - float lightposX = lights[i].x; - float lightposY = lights[i].y; - float lightposZ = lights[i].z; - float light_radius = lights[i].radius; - uint32_t light_color = lights[i].color; - - bool is_attenuated = light_radius < 0.0f; - if (is_attenuated) - light_radius = -light_radius; - - // L = light-pos - // dist = sqrt(dot(L, L)) - // distance_attenuation = 1 - MIN(dist * (1/radius), 1) - float Lx = lightposX - worldposX[x]; - float Ly = lightposY - worldposY[x]; - float Lz = lightposZ - worldposZ[x]; - float dist2 = Lx * Lx + Ly * Ly + Lz * Lz; -#ifdef NO_SSE - //float rcp_dist = 1.0f / sqrt(dist2); - float rcp_dist = 1.0f / (dist2 * 0.01f); -#else - float rcp_dist = _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(dist2))); -#endif - float dist = dist2 * rcp_dist; - float distance_attenuation = 256.0f - MIN(dist * light_radius, 256.0f); - - // The simple light type - float simple_attenuation = distance_attenuation; - - // The point light type - // diffuse = max(dot(N,normalize(L)),0) * attenuation - Lx *= rcp_dist; - Ly *= rcp_dist; - Lz *= rcp_dist; - float dotNL = worldnormalX * Lx + worldnormalY * Ly + worldnormalZ * Lz; - float point_attenuation = MAX(dotNL, 0.0f) * distance_attenuation; - - uint32_t attenuation = (uint32_t)(is_attenuated ? (int32_t)point_attenuation : (int32_t)simple_attenuation); - - lit_r += (RPART(light_color) * attenuation) >> 8; - lit_g += (GPART(light_color) * attenuation) >> 8; - lit_b += (BPART(light_color) * attenuation) >> 8; - } - - lit_r = MIN(lit_r, 255); - lit_g = MIN(lit_g, 255); - lit_b = MIN(lit_b, 255); - dynlights[x] = MAKEARGB(255, lit_r, lit_g, lit_b); - } -#endif - } -} - -template -void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread) -{ - using namespace TriScreenDrawerModes; - - StepSpan(y, x0, x1, args, thread); - - uint32_t fixedlight; - uint32_t shade_fade_r, shade_fade_g, shade_fade_b, shade_light_r, shade_light_g, shade_light_b, desaturate, inv_desaturate; - fixed_t fuzzscale; - int _fuzzpos; - const uint32_t *texPixels, *translation; - uint32_t fillcolor; - int actoralpha; - uint8_t *alphatestbuf; - - uint32_t *texel = thread->texel; - int32_t *texelV = thread->texelV; - uint16_t *lightarray = thread->lightarray; - uint32_t *dynlights = thread->dynlights; - - if (!(ModeT::SWFlags & SWSTYLEF_Fill) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary)) - { - texPixels = (const uint32_t*)thread->drawargs.TexturePixels(); - } - - if (ModeT::SWFlags & SWSTYLEF_Translated) - { - translation = (const uint32_t*)thread->drawargs.Translation(); - } - - if ((ModeT::SWFlags & SWSTYLEF_Fill) || (ModeT::SWFlags & SWSTYLEF_Skycap) || (ModeT::Flags & STYLEF_ColorIsFixed)) - { - fillcolor = thread->drawargs.Color(); - } - - if (!(ModeT::Flags & STYLEF_Alpha1)) - { - actoralpha = thread->drawargs.Alpha(); - } - - if (OptT::Flags & SWOPT_FixedLight) - { - fixedlight = thread->drawargs.Light(); - fixedlight += fixedlight >> 7; // 255 -> 256 - } - - if (OptT::Flags & SWOPT_ColoredFog) - { - shade_fade_r = thread->drawargs.ShadeFadeRed(); - shade_fade_g = thread->drawargs.ShadeFadeGreen(); - shade_fade_b = thread->drawargs.ShadeFadeBlue(); - shade_light_r = thread->drawargs.ShadeLightRed(); - shade_light_g = thread->drawargs.ShadeLightGreen(); - shade_light_b = thread->drawargs.ShadeLightBlue(); - desaturate = thread->drawargs.ShadeDesaturate(); - inv_desaturate = 256 - desaturate; - } - - if (ModeT::BlendOp == STYLEOP_Fuzz) - { - fuzzscale = (200 << FRACBITS) / thread->dest_height; - _fuzzpos = swrenderer::fuzzpos; - } - - if (ModeT::SWFlags & SWSTYLEF_AlphaTest) - { - alphatestbuf = thread->alphatestbuffer; - } - - uint32_t *dest = (uint32_t*)thread->dest; - uint32_t *destLine = dest + thread->dest_pitch * y; - - int sseend = x0; -#ifndef NO_SSE - if (ModeT::BlendOp == STYLEOP_Add && - ModeT::BlendSrc == STYLEALPHA_One && - ModeT::BlendDest == STYLEALPHA_Zero && - (ModeT::Flags & STYLEF_Alpha1) && - !(OptT::Flags & SWOPT_ColoredFog) && - !(ModeT::Flags & STYLEF_RedIsAlpha) && - !(ModeT::SWFlags & SWSTYLEF_Skycap) && - !(ModeT::SWFlags & SWSTYLEF_FogBoundary) && - !(ModeT::SWFlags & SWSTYLEF_Fill) && - !(ModeT::SWFlags & SWSTYLEF_AlphaTest)) - { - sseend += (x1 - x0) / 2 * 2; - - __m128i mlightshade; - if (OptT::Flags & SWOPT_FixedLight) - mlightshade = _mm_set1_epi16(fixedlight); - - __m128i alphamask = _mm_set1_epi32(0xff000000); - - for (int x = x0; x < sseend; x += 2) - { - __m128i mfg = _mm_unpacklo_epi8(_mm_setr_epi32(texPixels[texel[x]], texPixels[texel[x + 1]], 0, 0), _mm_setzero_si128()); - - if (!(OptT::Flags & SWOPT_FixedLight)) - mlightshade = _mm_shuffle_epi32(_mm_shufflelo_epi16(_mm_cvtsi32_si128(*(int*)&lightarray[x]), _MM_SHUFFLE(1, 1, 0, 0)), _MM_SHUFFLE(1, 1, 0, 0)); - - if (OptT::Flags & SWOPT_DynLights) - { - __m128i mdynlight = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)&dynlights[x]), _mm_setzero_si128()); - mfg = _mm_srli_epi16(_mm_mullo_epi16(_mm_min_epi16(_mm_add_epi16(mdynlight, mlightshade), _mm_set1_epi16(256)), mfg), 8); - } - else - { - mfg = _mm_srli_epi16(_mm_mullo_epi16(mlightshade, mfg), 8); - } - - _mm_storel_epi64((__m128i*)&destLine[x], _mm_or_si128(_mm_packus_epi16(mfg, _mm_setzero_si128()), alphamask)); - } - } -#endif - - for (int x = sseend; x < x1; x++) - { - if (ModeT::BlendOp == STYLEOP_Fuzz) - { - using namespace swrenderer; - - unsigned int sampleshadeout = APART(texPixels[texel[x]]); - sampleshadeout += sampleshadeout >> 7; // 255 -> 256 - - int scaled_x = (x * fuzzscale) >> FRACBITS; - int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + _fuzzpos; - - fixed_t fuzzcount = FUZZTABLE << FRACBITS; - fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount; - unsigned int alpha = fuzzoffset[fuzz >> FRACBITS]; - - sampleshadeout = (sampleshadeout * alpha) >> 5; - - uint32_t a = 256 - sampleshadeout; - - uint32_t dest = destLine[x]; - uint32_t out_r = (RPART(dest) * a) >> 8; - uint32_t out_g = (GPART(dest) * a) >> 8; - uint32_t out_b = (BPART(dest) * a) >> 8; - destLine[x] = MAKEARGB(255, out_r, out_g, out_b); - } - else if (ModeT::SWFlags & SWSTYLEF_Skycap) - { - uint32_t fg = texPixels[texel[x]]; - - int v = texelV[x]; - int start_fade = 2; // How fast it should fade out - int alpha_top = clamp(v >> (16 - start_fade), 0, 256); - int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256); - int a = MIN(alpha_top, alpha_bottom); - int inv_a = 256 - a; - - if (a == 256) - { - destLine[x] = fg; - } - else - { - uint32_t r = RPART(fg); - uint32_t g = GPART(fg); - uint32_t b = BPART(fg); - uint32_t fg_a = APART(fg); - uint32_t bg_red = RPART(fillcolor); - uint32_t bg_green = GPART(fillcolor); - uint32_t bg_blue = BPART(fillcolor); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - - destLine[x] = MAKEARGB(255, r, g, b); - } - } - else if (ModeT::SWFlags & SWSTYLEF_FogBoundary) - { - uint32_t fg = destLine[x]; - - int lightshade; - if (OptT::Flags & SWOPT_FixedLight) - { - lightshade = fixedlight; - } - else - { - lightshade = lightarray[x]; - } - - uint32_t shadedfg_r, shadedfg_g, shadedfg_b; - if (OptT::Flags & SWOPT_ColoredFog) - { - uint32_t fg_r = RPART(fg); - uint32_t fg_g = GPART(fg); - uint32_t fg_b = BPART(fg); - uint32_t intensity = ((fg_r * 77 + fg_g * 143 + fg_b * 37) >> 8) * desaturate; - int inv_light = 256 - lightshade; - shadedfg_r = (((shade_fade_r * inv_light + ((fg_r * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_r) >> 8; - shadedfg_g = (((shade_fade_g * inv_light + ((fg_g * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_g) >> 8; - shadedfg_b = (((shade_fade_b * inv_light + ((fg_b * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_b) >> 8; - } - else - { - shadedfg_r = (RPART(fg) * lightshade) >> 8; - shadedfg_g = (GPART(fg) * lightshade) >> 8; - shadedfg_b = (BPART(fg) * lightshade) >> 8; - } - - destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b); - } - else - { - uint32_t fg = 0; - - if (ModeT::SWFlags & SWSTYLEF_Fill) - { - fg = fillcolor; - } - else if (ModeT::SWFlags & SWSTYLEF_Translated) - { - fg = translation[((const uint8_t*)texPixels)[texel[x]]]; - } - else if (ModeT::Flags & STYLEF_RedIsAlpha) - { - fg = ((const uint8_t*)texPixels)[texel[x]]; - } - else - { - fg = texPixels[texel[x]]; - } - - if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill)) - { - if (ModeT::Flags & STYLEF_RedIsAlpha) - fg = (fg << 24) | (fillcolor & 0x00ffffff); - else - fg = (fg & 0xff000000) | (fillcolor & 0x00ffffff); - } - - uint32_t fgalpha = fg >> 24; - - if (!(ModeT::Flags & STYLEF_Alpha1)) - { - fgalpha = (fgalpha * actoralpha) >> 8; - } - - if (ModeT::SWFlags & SWSTYLEF_AlphaTest) - { - alphatestbuf[x] = fgalpha; - } - - uint32_t lightshade; - if (OptT::Flags & SWOPT_FixedLight) - { - lightshade = fixedlight; - } - else - { - lightshade = lightarray[x]; - } - - uint32_t shadedfg_r, shadedfg_g, shadedfg_b; - if (OptT::Flags & SWOPT_ColoredFog) - { - uint32_t fg_r = RPART(fg); - uint32_t fg_g = GPART(fg); - uint32_t fg_b = BPART(fg); - uint32_t intensity = ((fg_r * 77 + fg_g * 143 + fg_b * 37) >> 8) * desaturate; - int inv_light = 256 - lightshade; - shadedfg_r = (((shade_fade_r * inv_light + ((fg_r * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_r) >> 8; - shadedfg_g = (((shade_fade_g * inv_light + ((fg_g * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_g) >> 8; - shadedfg_b = (((shade_fade_b * inv_light + ((fg_b * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_b) >> 8; - - if (OptT::Flags & SWOPT_DynLights) - { - shadedfg_r = MIN(shadedfg_r + ((fg_r * RPART(dynlights[x])) >> 8), (uint32_t)255); - shadedfg_g = MIN(shadedfg_g + ((fg_g * GPART(dynlights[x])) >> 8), (uint32_t)255); - shadedfg_b = MIN(shadedfg_b + ((fg_b * BPART(dynlights[x])) >> 8), (uint32_t)255); - } - } - else - { - if (OptT::Flags & SWOPT_DynLights) - { - shadedfg_r = (RPART(fg) * MIN(lightshade + RPART(dynlights[x]), (uint32_t)256)) >> 8; - shadedfg_g = (GPART(fg) * MIN(lightshade + GPART(dynlights[x]), (uint32_t)256)) >> 8; - shadedfg_b = (BPART(fg) * MIN(lightshade + BPART(dynlights[x]), (uint32_t)256)) >> 8; - } - else - { - shadedfg_r = (RPART(fg) * lightshade) >> 8; - shadedfg_g = (GPART(fg) * lightshade) >> 8; - shadedfg_b = (BPART(fg) * lightshade) >> 8; - } - } - - if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero) - { - destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b); - } - else if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_One) - { - uint32_t dest = destLine[x]; - - if (ModeT::BlendOp == STYLEOP_Add) - { - uint32_t out_r = MIN(RPART(dest) + shadedfg_r, 255); - uint32_t out_g = MIN(GPART(dest) + shadedfg_g, 255); - uint32_t out_b = MIN(BPART(dest) + shadedfg_b, 255); - destLine[x] = MAKEARGB(255, out_r, out_g, out_b); - } - else if (ModeT::BlendOp == STYLEOP_RevSub) - { - uint32_t out_r = MAX(RPART(dest) - shadedfg_r, 0); - uint32_t out_g = MAX(GPART(dest) - shadedfg_g, 0); - uint32_t out_b = MAX(BPART(dest) - shadedfg_b, 0); - destLine[x] = MAKEARGB(255, out_r, out_g, out_b); - } - else //if (ModeT::BlendOp == STYLEOP_Sub) - { - uint32_t out_r = MAX(shadedfg_r - RPART(dest), 0); - uint32_t out_g = MAX(shadedfg_g - GPART(dest), 0); - uint32_t out_b = MAX(shadedfg_b - BPART(dest), 0); - destLine[x] = MAKEARGB(255, out_r, out_g, out_b); - } - } - else if (ModeT::SWFlags & SWSTYLEF_SrcColorOneMinusSrcColor) - { - uint32_t dest = destLine[x]; - - uint32_t sfactor_r = shadedfg_r; sfactor_r += sfactor_r >> 7; // 255 -> 256 - uint32_t sfactor_g = shadedfg_g; sfactor_g += sfactor_g >> 7; // 255 -> 256 - uint32_t sfactor_b = shadedfg_b; sfactor_b += sfactor_b >> 7; // 255 -> 256 - uint32_t sfactor_a = fgalpha; sfactor_a += sfactor_a >> 7; // 255 -> 256 - uint32_t dfactor_r = 256 - sfactor_r; - uint32_t dfactor_g = 256 - sfactor_g; - uint32_t dfactor_b = 256 - sfactor_b; - uint32_t out_r = (RPART(dest) * dfactor_r + shadedfg_r * sfactor_r + 128) >> 8; - uint32_t out_g = (GPART(dest) * dfactor_g + shadedfg_g * sfactor_g + 128) >> 8; - uint32_t out_b = (BPART(dest) * dfactor_b + shadedfg_b * sfactor_b + 128) >> 8; - - destLine[x] = MAKEARGB(255, out_r, out_g, out_b); - } - else if (ModeT::BlendSrc == STYLEALPHA_Src && ModeT::BlendDest == STYLEALPHA_InvSrc && fgalpha == 255) - { - destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b); - } - else if (ModeT::BlendSrc != STYLEALPHA_Src || ModeT::BlendDest != STYLEALPHA_InvSrc || fgalpha != 0) - { - uint32_t dest = destLine[x]; - - uint32_t sfactor = fgalpha; sfactor += sfactor >> 7; // 255 -> 256 - uint32_t src_r = shadedfg_r * sfactor; - uint32_t src_g = shadedfg_g * sfactor; - uint32_t src_b = shadedfg_b * sfactor; - uint32_t dest_r = RPART(dest); - uint32_t dest_g = GPART(dest); - uint32_t dest_b = BPART(dest); - if (ModeT::BlendDest == STYLEALPHA_One) - { - dest_r <<= 8; - dest_g <<= 8; - dest_b <<= 8; - } - else - { - uint32_t dfactor = 256 - sfactor; - dest_r *= dfactor; - dest_g *= dfactor; - dest_b *= dfactor; - } - - uint32_t out_r, out_g, out_b; - if (ModeT::BlendOp == STYLEOP_Add) - { - if (ModeT::BlendDest == STYLEALPHA_One) - { - out_r = MIN((dest_r + src_r + 128) >> 8, 255); - out_g = MIN((dest_g + src_g + 128) >> 8, 255); - out_b = MIN((dest_b + src_b + 128) >> 8, 255); - } - else - { - out_r = (dest_r + src_r + 128) >> 8; - out_g = (dest_g + src_g + 128) >> 8; - out_b = (dest_b + src_b + 128) >> 8; - } - } - else if (ModeT::BlendOp == STYLEOP_RevSub) - { - out_r = MAX(static_cast(dest_r - src_r + 128) >> 8, 0); - out_g = MAX(static_cast(dest_g - src_g + 128) >> 8, 0); - out_b = MAX(static_cast(dest_b - src_b + 128) >> 8, 0); - } - else //if (ModeT::BlendOp == STYLEOP_Sub) - { - out_r = MAX(static_cast(src_r - dest_r + 128) >> 8, 0); - out_g = MAX(static_cast(src_g - dest_g + 128) >> 8, 0); - out_b = MAX(static_cast(src_b - dest_b + 128) >> 8, 0); - } - - destLine[x] = MAKEARGB(255, out_r, out_g, out_b); - } - } - } -} - -template -void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread) -{ - using namespace TriScreenDrawerModes; - - if (thread->drawargs.NumLights() == 0 && thread->drawargs.DynLightColor() == 0) - { - if (!thread->drawargs.FixedLight()) - { - if (thread->drawargs.SimpleShade()) - DrawSpanOpt32(y, x0, x1, args, thread); - else - DrawSpanOpt32(y, x0, x1, args, thread); - } - else - { - if (thread->drawargs.SimpleShade()) - DrawSpanOpt32(y, x0, x1, args, thread); - else - DrawSpanOpt32(y, x0, x1, args, thread); - } - } - else - { - if (!thread->drawargs.FixedLight()) - { - if (thread->drawargs.SimpleShade()) - DrawSpanOpt32(y, x0, x1, args, thread); - else - DrawSpanOpt32(y, x0, x1, args, thread); - } - else - { - if (thread->drawargs.SimpleShade()) - DrawSpanOpt32(y, x0, x1, args, thread); - else - DrawSpanOpt32(y, x0, x1, args, thread); - } - } -} - -template -void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread) -{ - using namespace TriScreenDrawerModes; - - StepSpan(y, x0, x1, args, thread); - - uint32_t fixedlight, capcolor; - fixed_t fuzzscale; - int _fuzzpos; - const uint8_t *colormaps, *texPixels, *translation; - uint32_t fillcolor; - int actoralpha; - - uint32_t *texel = thread->texel; - int32_t *texelV = thread->texelV; - uint16_t *lightarray = thread->lightarray; - uint32_t *dynlights = thread->dynlights; - - colormaps = thread->drawargs.BaseColormap(); - - if (!(ModeT::SWFlags & SWSTYLEF_Fill) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary)) - { - texPixels = thread->drawargs.TexturePixels(); - } - - if (ModeT::SWFlags & SWSTYLEF_Translated) - { - translation = thread->drawargs.Translation(); - } - - if ((ModeT::SWFlags & SWSTYLEF_Fill) || (ModeT::SWFlags & SWSTYLEF_Skycap) || (ModeT::Flags & STYLEF_ColorIsFixed)) - { - fillcolor = thread->drawargs.Color(); - } - - if (!(ModeT::Flags & STYLEF_Alpha1)) - { - actoralpha = thread->drawargs.Alpha(); - } - - if (ModeT::SWFlags & SWSTYLEF_Skycap) - capcolor = GPalette.BaseColors[fillcolor].d; - - if (OptT::Flags & SWOPT_FixedLight) - { - fixedlight = thread->drawargs.Light(); - fixedlight += fixedlight >> 7; // 255 -> 256 - fixedlight = ((256 - fixedlight) * NUMCOLORMAPS) & 0xffffff00; - } - - if (ModeT::BlendOp == STYLEOP_Fuzz) - { - fuzzscale = (200 << FRACBITS) / thread->dest_height; - _fuzzpos = swrenderer::fuzzpos; - } - - uint8_t *dest = (uint8_t*)thread->dest; - uint8_t *destLine = dest + thread->dest_pitch * y; - - for (int x = x0; x < x1; x++) - { - if (ModeT::BlendOp == STYLEOP_Fuzz) - { - using namespace swrenderer; - - unsigned int sampleshadeout = (texPixels[texel[x]] != 0) ? 256 : 0; - - int scaled_x = (x * fuzzscale) >> FRACBITS; - int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + _fuzzpos; - - fixed_t fuzzcount = FUZZTABLE << FRACBITS; - fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount; - unsigned int alpha = fuzzoffset[fuzz >> FRACBITS]; - - sampleshadeout = (sampleshadeout * alpha) >> 5; - - uint32_t a = 256 - sampleshadeout; - - uint32_t dest = GPalette.BaseColors[destLine[x]].d; - uint32_t r = (RPART(dest) * a) >> 8; - uint32_t g = (GPART(dest) * a) >> 8; - uint32_t b = (BPART(dest) * a) >> 8; - destLine[x] = RGB256k.All[((r >> 2) << 12) | ((g >> 2) << 6) | (b >> 2)]; - } - else if (ModeT::SWFlags & SWSTYLEF_Skycap) - { - int32_t v = texelV[x]; - int fg = texPixels[texel[x]]; - - int start_fade = 2; // How fast it should fade out - int alpha_top = clamp(v >> (16 - start_fade), 0, 256); - int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256); - int a = MIN(alpha_top, alpha_bottom); - int inv_a = 256 - a; - - if (a == 256) - { - destLine[x] = fg; - } - else - { - uint32_t texelrgb = GPalette.BaseColors[fg].d; - - uint32_t r = RPART(texelrgb); - uint32_t g = GPART(texelrgb); - uint32_t b = BPART(texelrgb); - uint32_t fg_a = APART(texelrgb); - uint32_t bg_red = RPART(capcolor); - uint32_t bg_green = GPART(capcolor); - uint32_t bg_blue = BPART(capcolor); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - - destLine[x] = RGB256k.All[((r >> 2) << 12) | ((g >> 2) << 6) | (b >> 2)]; - } - } - else if (ModeT::SWFlags & SWSTYLEF_FogBoundary) - { - int fg = destLine[x]; - - uint8_t shadedfg; - if (OptT::Flags & SWOPT_FixedLight) - { - shadedfg = colormaps[fixedlight + fg]; - } - else - { - shadedfg = colormaps[lightarray[x] + fg]; - } - - destLine[x] = shadedfg; - } - else - { - int fg; - if (ModeT::SWFlags & SWSTYLEF_Fill) - { - fg = fillcolor; - } - else - { - fg = texPixels[texel[x]]; - } - - int fgalpha = 255; - - if (ModeT::BlendDest == STYLEALPHA_InvSrc) - { - if (fg == 0) - fgalpha = 0; - } - - if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill)) - { - if (ModeT::Flags & STYLEF_RedIsAlpha) - fgalpha = fg; - fg = fillcolor; - } - - if (!(ModeT::Flags & STYLEF_Alpha1)) - { - fgalpha = (fgalpha * actoralpha) >> 8; - } - - if (ModeT::SWFlags & SWSTYLEF_Translated) - fg = translation[fg]; - - uint8_t shadedfg; - if (OptT::Flags & SWOPT_FixedLight) - { - shadedfg = colormaps[fixedlight + fg]; - } - else - { - shadedfg = colormaps[lightarray[x] + fg]; - } - - if (OptT::Flags & SWOPT_DynLights) - { - uint32_t lit = dynlights[x]; - if (lit & 0x00ffffff) - { - uint32_t fgrgb = GPalette.BaseColors[fg]; - uint32_t shadedfgrgb = GPalette.BaseColors[shadedfg]; - - uint32_t out_r = MIN(((RPART(fgrgb) * RPART(lit)) >> 8) + RPART(shadedfgrgb), (uint32_t)255); - uint32_t out_g = MIN(((GPART(fgrgb) * GPART(lit)) >> 8) + GPART(shadedfgrgb), (uint32_t)255); - uint32_t out_b = MIN(((BPART(fgrgb) * BPART(lit)) >> 8) + BPART(shadedfgrgb), (uint32_t)255); - shadedfg = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; - } - } - - if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero) - { - destLine[x] = shadedfg; - } - else if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_One) - { - uint32_t src = GPalette.BaseColors[shadedfg]; - uint32_t dest = GPalette.BaseColors[destLine[x]]; - - if (ModeT::BlendOp == STYLEOP_Add) - { - uint32_t out_r = MIN(RPART(dest) + RPART(src), 255); - uint32_t out_g = MIN(GPART(dest) + GPART(src), 255); - uint32_t out_b = MIN(BPART(dest) + BPART(src), 255); - destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; - } - else if (ModeT::BlendOp == STYLEOP_RevSub) - { - uint32_t out_r = MAX(RPART(dest) - RPART(src), 0); - uint32_t out_g = MAX(GPART(dest) - GPART(src), 0); - uint32_t out_b = MAX(BPART(dest) - BPART(src), 0); - destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; - } - else //if (ModeT::BlendOp == STYLEOP_Sub) - { - uint32_t out_r = MAX(RPART(src) - RPART(dest), 0); - uint32_t out_g = MAX(GPART(src) - GPART(dest), 0); - uint32_t out_b = MAX(BPART(src) - BPART(dest), 0); - destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; - } - } - else if (ModeT::SWFlags & SWSTYLEF_SrcColorOneMinusSrcColor) - { - uint32_t src = GPalette.BaseColors[shadedfg]; - uint32_t dest = GPalette.BaseColors[destLine[x]]; - - uint32_t sfactor_r = RPART(src); sfactor_r += sfactor_r >> 7; // 255 -> 256 - uint32_t sfactor_g = GPART(src); sfactor_g += sfactor_g >> 7; // 255 -> 256 - uint32_t sfactor_b = BPART(src); sfactor_b += sfactor_b >> 7; // 255 -> 256 - uint32_t sfactor_a = fgalpha; sfactor_a += sfactor_a >> 7; // 255 -> 256 - uint32_t dfactor_r = 256 - sfactor_r; - uint32_t dfactor_g = 256 - sfactor_g; - uint32_t dfactor_b = 256 - sfactor_b; - uint32_t out_r = (RPART(dest) * dfactor_r + RPART(src) * sfactor_r + 128) >> 8; - uint32_t out_g = (GPART(dest) * dfactor_g + GPART(src) * sfactor_g + 128) >> 8; - uint32_t out_b = (BPART(dest) * dfactor_b + BPART(src) * sfactor_b + 128) >> 8; - - destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; - } - else if (ModeT::BlendSrc == STYLEALPHA_Src && ModeT::BlendDest == STYLEALPHA_InvSrc && fgalpha == 255) - { - destLine[x] = shadedfg; - } - else if (ModeT::BlendSrc != STYLEALPHA_Src || ModeT::BlendDest != STYLEALPHA_InvSrc || fgalpha != 0) - { - uint32_t src = GPalette.BaseColors[shadedfg]; - uint32_t dest = GPalette.BaseColors[destLine[x]]; - - uint32_t sfactor = fgalpha; sfactor += sfactor >> 7; // 255 -> 256 - uint32_t dfactor = 256 - sfactor; - uint32_t src_r = RPART(src) * sfactor; - uint32_t src_g = GPART(src) * sfactor; - uint32_t src_b = BPART(src) * sfactor; - uint32_t dest_r = RPART(dest); - uint32_t dest_g = GPART(dest); - uint32_t dest_b = BPART(dest); - if (ModeT::BlendDest == STYLEALPHA_One) - { - dest_r <<= 8; - dest_g <<= 8; - dest_b <<= 8; - } - else - { - uint32_t dfactor = 256 - sfactor; - dest_r *= dfactor; - dest_g *= dfactor; - dest_b *= dfactor; - } - - uint32_t out_r, out_g, out_b; - if (ModeT::BlendOp == STYLEOP_Add) - { - if (ModeT::BlendDest == STYLEALPHA_One) - { - out_r = MIN((dest_r + src_r + 128) >> 8, 255); - out_g = MIN((dest_g + src_g + 128) >> 8, 255); - out_b = MIN((dest_b + src_b + 128) >> 8, 255); - } - else - { - out_r = (dest_r + src_r + 128) >> 8; - out_g = (dest_g + src_g + 128) >> 8; - out_b = (dest_b + src_b + 128) >> 8; - } - } - else if (ModeT::BlendOp == STYLEOP_RevSub) - { - out_r = MAX(static_cast(dest_r - src_r + 128) >> 8, 0); - out_g = MAX(static_cast(dest_g - src_g + 128) >> 8, 0); - out_b = MAX(static_cast(dest_b - src_b + 128) >> 8, 0); - } - else //if (ModeT::BlendOp == STYLEOP_Sub) - { - out_r = MAX(static_cast(src_r - dest_r + 128) >> 8, 0); - out_g = MAX(static_cast(src_g - dest_g + 128) >> 8, 0); - out_b = MAX(static_cast(src_b - dest_b + 128) >> 8, 0); - } - - destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)]; - } - } - } -} - -template -void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread) -{ - using namespace TriScreenDrawerModes; - - if (thread->drawargs.NumLights() == 0 && thread->drawargs.DynLightColor() == 0) - { - if (!thread->drawargs.FixedLight()) - DrawSpanOpt8(y, x0, x1, args, thread); - else - DrawSpanOpt8(y, x0, x1, args, thread); - } - else - { - if (!thread->drawargs.FixedLight()) - DrawSpanOpt8(y, x0, x1, args, thread); - else - DrawSpanOpt8(y, x0, x1, args, thread); - } -} - -void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *, PolyTriangleThreadData *) = -{ - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8, - &DrawSpan8 -}; - -void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs *, PolyTriangleThreadData *) = -{ - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32, - &DrawSpan32 -}; - -void(*ScreenTriangle::TriangleDrawers[])(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread, int16_t *edges, int topY, int bottomY) = -{ - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle, - &DrawTriangle -}; - -int ScreenTriangle::FuzzStart = 0; - -#endif diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.h b/src/rendering/polyrenderer/drawers/screen_triangle.h index 8da0eca89..9deee30cd 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.h +++ b/src/rendering/polyrenderer/drawers/screen_triangle.h @@ -149,133 +149,3 @@ namespace TriScreenDrawerModes struct TestSpanOpt2 { static const int Flags = 2; }; struct TestSpanOpt3 { static const int Flags = 3; }; } - -#if 0 - -class ScreenTriangle -{ -public: - static void Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); - - static void(*TriangleDrawers[])(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread, int16_t *edges, int topY, int bottomY); - - 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); - - static int FuzzStart; -}; - -namespace TriScreenDrawerModes -{ - enum SWStyleFlags - { - SWSTYLEF_Translated = 1, - SWSTYLEF_Skycap = 2, - SWSTYLEF_FogBoundary = 4, - SWSTYLEF_Fill = 8, - SWSTYLEF_SrcColorOneMinusSrcColor = 16, - SWSTYLEF_AlphaTest = 32 - }; - - struct StyleOpaque { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = 0; }; - struct StyleSkycap { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Skycap; }; - struct StyleFogBoundary { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_FogBoundary; }; - struct StyleSrcColor { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_SrcColorOneMinusSrcColor; }; - struct StyleFill { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Fill; }; - struct StyleFillTranslucent { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Fill; }; - - struct StyleNormal { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = 0; }; - struct StyleAlphaTest { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_AlphaTest; }; - struct StyleFuzzy { static const int BlendOp = STYLEOP_Fuzz, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; }; - struct StyleStencil { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1 | STYLEF_ColorIsFixed, SWFlags = 0; }; - struct StyleTranslucent { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; }; - struct StyleAdd { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = 0, SWFlags = 0; }; - struct StyleShaded { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, SWFlags = 0; }; - struct StyleTranslucentStencil { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_ColorIsFixed, SWFlags = 0; }; - struct StyleShadow { static const int BlendOp = STYLEOP_Shadow, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; }; - struct StyleSubtract { static const int BlendOp = STYLEOP_RevSub, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = 0, SWFlags = 0; }; - struct StyleAddStencil { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_ColorIsFixed, SWFlags = 0; }; - struct StyleAddShaded { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, SWFlags = 0; }; - - struct StyleOpaqueTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Translated; }; - struct StyleSrcColorTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Translated|SWSTYLEF_SrcColorOneMinusSrcColor; }; - struct StyleNormalTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Translated; }; - struct StyleStencilTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1 | STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; }; - struct StyleTranslucentTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = SWSTYLEF_Translated; }; - struct StyleAddTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = 0, SWFlags = SWSTYLEF_Translated; }; - struct StyleShadedTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; }; - struct StyleTranslucentStencilTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; }; - struct StyleShadowTranslated { static const int BlendOp = STYLEOP_Shadow, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = SWSTYLEF_Translated; }; - struct StyleSubtractTranslated { static const int BlendOp = STYLEOP_RevSub, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = 0, SWFlags = SWSTYLEF_Translated; }; - struct StyleAddStencilTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; }; - struct StyleAddShadedTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; }; - - enum SWOptFlags - { - SWOPT_DynLights = 1, - SWOPT_ColoredFog = 2, - SWOPT_FixedLight = 4 - }; - - struct DrawerOpt { static const int Flags = 0; }; - struct DrawerOptF { static const int Flags = SWOPT_FixedLight; }; - struct DrawerOptC { static const int Flags = SWOPT_ColoredFog; }; - struct DrawerOptCF { static const int Flags = SWOPT_ColoredFog | SWOPT_FixedLight; }; - struct DrawerOptL { static const int Flags = SWOPT_DynLights; }; - struct DrawerOptLC { static const int Flags = SWOPT_DynLights | SWOPT_ColoredFog; }; - struct DrawerOptLF { static const int Flags = SWOPT_DynLights | SWOPT_FixedLight; }; - struct DrawerOptLCF { static const int Flags = SWOPT_DynLights | SWOPT_ColoredFog | SWOPT_FixedLight; }; - - static const int fuzzcolormap[FUZZTABLE] = - { - 6, 11, 6, 11, 6, 6, 11, 6, 6, 11, - 6, 6, 6, 11, 6, 6, 6, 11, 15, 18, - 21, 6, 11, 15, 6, 6, 6, 6, 11, 6, - 11, 6, 6, 11, 15, 6, 6, 11, 15, 18, - 21, 6, 6, 6, 6, 11, 6, 6, 11, 6, - }; - - enum SWTriangleFlags - { - SWTRI_DepthTest = 1, - SWTRI_StencilTest = 2, - SWTRI_WriteColor = 4, - SWTRI_WriteDepth = 8, - SWTRI_WriteStencil = 16 - }; - - struct TriangleOpt0 { static const int Flags = 0; }; - struct TriangleOpt1 { static const int Flags = 1; }; - struct TriangleOpt2 { static const int Flags = 2; }; - struct TriangleOpt3 { static const int Flags = 3; }; - struct TriangleOpt4 { static const int Flags = 4; }; - struct TriangleOpt5 { static const int Flags = 5; }; - struct TriangleOpt6 { static const int Flags = 6; }; - struct TriangleOpt7 { static const int Flags = 7; }; - struct TriangleOpt8 { static const int Flags = 8; }; - struct TriangleOpt9 { static const int Flags = 9; }; - struct TriangleOpt10 { static const int Flags = 10; }; - struct TriangleOpt11 { static const int Flags = 11; }; - struct TriangleOpt12 { static const int Flags = 12; }; - struct TriangleOpt13 { static const int Flags = 13; }; - struct TriangleOpt14 { static const int Flags = 14; }; - struct TriangleOpt15 { static const int Flags = 15; }; - struct TriangleOpt16 { static const int Flags = 16; }; - struct TriangleOpt17 { static const int Flags = 17; }; - struct TriangleOpt18 { static const int Flags = 18; }; - struct TriangleOpt19 { static const int Flags = 19; }; - struct TriangleOpt20 { static const int Flags = 20; }; - struct TriangleOpt21 { static const int Flags = 21; }; - struct TriangleOpt22 { static const int Flags = 22; }; - struct TriangleOpt23 { static const int Flags = 23; }; - struct TriangleOpt24 { static const int Flags = 24; }; - struct TriangleOpt25 { static const int Flags = 25; }; - struct TriangleOpt26 { static const int Flags = 26; }; - struct TriangleOpt27 { static const int Flags = 27; }; - struct TriangleOpt28 { static const int Flags = 28; }; - struct TriangleOpt29 { static const int Flags = 29; }; - struct TriangleOpt30 { static const int Flags = 30; }; - struct TriangleOpt31 { static const int Flags = 31; }; -} - -#endif From 4a4b79194dd50426205fff32a01938251862ba2f Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 1 Dec 2019 23:37:43 +0100 Subject: [PATCH 46/60] Remove/disable old swrenderer model rendering code --- .../polyrenderer/drawers/poly_draw_args.h | 4 +- .../polyrenderer/drawers/poly_triangle.cpp | 68 --------------- .../polyrenderer/drawers/poly_triangle.h | 86 ------------------- .../polyrenderer/drawers/poly_vertex_shader.h | 60 ------------- src/rendering/swrenderer/things/r_model.cpp | 6 ++ src/rendering/swrenderer/things/r_model.h | 2 + 6 files changed, 10 insertions(+), 216 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.h b/src/rendering/polyrenderer/drawers/poly_draw_args.h index 2b89f9d1e..44ad4c776 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.h +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.h @@ -67,7 +67,7 @@ struct PolyLight class PolyDrawArgs { public: - void SetClipPlane(int index, const PolyClipPlane &plane) { mClipPlane[index] = plane; } + //void SetClipPlane(int index, const PolyClipPlane &plane) { mClipPlane[index] = plane; } void SetTexture(const uint8_t *texels, int width, int height); void SetTexture(FSoftwareTexture *texture, FRenderStyle style); void SetTexture(FSoftwareTexture *texture, uint32_t translationID, FRenderStyle style); @@ -86,7 +86,7 @@ public: void SetLights(PolyLight *lights, int numLights) { mLights = lights; mNumLights = numLights; } void SetDynLightColor(uint32_t color) { mDynLightColor = color; } - const PolyClipPlane &ClipPlane(int index) const { return mClipPlane[index]; } + //const PolyClipPlane &ClipPlane(int index) const { return mClipPlane[index]; } bool WriteColor() const { return mWriteColor; } diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 0afe496a5..4f895b82e 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -73,31 +73,6 @@ void PolyTriangleDrawer::SetInputAssembly(const DrawerCommandQueuePtr &queue, Po queue->Push(input); } -void PolyTriangleDrawer::SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld) -{ - queue->Push(objectToClip, objectToWorld); -} - -void PolyTriangleDrawer::SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw) -{ - queue->Push(ccw); -} - -void PolyTriangleDrawer::SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided) -{ - queue->Push(twosided); -} - -void PolyTriangleDrawer::SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable) -{ - queue->Push(enable); -} - -void PolyTriangleDrawer::SetModelVertexShader(const DrawerCommandQueuePtr &queue, int frame1, int frame2, float interpolationFactor) -{ - queue->Push(frame1, frame2, interpolationFactor); -} - void PolyTriangleDrawer::SetVertexBuffer(const DrawerCommandQueuePtr &queue, const void *vertices) { queue->Push(vertices); @@ -113,11 +88,6 @@ void PolyTriangleDrawer::SetLightBuffer(const DrawerCommandQueuePtr& queue, cons queue->Push(lights); } -void PolyTriangleDrawer::PushDrawArgs(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args) -{ - queue->Push(args); -} - void PolyTriangleDrawer::SetDepthClamp(const DrawerCommandQueuePtr &queue, bool on) { queue->Push(on); @@ -287,17 +257,6 @@ void PolyTriangleThreadData::UpdateClip() clip.bottom = MIN(MIN(viewport_y + viewport_height, scissor.bottom), dest_height); } -void PolyTriangleThreadData::SetTransform(const Mat4f *newObjectToClip, const Mat4f *newObjectToWorld) -{ - swVertexShader.objectToClip = newObjectToClip; - swVertexShader.objectToWorld = newObjectToWorld; -} - -void PolyTriangleThreadData::PushDrawArgs(const PolyDrawArgs &args) -{ - drawargs = args; -} - void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPushConstants &constants) { mainVertexShader.Data = data; @@ -595,33 +554,6 @@ ShadedTriVertex PolyTriangleThreadData::ShadeVertex(int index) return mainVertexShader; } -void PolySWInputAssembly::Load(PolyTriangleThreadData *thread, const void *vertices, int index) -{ - if (thread->modelFrame1 == -1) - { - thread->swVertexShader.v1 = static_cast(vertices)[index]; - } - else - { - const FModelVertex &v1 = static_cast(vertices)[thread->modelFrame1 + index]; - const FModelVertex &v2 = static_cast(vertices)[thread->modelFrame2 + index]; - - thread->swVertexShader.v1.x = v1.x; - thread->swVertexShader.v1.y = v1.y; - thread->swVertexShader.v1.z = v1.z; - thread->swVertexShader.v1.w = 1.0f; - thread->swVertexShader.v1.u = v1.u; - thread->swVertexShader.v1.v = v1.v; - - thread->swVertexShader.v2.x = v2.x; - thread->swVertexShader.v2.y = v2.y; - thread->swVertexShader.v2.z = v2.z; - thread->swVertexShader.v2.w = 1.0f; - thread->swVertexShader.v2.u = v2.u; - thread->swVertexShader.v2.v = v2.v; - } -} - bool PolyTriangleThreadData::IsDegenerate(const ShadedTriVertex *const* vert) { // A degenerate triangle has a zero cross product for two of its sides. diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 1e3cb1467..b8da0ac22 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -66,14 +66,6 @@ public: static void Draw(const DrawerCommandQueuePtr &queue, int index, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); static void DrawIndexed(const DrawerCommandQueuePtr &queue, int index, int count, PolyDrawMode mode = PolyDrawMode::Triangles); static bool IsBgra(); - - // Old softpoly/swrenderer interface - static void SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw); - static void SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided); - static void SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable); - static void SetModelVertexShader(const DrawerCommandQueuePtr &queue, int frame1, int frame2, float interpolationFactor); - static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld); - static void PushDrawArgs(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args); }; class PolyDepthStencil @@ -116,30 +108,20 @@ public: virtual void Load(PolyTriangleThreadData *thread, const void *vertices, int index) = 0; }; -class PolySWInputAssembly : public PolyInputAssembly -{ -public: - void Load(PolyTriangleThreadData *thread, const void *vertices, int index) override; -}; - class PolyTriangleThreadData { public: PolyTriangleThreadData(int32_t core, int32_t num_cores, int32_t numa_node, int32_t num_numa_nodes, int numa_start_y, int numa_end_y) : core(core), num_cores(num_cores), numa_node(numa_node), num_numa_nodes(num_numa_nodes), numa_start_y(numa_start_y), numa_end_y(numa_end_y) { - swVertexShader.drawargs = &drawargs; } void ClearDepth(float value); void ClearStencil(uint8_t value); void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, PolyDepthStencil *depthstencil); - void SetTransform(const Mat4f *objectToClip, const Mat4f *objectToWorld); void SetCullCCW(bool value) { ccw = value; } void SetTwoSided(bool value) { twosided = value; } - void SetWeaponScene(bool value) { depthbias = value ? -1.0f : 0.0f; } - void SetModelVertexShader(int frame1, int frame2, float interpolationFactor) { modelFrame1 = frame1; modelFrame2 = frame2; swVertexShader.modelInterpolationFactor = interpolationFactor; } void SetInputAssembly(PolyInputAssembly *input) { inputAssembly = input; } void SetVertexBuffer(const void *data) { vertices = data; } @@ -164,7 +146,6 @@ public: void UpdateClip(); - void PushDrawArgs(const PolyDrawArgs &args); void PushStreamData(const StreamData &data, const PolyPushConstants &constants); void PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); @@ -249,10 +230,6 @@ public: PolyMainVertexShader mainVertexShader; - int modelFrame1 = -1; - int modelFrame2 = -1; - PolySWVertexShader swVertexShader; - private: ShadedTriVertex ShadeVertex(int index); void DrawShadedPoint(const ShadedTriVertex *const* vertex); @@ -485,59 +462,6 @@ private: PolyInputAssembly *input; }; -class PolySetTransformCommand : public PolyDrawerCommand -{ -public: - PolySetTransformCommand(const Mat4f *objectToClip, const Mat4f *objectToWorld) : objectToClip(objectToClip), objectToWorld(objectToWorld) { } - void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetTransform(objectToClip, objectToWorld); } - -private: - const Mat4f *objectToClip; - const Mat4f *objectToWorld; -}; - -class PolySetCullCCWCommand : public PolyDrawerCommand -{ -public: - PolySetCullCCWCommand(bool ccw) : ccw(ccw) { } - void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetCullCCW(ccw); } - -private: - bool ccw; -}; - -class PolySetTwoSidedCommand : public PolyDrawerCommand -{ -public: - PolySetTwoSidedCommand(bool twosided) : twosided(twosided) { } - void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetTwoSided(twosided); } - -private: - bool twosided; -}; - -class PolySetWeaponSceneCommand : public PolyDrawerCommand -{ -public: - PolySetWeaponSceneCommand(bool value) : value(value) { } - void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetWeaponScene(value); } - -private: - bool value; -}; - -class PolySetModelVertexShaderCommand : public PolyDrawerCommand -{ -public: - PolySetModelVertexShaderCommand(int frame1, int frame2, float interpolationFactor) : frame1(frame1), frame2(frame2), interpolationFactor(interpolationFactor) { } - void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetModelVertexShader(frame1, frame2, interpolationFactor); } - -private: - int frame1; - int frame2; - float interpolationFactor; -}; - class PolyClearDepthCommand : public PolyDrawerCommand { public: @@ -612,16 +536,6 @@ private: PolyPushConstants constants; }; -class PolyPushDrawArgsCommand : public PolyDrawerCommand -{ -public: - PolyPushDrawArgsCommand(const PolyDrawArgs &args) : args(args) { } - void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->PushDrawArgs(args); } - -private: - PolyDrawArgs args; -}; - class PolyDrawCommand : public PolyDrawerCommand { public: diff --git a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h index 6c080552f..a3797ee7f 100644 --- a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h +++ b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h @@ -197,63 +197,3 @@ private: return result; } }; - -class PolySWVertexShader : public ShadedTriVertex -{ -public: - // Input - TriVertex v1; - TriVertex v2; - - // Uniforms - float modelInterpolationFactor = 0.0f; - const Mat4f *objectToClip = nullptr; - const Mat4f *objectToWorld = nullptr; - PolyDrawArgs *drawargs = nullptr; - - void main() - { - Vec4f objpos; - - if (modelInterpolationFactor == 0.f) - { - objpos = Vec4f(v1.x, v1.y, v1.z, v1.w); - vTexCoord.X = v1.u; - vTexCoord.Y = v1.v; - } - else - { - float frac = modelInterpolationFactor; - float inv_frac = 1.0f - frac; - - objpos = Vec4f(v1.x * inv_frac + v2.x * frac, v1.y * inv_frac + v2.y * frac, v1.z * inv_frac + v2.z * frac, 1.0f); - vTexCoord.X = v1.u; - vTexCoord.Y = v1.v; - } - - // Apply transform to get clip coordinates: - gl_Position = (*objectToClip) * objpos; - - if (!objectToWorld) // Identity matrix - { - pixelpos = objpos; - } - else - { - pixelpos = (*objectToWorld) * objpos; - } - - vColor = drawargs->Color(); - - vWorldNormal = { drawargs->Normal().X, drawargs->Normal().Y, drawargs->Normal().Z }; - - // Calculate gl_ClipDistance[i] - for (int i = 0; i < 3; i++) - { - const auto &clipPlane = drawargs->ClipPlane(i); - gl_ClipDistance[i] = objpos.X * clipPlane.A + objpos.Y * clipPlane.B + objpos.Z * clipPlane.C + objpos.W * clipPlane.D; - } - gl_ClipDistance[3] = 1.0f; - gl_ClipDistance[4] = 1.0f; - } -}; diff --git a/src/rendering/swrenderer/things/r_model.cpp b/src/rendering/swrenderer/things/r_model.cpp index 227556d04..38356f30d 100644 --- a/src/rendering/swrenderer/things/r_model.cpp +++ b/src/rendering/swrenderer/things/r_model.cpp @@ -74,6 +74,7 @@ namespace swrenderer void RenderModel::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) { +#if 0 SWModelRenderer renderer(thread, clip3DFloor, &WorldToClip, MirrorWorldToClip); renderer.sector = actor->Sector; @@ -94,6 +95,7 @@ namespace swrenderer renderer.AddLights(actor); renderer.RenderModel(x, y, z, smf, actor, r_viewpoint.TicFrac); PolyTriangleDrawer::SetModelVertexShader(thread->DrawQueue, -1, -1, 0.0f); +#endif } ///////////////////////////////////////////////////////////////////////////// @@ -116,6 +118,7 @@ namespace swrenderer void RenderHUDModel(RenderThread *thread, DPSprite *psp, float ofsx, float ofsy) { +#if 0 SWModelRenderer renderer(thread, Fake3DTranslucent(), &thread->Viewport->WorldToClip, false); AActor *playermo = players[consoleplayer].camera; @@ -141,10 +144,12 @@ namespace swrenderer renderer.RenderHUDModel(psp, ofsx, ofsy); PolyTriangleDrawer::SetModelVertexShader(thread->DrawQueue, -1, -1, 0.0f); +#endif } ///////////////////////////////////////////////////////////////////////////// +#if 0 SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor, Mat4f *worldToClip, bool mirrorWorldToClip) : Thread(thread), Clip3DFloor(clip3DFloor), WorldToClip(worldToClip), MirrorWorldToClip(mirrorWorldToClip) { @@ -431,4 +436,5 @@ namespace swrenderer PolyTriangleDrawer::SetModelVertexShader(swrenderer->Thread->DrawQueue, frame1, frame2, swrenderer->InterpolationFactor); } +#endif } diff --git a/src/rendering/swrenderer/things/r_model.h b/src/rendering/swrenderer/things/r_model.h index 7fea29227..2ce2bf6a4 100644 --- a/src/rendering/swrenderer/things/r_model.h +++ b/src/rendering/swrenderer/things/r_model.h @@ -53,6 +53,7 @@ namespace swrenderer bool MirrorWorldToClip; }; +#if 0 class SWModelRenderer : public FModelRenderer { public: @@ -115,4 +116,5 @@ namespace swrenderer TArray mVertexBuffer; TArray mIndexBuffer; }; +#endif } From d2f457033775a231b69f99a5a3d51eed424d030f Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 2 Dec 2019 00:01:04 +0100 Subject: [PATCH 47/60] Remove old polyargs --- .../polyrenderer/backend/poly_buffers.h | 2 - .../polyrenderer/drawers/poly_draw_args.cpp | 302 ------------------ .../polyrenderer/drawers/poly_draw_args.h | 105 ------ .../polyrenderer/drawers/poly_triangle.cpp | 7 +- .../polyrenderer/drawers/poly_triangle.h | 18 +- .../polyrenderer/drawers/screen_triangle.h | 34 -- 6 files changed, 19 insertions(+), 449 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_buffers.h b/src/rendering/polyrenderer/backend/poly_buffers.h index 53585e95e..35376f291 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.h +++ b/src/rendering/polyrenderer/backend/poly_buffers.h @@ -11,8 +11,6 @@ #pragma warning(disable:4250) #endif -struct TriVertex; - class PolyBuffer : virtual public IBuffer { public: diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.cpp b/src/rendering/polyrenderer/drawers/poly_draw_args.cpp index b18619b74..1a04a28f6 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.cpp @@ -40,23 +40,9 @@ void PolyDrawArgs::SetTexture(const uint8_t *texels, int width, int height) { - mTexture = nullptr; mTexturePixels = texels; mTextureWidth = width; mTextureHeight = height; - mTranslation = nullptr; -} - -void PolyDrawArgs::SetTexture(FSoftwareTexture *texture, FRenderStyle style) -{ - mTexture = texture; - mTextureWidth = texture->GetPhysicalWidth(); - mTextureHeight = texture->GetPhysicalHeight(); - if (PolyTriangleDrawer::IsBgra()) - mTexturePixels = (const uint8_t *)texture->GetPixelsBgra(); - else - mTexturePixels = texture->GetPixels(style); - mTranslation = nullptr; } void PolyDrawArgs::SetTexture2(const uint8_t* texels, int width, int height) @@ -65,291 +51,3 @@ void PolyDrawArgs::SetTexture2(const uint8_t* texels, int width, int height) mTexture2Width = width; mTexture2Height = height; } - -void PolyDrawArgs::SetTexture(FSoftwareTexture *texture, uint32_t translationID, FRenderStyle style) -{ - // Alphatexture overrides translations. - if (translationID != 0xffffffff && translationID != 0 && !(style.Flags & STYLEF_RedIsAlpha)) - { - FRemapTable *table = TranslationToTable(translationID); - if (table != nullptr && !table->Inactive) - { - if (PolyTriangleDrawer::IsBgra()) - mTranslation = (uint8_t*)table->Palette; - else - mTranslation = table->Remap; - - mTexture = texture; - mTextureWidth = texture->GetPhysicalWidth(); - mTextureHeight = texture->GetPhysicalHeight(); - mTexturePixels = texture->GetPixels(style); - return; - } - } - - if (style.Flags & STYLEF_RedIsAlpha) - { - mTexture = texture; - mTextureWidth = texture->GetPhysicalWidth(); - mTextureHeight = texture->GetPhysicalHeight(); - mTexturePixels = texture->GetPixels(style); - } - else - { - SetTexture(texture, style); - } -} - -void PolyDrawArgs::SetLight(FSWColormap *base_colormap, uint32_t lightlevel, double globVis, bool fixed) -{ - mGlobVis = (float)globVis; - - mLight = clamp(lightlevel, 0, 255); - mFixedLight = fixed; - mLightRed = base_colormap->Color.r; - mLightRed += mLightRed >> 7; - mLightGreen = base_colormap->Color.g; - mLightGreen += mLightGreen >> 7; - mLightBlue = base_colormap->Color.b; - mLightBlue += mLightBlue >> 7; - mLightAlpha = base_colormap->Color.a; - mLightAlpha += mLightAlpha >> 7; - mFadeRed = base_colormap->Fade.r; - mFadeRed += mFadeRed >> 7; - mFadeGreen = base_colormap->Fade.g; - mFadeGreen += mFadeGreen >> 7; - mFadeBlue = base_colormap->Fade.b; - mFadeBlue += mFadeBlue >> 7; - mFadeAlpha = base_colormap->Fade.a; - mFadeAlpha += mFadeAlpha >> 7; - mDesaturate = MIN(abs(base_colormap->Desaturate), 255); - mDesaturate += mDesaturate >> 7; - mSimpleShade = (base_colormap->Color.d == 0x00ffffff && base_colormap->Fade.d == 0x00000000 && base_colormap->Desaturate == 0); - mColormaps = base_colormap->Maps; -} - -void PolyDrawArgs::SetColor(uint32_t bgra, uint8_t palindex) -{ - if (PolyTriangleDrawer::IsBgra()) - { - mColor = bgra; - } - else - { - mColor = palindex; - } -} - -void PolyDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FSoftwareTexture *tex, bool fullbright) -{ - SetTexture(tex, translationID, renderstyle); - SetColor(0xff000000 | fillcolor, fillcolor >> 24); - - if (renderstyle == LegacyRenderStyles[STYLE_Normal] || (r_drawfuzz == 0 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) - { - SetStyle(Translation() ? TriBlendMode::NormalTranslated : TriBlendMode::Normal, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Add] && fullbright && alpha == 1.0 && !Translation()) - { - SetStyle(TriBlendMode::SrcColor, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_SoulTrans]) - { - SetStyle(Translation() ? TriBlendMode::AddTranslated : TriBlendMode::Add, transsouls); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Fuzzy] || (r_drawfuzz == 1 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) - { - SetColor(0xff000000, 0); - SetStyle(TriBlendMode::Fuzzy); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Shadow] || (r_drawfuzz == 2 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) - { - SetColor(0xff000000, 0); - SetStyle(Translation() ? TriBlendMode::TranslucentStencilTranslated : TriBlendMode::TranslucentStencil, 1.0 - 160 / 255.0); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Stencil]) - { - SetStyle(Translation() ? TriBlendMode::StencilTranslated : TriBlendMode::Stencil, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Translucent]) - { - SetStyle(Translation() ? TriBlendMode::TranslucentTranslated : TriBlendMode::Translucent, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Add]) - { - SetStyle(Translation() ? TriBlendMode::AddTranslated : TriBlendMode::Add, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Shaded]) - { - SetStyle(Translation() ? TriBlendMode::ShadedTranslated : TriBlendMode::Shaded, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_TranslucentStencil]) - { - SetStyle(Translation() ? TriBlendMode::TranslucentStencilTranslated : TriBlendMode::TranslucentStencil, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Subtract]) - { - SetStyle(Translation() ? TriBlendMode::SubtractTranslated : TriBlendMode::Subtract, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_AddStencil]) - { - SetStyle(Translation() ? TriBlendMode::AddStencilTranslated : TriBlendMode::AddStencil, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_AddShaded]) - { - SetStyle(Translation() ? TriBlendMode::AddShadedTranslated : TriBlendMode::AddShaded, alpha); - } -} - -///////////////////////////////////////////////////////////////////////////// - -#if 0 -void RectDrawArgs::SetTexture(FSoftwareTexture *texture, FRenderStyle style) -{ - mTexture = texture; - mTextureWidth = texture->GetWidth(); - mTextureHeight = texture->GetHeight(); - if (PolyTriangleDrawer::IsBgra()) - mTexturePixels = (const uint8_t *)texture->GetPixelsBgra(); - else - mTexturePixels = texture->GetPixels(style); - mTranslation = nullptr; -} - -void RectDrawArgs::SetTexture(FSoftwareTexture *texture, uint32_t translationID, FRenderStyle style) -{ - // Alphatexture overrides translations. - if (translationID != 0xffffffff && translationID != 0 && !(style.Flags & STYLEF_RedIsAlpha)) - { - FRemapTable *table = TranslationToTable(translationID); - if (table != nullptr && !table->Inactive) - { - if (PolyTriangleDrawer::IsBgra()) - mTranslation = (uint8_t*)table->Palette; - else - mTranslation = table->Remap; - - mTexture = texture; - mTextureWidth = texture->GetWidth(); - mTextureHeight = texture->GetHeight(); - mTexturePixels = texture->GetPixels(style); - return; - } - } - - if (style.Flags & STYLEF_RedIsAlpha) - { - mTexture = texture; - mTextureWidth = texture->GetWidth(); - mTextureHeight = texture->GetHeight(); - mTexturePixels = texture->GetPixels(style); - } - else - { - SetTexture(texture, style); - } -} - -void RectDrawArgs::SetLight(FSWColormap *base_colormap, uint32_t lightlevel) -{ - mLight = clamp(lightlevel, 0, 255); - mLightRed = base_colormap->Color.r * 256 / 255; - mLightGreen = base_colormap->Color.g * 256 / 255; - mLightBlue = base_colormap->Color.b * 256 / 255; - mLightAlpha = base_colormap->Color.a * 256 / 255; - mFadeRed = base_colormap->Fade.r; - mFadeGreen = base_colormap->Fade.g; - mFadeBlue = base_colormap->Fade.b; - mFadeAlpha = base_colormap->Fade.a; - mDesaturate = MIN(abs(base_colormap->Desaturate), 255) * 255 / 256; - mSimpleShade = (base_colormap->Color.d == 0x00ffffff && base_colormap->Fade.d == 0x00000000 && base_colormap->Desaturate == 0); - mColormaps = base_colormap->Maps; -} - -void RectDrawArgs::SetColor(uint32_t bgra, uint8_t palindex) -{ - if (PolyTriangleDrawer::IsBgra()) - { - mColor = bgra; - } - else - { - mColor = palindex; - } -} - -void RectDrawArgs::Draw(PolyRenderThread *thread, double x0, double x1, double y0, double y1, double u0, double u1, double v0, double v1) -{ - mX0 = (float)x0; - mX1 = (float)x1; - mY0 = (float)y0; - mY1 = (float)y1; - mU0 = (float)u0; - mU1 = (float)u1; - mV0 = (float)v0; - mV1 = (float)v1; - - thread->DrawQueue->Push(*this); -} - -void RectDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FSoftwareTexture *tex, bool fullbright) -{ - SetTexture(tex, translationID, renderstyle); - SetColor(0xff000000 | fillcolor, fillcolor >> 24); - - if (renderstyle == LegacyRenderStyles[STYLE_Normal] || (r_drawfuzz == 0 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) - { - SetStyle(Translation() ? TriBlendMode::NormalTranslated : TriBlendMode::Normal, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Add] && fullbright && alpha == 1.0 && !Translation()) - { - SetStyle(TriBlendMode::SrcColor, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_SoulTrans]) - { - SetStyle(Translation() ? TriBlendMode::AddTranslated : TriBlendMode::Add, transsouls); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Fuzzy] || (r_drawfuzz == 1 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) - { - SetColor(0xff000000, 0); - SetStyle(TriBlendMode::Fuzzy); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Shadow] || (r_drawfuzz == 2 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) - { - SetColor(0xff000000, 0); - SetStyle(Translation() ? TriBlendMode::TranslucentStencilTranslated : TriBlendMode::TranslucentStencil, 1.0 - 160 / 255.0); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Stencil]) - { - SetStyle(Translation() ? TriBlendMode::StencilTranslated : TriBlendMode::Stencil, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Translucent]) - { - SetStyle(Translation() ? TriBlendMode::TranslucentTranslated : TriBlendMode::Translucent, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Add]) - { - SetStyle(Translation() ? TriBlendMode::AddTranslated : TriBlendMode::Add, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Shaded]) - { - SetStyle(Translation() ? TriBlendMode::ShadedTranslated : TriBlendMode::Shaded, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_TranslucentStencil]) - { - SetStyle(Translation() ? TriBlendMode::TranslucentStencilTranslated : TriBlendMode::TranslucentStencil, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_Subtract]) - { - SetStyle(Translation() ? TriBlendMode::SubtractTranslated : TriBlendMode::Subtract, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_AddStencil]) - { - SetStyle(Translation() ? TriBlendMode::AddStencilTranslated : TriBlendMode::AddStencil, alpha); - } - else if (renderstyle == LegacyRenderStyles[STYLE_AddShaded]) - { - 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 44ad4c776..9835e33f5 100644 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.h +++ b/src/rendering/polyrenderer/drawers/poly_draw_args.h @@ -26,75 +26,23 @@ #include "r_data/colormaps.h" #include "screen_triangle.h" -class PolyRenderThread; -class FSoftwareTexture; -class Mat4f; - -enum class PolyDrawMode -{ - Points, - Lines, - Triangles, - TriangleFan, - TriangleStrip -}; - -class PolyClipPlane -{ -public: - PolyClipPlane() : A(0.0f), B(0.0f), C(0.0f), D(1.0f) { } - PolyClipPlane(float a, float b, float c, float d) : A(a), B(b), C(c), D(d) { } - - float A, B, C, D; -}; - -struct TriVertex -{ - TriVertex() { } - TriVertex(float x, float y, float z, float w, float u, float v) : x(x), y(y), z(z), w(w), u(u), v(v) { } - - float x, y, z, w; - float u, v; -}; - -struct PolyLight -{ - uint32_t color; - float x, y, z; - float radius; -}; - class PolyDrawArgs { public: - //void SetClipPlane(int index, const PolyClipPlane &plane) { mClipPlane[index] = plane; } void SetTexture(const uint8_t *texels, int width, int height); - void SetTexture(FSoftwareTexture *texture, FRenderStyle style); - void SetTexture(FSoftwareTexture *texture, uint32_t translationID, FRenderStyle style); void SetTexture2(const uint8_t* texels, int width, int height); - void SetLight(FSWColormap *basecolormap, uint32_t lightlevel, double globVis, bool fixed); - void SetNoColormap() { mLight = 255; mFixedLight = true; mLightRed = 256; mLightGreen = 256; mLightBlue = 256; mLightAlpha = 256; mFadeRed = 0; mFadeGreen = 0; mFadeBlue = 0; mFadeAlpha = 0; mDesaturate = 0; mSimpleShade = true; mColormaps = nullptr; } void SetDepthTest(bool enable) { mDepthTest = enable; } void SetStencilTest(bool enable) { mStencilTest = enable; } void SetStencilTestValue(uint8_t stencilTestValue) { mStencilTestValue = stencilTestValue; } void SetWriteColor(bool enable) { mWriteColor = enable; } void SetWriteStencil(bool enable, uint8_t stencilWriteValue = 0) { mWriteStencil = enable; mStencilWriteValue = stencilWriteValue; } void SetWriteDepth(bool enable) { mWriteDepth = enable; } - void SetStyle(TriBlendMode blendmode, double alpha = 1.0) { mBlendMode = blendmode; mAlpha = (uint32_t)(alpha * 256.0 + 0.5); } - void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FSoftwareTexture *texture, bool fullbright); - void SetColor(uint32_t bgra, uint8_t palindex); - void SetLights(PolyLight *lights, int numLights) { mLights = lights; mNumLights = numLights; } - void SetDynLightColor(uint32_t color) { mDynLightColor = color; } - - //const PolyClipPlane &ClipPlane(int index) const { return mClipPlane[index]; } bool WriteColor() const { return mWriteColor; } - FSoftwareTexture *Texture() const { return mTexture; } const uint8_t *TexturePixels() const { return mTexturePixels; } int TextureWidth() const { return mTextureWidth; } int TextureHeight() const { return mTextureHeight; } - const uint8_t *Translation() const { return mTranslation; } const uint8_t* Texture2Pixels() const { return mTexture2Pixels; } int Texture2Width() const { return mTexture2Width; } @@ -108,71 +56,18 @@ public: bool DepthTest() const { return mDepthTest; } bool WriteDepth() const { return mWriteDepth; } - TriBlendMode BlendMode() const { return mBlendMode; } - uint32_t Color() const { return mColor; } - uint32_t Alpha() const { return mAlpha; } - - float GlobVis() const { return mGlobVis; } - uint32_t Light() const { return mLight; } - const uint8_t *BaseColormap() const { return mColormaps; } - uint16_t ShadeLightAlpha() const { return mLightAlpha; } - uint16_t ShadeLightRed() const { return mLightRed; } - uint16_t ShadeLightGreen() const { return mLightGreen; } - uint16_t ShadeLightBlue() const { return mLightBlue; } - uint16_t ShadeFadeAlpha() const { return mFadeAlpha; } - uint16_t ShadeFadeRed() const { return mFadeRed; } - uint16_t ShadeFadeGreen() const { return mFadeGreen; } - uint16_t ShadeFadeBlue() const { return mFadeBlue; } - uint16_t ShadeDesaturate() const { return mDesaturate; } - - bool SimpleShade() const { return mSimpleShade; } - bool NearestFilter() const { return mNearestFilter; } - bool FixedLight() const { return mFixedLight; } - - PolyLight *Lights() const { return mLights; } - int NumLights() const { return mNumLights; } - uint32_t DynLightColor() const { return mDynLightColor; } - - const FVector3 &Normal() const { return mNormal; } - void SetNormal(const FVector3 &normal) { mNormal = normal; } - private: bool mDepthTest = false; bool mStencilTest = true; bool mWriteStencil = true; bool mWriteColor = true; bool mWriteDepth = true; - FSoftwareTexture *mTexture = nullptr; const uint8_t *mTexturePixels = nullptr; int mTextureWidth = 0; int mTextureHeight = 0; - const uint8_t *mTranslation = nullptr; const uint8_t* mTexture2Pixels = nullptr; int mTexture2Width = 0; int mTexture2Height = 0; uint8_t mStencilTestValue = 0; uint8_t mStencilWriteValue = 0; - const uint8_t *mColormaps = nullptr; - PolyClipPlane mClipPlane[3]; - TriBlendMode mBlendMode = TriBlendMode::Fill; - uint32_t mLight = 0; - uint32_t mColor = 0; - uint32_t mAlpha = 0; - uint16_t mLightAlpha = 0; - uint16_t mLightRed = 0; - uint16_t mLightGreen = 0; - uint16_t mLightBlue = 0; - uint16_t mFadeAlpha = 0; - uint16_t mFadeRed = 0; - uint16_t mFadeGreen = 0; - uint16_t mFadeBlue = 0; - uint16_t mDesaturate = 0; - float mGlobVis = 0.0f; - bool mSimpleShade = true; - bool mNearestFilter = true; - bool mFixedLight = false; - PolyLight *mLights = nullptr; - int mNumLights = 0; - FVector3 mNormal; - uint32_t mDynLightColor = 0; }; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 4f895b82e..8344372aa 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -264,7 +264,7 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu PushConstants = &constants; - int numLights = 0; + /*int numLights = 0; if (constants.uLightIndex >= 0) { const FVector4 &lightRange = lights[constants.uLightIndex]; @@ -298,7 +298,7 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu } } } - drawargs.SetLights(polyLights, numLights); + drawargs.SetLights(polyLights, numLights);*/ } void PolyTriangleThreadData::PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) @@ -691,9 +691,6 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve if (IsDegenerate(vert)) return; - drawargs.SetColor(vert[0]->vColor, 0); - drawargs.SetNormal(FVector3(vert[0]->vWorldNormal.X, vert[0]->vWorldNormal.Y, vert[0]->vWorldNormal.Z)); - // Cull, clip and generate additional vertices as needed ScreenTriVertex clippedvert[max_additional_vertices]; int numclipvert = ClipEdge(vert); diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index b8da0ac22..b97c92277 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -35,6 +35,15 @@ class PolyInputAssembly; class PolyDepthStencil; struct PolyPushConstants; +enum class PolyDrawMode +{ + Points, + Lines, + Triangles, + TriangleFan, + TriangleStrip +}; + class PolyTriangleDrawer { public: @@ -225,8 +234,15 @@ public: const unsigned int *elements = nullptr; const FVector4 *lights = nullptr; + /*struct PolyLight + { + uint32_t color; + float x, y, z; + float radius; + }; + enum { maxPolyLights = 16 }; - PolyLight polyLights[maxPolyLights]; + PolyLight polyLights[maxPolyLights];*/ PolyMainVertexShader mainVertexShader; diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.h b/src/rendering/polyrenderer/drawers/screen_triangle.h index 9deee30cd..d26aadd07 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.h +++ b/src/rendering/polyrenderer/drawers/screen_triangle.h @@ -93,40 +93,6 @@ private: } }; -enum class TriBlendMode -{ - Opaque, - Skycap, - FogBoundary, - SrcColor, - Fill, - FillTranslucent, - Normal, - AlphaTest, - Fuzzy, - Stencil, - Translucent, - Add, - Shaded, - TranslucentStencil, - Shadow, - Subtract, - AddStencil, - AddShaded, - OpaqueTranslated, - SrcColorTranslated, - NormalTranslated, - StencilTranslated, - TranslucentTranslated, - AddTranslated, - ShadedTranslated, - TranslucentStencilTranslated, - ShadowTranslated, - SubtractTranslated, - AddStencilTranslated, - AddShadedTranslated -}; - class ScreenTriangle { public: From 74c6b9fe6dcd3d86cfee26e5cc67e0b23492bc4b Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 2 Dec 2019 00:21:42 +0100 Subject: [PATCH 48/60] Remove PolyDrawArgs --- src/CMakeLists.txt | 1 - .../polyrenderer/drawers/poly_draw_args.cpp | 53 -------------- .../polyrenderer/drawers/poly_draw_args.h | 73 ------------------- .../polyrenderer/drawers/poly_triangle.cpp | 33 +++++---- .../polyrenderer/drawers/poly_triangle.h | 19 ++++- .../polyrenderer/drawers/screen_triangle.cpp | 32 ++++---- src/rendering/polyrenderer/poly_all.cpp | 1 - 7 files changed, 50 insertions(+), 162 deletions(-) delete mode 100644 src/rendering/polyrenderer/drawers/poly_draw_args.cpp delete mode 100644 src/rendering/polyrenderer/drawers/poly_draw_args.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1b2ecff7b..cc60d5619 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -708,7 +708,6 @@ set ( SWRENDER_SOURCES set( POLYRENDER_SOURCES rendering/polyrenderer/drawers/poly_triangle.cpp - rendering/polyrenderer/drawers/poly_draw_args.cpp rendering/polyrenderer/drawers/screen_triangle.cpp rendering/polyrenderer/math/gpu_types.cpp ) diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.cpp b/src/rendering/polyrenderer/drawers/poly_draw_args.cpp deleted file mode 100644 index 1a04a28f6..000000000 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.cpp +++ /dev/null @@ -1,53 +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 "w_wad.h" -#include "v_video.h" -#include "doomstat.h" -#include "st_stuff.h" -#include "g_game.h" -#include "g_level.h" -#include "r_data/r_translate.h" -#include "v_palette.h" -#include "r_data/colormaps.h" -#include "swrenderer/r_swcolormaps.h" -#include "poly_draw_args.h" -#include "swrenderer/viewport/r_viewport.h" -#include "polyrenderer/drawers/poly_triangle.h" - -void PolyDrawArgs::SetTexture(const uint8_t *texels, int width, int height) -{ - mTexturePixels = texels; - mTextureWidth = width; - mTextureHeight = height; -} - -void PolyDrawArgs::SetTexture2(const uint8_t* texels, int width, int height) -{ - mTexture2Pixels = texels; - mTexture2Width = width; - mTexture2Height = height; -} diff --git a/src/rendering/polyrenderer/drawers/poly_draw_args.h b/src/rendering/polyrenderer/drawers/poly_draw_args.h deleted file mode 100644 index 9835e33f5..000000000 --- a/src/rendering/polyrenderer/drawers/poly_draw_args.h +++ /dev/null @@ -1,73 +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_data/r_translate.h" -#include "r_data/colormaps.h" -#include "screen_triangle.h" - -class PolyDrawArgs -{ -public: - void SetTexture(const uint8_t *texels, int width, int height); - void SetTexture2(const uint8_t* texels, int width, int height); - void SetDepthTest(bool enable) { mDepthTest = enable; } - void SetStencilTest(bool enable) { mStencilTest = enable; } - void SetStencilTestValue(uint8_t stencilTestValue) { mStencilTestValue = stencilTestValue; } - void SetWriteColor(bool enable) { mWriteColor = enable; } - void SetWriteStencil(bool enable, uint8_t stencilWriteValue = 0) { mWriteStencil = enable; mStencilWriteValue = stencilWriteValue; } - void SetWriteDepth(bool enable) { mWriteDepth = enable; } - - bool WriteColor() const { return mWriteColor; } - - const uint8_t *TexturePixels() const { return mTexturePixels; } - int TextureWidth() const { return mTextureWidth; } - int TextureHeight() const { return mTextureHeight; } - - const uint8_t* Texture2Pixels() const { return mTexture2Pixels; } - int Texture2Width() const { return mTexture2Width; } - int Texture2Height() const { return mTexture2Height; } - - bool WriteStencil() const { return mWriteStencil; } - bool StencilTest() const { return mStencilTest; } - uint8_t StencilTestValue() const { return mStencilTestValue; } - uint8_t StencilWriteValue() const { return mStencilWriteValue; } - - bool DepthTest() const { return mDepthTest; } - bool WriteDepth() const { return mWriteDepth; } - -private: - bool mDepthTest = false; - bool mStencilTest = true; - bool mWriteStencil = true; - bool mWriteColor = true; - bool mWriteDepth = true; - const uint8_t *mTexturePixels = nullptr; - int mTextureWidth = 0; - int mTextureHeight = 0; - const uint8_t* mTexture2Pixels = nullptr; - int mTexture2Width = 0; - int mTexture2Height = 0; - uint8_t mStencilTestValue = 0; - uint8_t mStencilWriteValue = 0; -}; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 8344372aa..965214aad 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -319,18 +319,18 @@ void PolyTriangleThreadData::SetDepthClamp(bool on) void PolyTriangleThreadData::SetDepthMask(bool on) { - drawargs.SetWriteDepth(on); + WriteDepth = on; } void PolyTriangleThreadData::SetDepthFunc(int func) { if (func == DF_LEqual || func == DF_Less) { - drawargs.SetDepthTest(true); + DepthTest = true; } else if (func == DF_Always) { - drawargs.SetDepthTest(false); + DepthTest = false; } } @@ -352,23 +352,26 @@ void PolyTriangleThreadData::SetDepthBias(float depthBiasConstantFactor, float d void PolyTriangleThreadData::SetColorMask(bool r, bool g, bool b, bool a) { - drawargs.SetWriteColor(r); + WriteColor = r; } void PolyTriangleThreadData::SetStencil(int stencilRef, int op) { - drawargs.SetStencilTestValue(stencilRef); + StencilTestValue = stencilRef; if (op == SOP_Increment) { - drawargs.SetWriteStencil(drawargs.StencilTest(), MIN(stencilRef + 1, (int)255)); + WriteStencil = StencilTest; + StencilWriteValue = MIN(stencilRef + 1, (int)255); } else if (op == SOP_Decrement) { - drawargs.SetWriteStencil(drawargs.StencilTest(), MAX(stencilRef - 1, (int)0)); + WriteStencil = StencilTest; + StencilWriteValue = MAX(stencilRef - 1, (int)0); } else // SOP_Keep { - drawargs.SetWriteStencil(false, stencilRef); + WriteStencil = false; + StencilWriteValue = stencilRef; } } @@ -384,13 +387,13 @@ void PolyTriangleThreadData::EnableClipDistance(int num, bool state) void PolyTriangleThreadData::EnableStencil(bool on) { - drawargs.SetStencilTest(on); - drawargs.SetWriteStencil(on && drawargs.StencilTestValue() != drawargs.StencilWriteValue(), drawargs.StencilWriteValue()); + StencilTest = on; + WriteStencil = on && StencilTestValue != StencilWriteValue; } void PolyTriangleThreadData::EnableDepthTest(bool on) { - drawargs.SetDepthTest(on); + DepthTest = on; } void PolyTriangleThreadData::SetRenderStyle(FRenderStyle style) @@ -407,10 +410,10 @@ void PolyTriangleThreadData::SetShader(int specialEffect, int effectState, bool void PolyTriangleThreadData::SetTexture(int unit, void *pixels, int width, int height) { - if (unit == 0) - drawargs.SetTexture((uint8_t*)pixels, width, height); - else if (unit == 1) - drawargs.SetTexture2((uint8_t*)pixels, width, height); + textures[unit].pixels = (uint8_t*)pixels; + textures[unit].width = width; + textures[unit].height = height; + textures[unit].bgra = true; } void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode drawmode) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index b97c92277..9b30e478a 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -26,7 +26,6 @@ #include "swrenderer/drawers/r_thread.h" #include "polyrenderer/drawers/screen_triangle.h" #include "polyrenderer/math/gpu_types.h" -#include "polyrenderer/drawers/poly_draw_args.h" #include "polyrenderer/drawers/poly_vertex_shader.h" class DCanvas; @@ -228,8 +227,6 @@ public: bool AlphaTest = false; const PolyPushConstants* PushConstants = nullptr; - PolyDrawArgs drawargs; - const void *vertices = nullptr; const unsigned int *elements = nullptr; const FVector4 *lights = nullptr; @@ -246,6 +243,22 @@ public: PolyMainVertexShader mainVertexShader; + struct TextureUnit + { + const uint8_t* pixels = nullptr; + int width = 0; + int height = 0; + bool bgra = true; + } textures[16]; + + bool DepthTest = false; + bool StencilTest = true; + bool WriteStencil = true; + bool WriteColor = true; + bool WriteDepth = true; + uint8_t StencilTestValue = 0; + uint8_t StencilWriteValue = 0; + private: ShadedTriVertex ShadeVertex(int index); void DrawShadedPoint(const ShadedTriVertex *const* vertex); diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 9e3e3a202..91248c7df 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -319,7 +319,7 @@ static void WriteStencil(int y, int x0, int x1, PolyTriangleThreadData* thread) { size_t pitch = thread->depthstencil->Width(); uint8_t* line = thread->depthstencil->StencilValues() + pitch * y; - uint8_t value = thread->drawargs.StencilWriteValue(); + uint8_t value = thread->StencilWriteValue; if (!thread->AlphaTest) { for (int x = x0; x < x1; x++) @@ -375,13 +375,13 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) } else if (thread->SpecialEffect == EFF_BURN) // burn.fp { - int texWidth = thread->drawargs.TextureWidth(); - int texHeight = thread->drawargs.TextureHeight(); - const uint32_t* texPixels = (const uint32_t*)thread->drawargs.TexturePixels(); + int texWidth = thread->textures[0].width; + int texHeight = thread->textures[0].height; + const uint32_t* texPixels = (const uint32_t*)thread->textures[0].pixels; - int tex2Width = thread->drawargs.Texture2Width(); - int tex2Height = thread->drawargs.Texture2Height(); - const uint32_t* tex2Pixels = (const uint32_t*)thread->drawargs.Texture2Pixels(); + int tex2Width = thread->textures[1].width; + int tex2Height = thread->textures[1].height; + const uint32_t* tex2Pixels = (const uint32_t*)thread->textures[1].pixels; uint32_t frag = thread->mainVertexShader.vColor; uint32_t frag_r = RPART(frag); @@ -441,9 +441,9 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) } else // func_normal { - int texWidth = thread->drawargs.TextureWidth(); - int texHeight = thread->drawargs.TextureHeight(); - const uint32_t* texPixels = (const uint32_t*)thread->drawargs.TexturePixels(); + int texWidth = thread->textures[0].width; + int texHeight = thread->textures[0].height; + const uint32_t* texPixels = (const uint32_t*)thread->textures[0].pixels; switch (constants->uTextureMode) { @@ -626,11 +626,11 @@ static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, Pol RunShader(x0, x1, thread); - if (thread->drawargs.WriteColor()) + if (thread->WriteColor) WriteColor(y, x0, x1, thread); - if (thread->drawargs.WriteDepth()) + if (thread->WriteDepth) WriteDepth(y, x0, x1, thread); - if (thread->drawargs.WriteStencil()) + if (thread->WriteStencil) WriteStencil(y, x0, x1, thread); } @@ -652,7 +652,7 @@ static void TestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, Pol { stencilbuffer = thread->depthstencil->StencilValues(); stencilLine = stencilbuffer + pitch * y; - stencilTestValue = thread->drawargs.StencilTestValue(); + stencilTestValue = thread->StencilTestValue; } float* zbuffer; @@ -760,8 +760,8 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs* args, PolyTriangleThreadDat void(*testfunc)(int y, int x0, int x1, const TriDrawTriangleArgs * args, PolyTriangleThreadData * thread); int opt = 0; - if (thread->drawargs.DepthTest()) opt |= TriScreenDrawerModes::SWTRI_DepthTest; - if (thread->drawargs.StencilTest()) opt |= TriScreenDrawerModes::SWTRI_StencilTest; + if (thread->DepthTest) opt |= TriScreenDrawerModes::SWTRI_DepthTest; + if (thread->StencilTest) opt |= TriScreenDrawerModes::SWTRI_StencilTest; testfunc = ScreenTriangle::TestSpanOpts[opt]; topY += thread->skipped_by_thread(topY); diff --git a/src/rendering/polyrenderer/poly_all.cpp b/src/rendering/polyrenderer/poly_all.cpp index 5e0dba3f2..ca3a93e8e 100644 --- a/src/rendering/polyrenderer/poly_all.cpp +++ b/src/rendering/polyrenderer/poly_all.cpp @@ -1,5 +1,4 @@ #include "../swrenderer/textures/r_swtexture.h" -#include "drawers/poly_draw_args.cpp" #include "drawers/poly_triangle.cpp" #include "drawers/screen_triangle.cpp" #include "math/gpu_types.cpp" From 4a2b763aaa05ac7fc6a7a0c9efce5e89b7fe2c0b Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 2 Dec 2019 00:35:15 +0100 Subject: [PATCH 49/60] Support 8-bit textures --- .../polyrenderer/backend/poly_renderstate.cpp | 4 +- .../polyrenderer/drawers/poly_triangle.cpp | 8 ++-- .../polyrenderer/drawers/poly_triangle.h | 11 ++--- .../polyrenderer/drawers/screen_triangle.cpp | 40 ++++++++++++------- 4 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 046a5c467..56ea11a33 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -233,7 +233,7 @@ void PolyRenderState::ApplyMaterial() if (base) { DCanvas *texcanvas = base->GetImage(mMaterial); - PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), 0, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth()); + PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), 0, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth(), texcanvas->IsBgra()); int numLayers = mMaterial.mMaterial->GetLayers(); for (int i = 1; i < numLayers; i++) @@ -242,7 +242,7 @@ void PolyRenderState::ApplyMaterial() auto systex = static_cast(mMaterial.mMaterial->GetLayer(i, 0, &layer)); texcanvas = systex->GetImage(mMaterial); - PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), i, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth()); + PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), i, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth(), texcanvas->IsBgra()); } } diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 965214aad..5cae9821c 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -153,9 +153,9 @@ void PolyTriangleDrawer::SetRenderStyle(const DrawerCommandQueuePtr &queue, FRen queue->Push(style); } -void PolyTriangleDrawer::SetTexture(const DrawerCommandQueuePtr &queue, int unit, void *pixels, int width, int height) +void PolyTriangleDrawer::SetTexture(const DrawerCommandQueuePtr &queue, int unit, void *pixels, int width, int height, bool bgra) { - queue->Push(unit, pixels, width, height); + queue->Push(unit, pixels, width, height, bgra); } void PolyTriangleDrawer::SetShader(const DrawerCommandQueuePtr &queue, int specialEffect, int effectState, bool alphaTest) @@ -408,9 +408,9 @@ void PolyTriangleThreadData::SetShader(int specialEffect, int effectState, bool AlphaTest = alphaTest; } -void PolyTriangleThreadData::SetTexture(int unit, void *pixels, int width, int height) +void PolyTriangleThreadData::SetTexture(int unit, const void *pixels, int width, int height, bool bgra) { - textures[unit].pixels = (uint8_t*)pixels; + textures[unit].pixels = pixels; textures[unit].width = width; textures[unit].height = height; textures[unit].bgra = true; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 9b30e478a..f5a351994 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -65,7 +65,7 @@ public: static void SetScissor(const DrawerCommandQueuePtr &queue, int x, int y, int w, int h); static void EnableDepthTest(const DrawerCommandQueuePtr &queue, bool on); static void SetRenderStyle(const DrawerCommandQueuePtr &queue, FRenderStyle style); - static void SetTexture(const DrawerCommandQueuePtr &queue, int unit, void *pixels, int width, int height); + static void SetTexture(const DrawerCommandQueuePtr &queue, int unit, void *pixels, int width, int height, bool bgra); static void SetShader(const DrawerCommandQueuePtr &queue, int specialEffect, int effectState, bool alphaTest); static void PushStreamData(const DrawerCommandQueuePtr &queue, const StreamData &data, const PolyPushConstants &constants); static void PushMatrices(const DrawerCommandQueuePtr &queue, const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); @@ -149,7 +149,7 @@ public: void SetScissor(int x, int y, int w, int h); void EnableDepthTest(bool on); void SetRenderStyle(FRenderStyle style); - void SetTexture(int unit, void *pixels, int width, int height); + void SetTexture(int unit, const void *pixels, int width, int height, bool bgra); void SetShader(int specialEffect, int effectState, bool alphaTest); void UpdateClip(); @@ -245,7 +245,7 @@ public: struct TextureUnit { - const uint8_t* pixels = nullptr; + const void* pixels = nullptr; int width = 0; int height = 0; bool bgra = true; @@ -429,14 +429,15 @@ private: class PolySetTextureCommand : public PolyDrawerCommand { public: - PolySetTextureCommand(int unit, void *pixels, int width, int height) : unit(unit), pixels(pixels), width(width), height(height) { } - void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetTexture(unit, pixels, width, height); } + PolySetTextureCommand(int unit, void *pixels, int width, int height, bool bgra) : unit(unit), pixels(pixels), width(width), height(height), bgra(bgra) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetTexture(unit, pixels, width, height, bgra); } private: int unit; void *pixels; int width; int height; + bool bgra; }; class PolySetShaderCommand : public PolyDrawerCommand diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 91248c7df..d1a2ae621 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -351,11 +351,20 @@ static float wrap(float value) } #endif -static uint32_t sampleTexture(float u, float v, const uint32_t* texPixels, int texWidth, int texHeight) +static uint32_t sampleTexture(float u, float v, const void* texPixels, int texWidth, int texHeight, bool texBgra) { int texelX = MIN(static_cast(wrap(u) * texWidth), texWidth - 1); int texelY = MIN(static_cast(wrap(v) * texHeight), texHeight - 1); - return texPixels[texelX * texHeight + texelY]; + int texelOffset = texelX * texHeight + texelY; + if (texBgra) + { + return static_cast(texPixels)[texelOffset]; + } + else + { + uint32_t c = static_cast(texPixels)[texelOffset]; + return c | 0xff000000; + } } static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) @@ -377,11 +386,13 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) { int texWidth = thread->textures[0].width; int texHeight = thread->textures[0].height; - const uint32_t* texPixels = (const uint32_t*)thread->textures[0].pixels; + const void* texPixels = thread->textures[0].pixels; + bool texBgra = thread->textures[0].bgra; int tex2Width = thread->textures[1].width; int tex2Height = thread->textures[1].height; - const uint32_t* tex2Pixels = (const uint32_t*)thread->textures[1].pixels; + const void* tex2Pixels = thread->textures[1].pixels; + bool tex2Bgra = thread->textures[1].bgra; uint32_t frag = thread->mainVertexShader.vColor; uint32_t frag_r = RPART(frag); @@ -394,8 +405,8 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) frag_a += frag_a >> 7; // 255 -> 256 for (int x = x0; x < x1; x++) { - uint32_t t1 = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); - uint32_t t2 = sampleTexture(u[x], 1.0f - v[x], tex2Pixels, tex2Width, tex2Height); + uint32_t t1 = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); + uint32_t t2 = sampleTexture(u[x], 1.0f - v[x], tex2Pixels, tex2Width, tex2Height, tex2Bgra); uint32_t r = (frag_r * RPART(t1)) >> 8; uint32_t g = (frag_g * GPART(t1)) >> 8; @@ -443,7 +454,8 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) { int texWidth = thread->textures[0].width; int texHeight = thread->textures[0].height; - const uint32_t* texPixels = (const uint32_t*)thread->textures[0].pixels; + const void* texPixels = thread->textures[0].pixels; + bool texBgra = thread->textures[0].bgra; switch (constants->uTextureMode) { @@ -452,35 +464,35 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) case TM_FOGLAYER: for (int x = x0; x < x1; x++) { - uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); fragcolor[x] = texel; } break; case TM_STENCIL: // TM_STENCIL for (int x = x0; x < x1; x++) { - uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); fragcolor[x] = texel | 0x00ffffff; } break; case TM_OPAQUE: for (int x = x0; x < x1; x++) { - uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); fragcolor[x] = texel | 0xff000000; } break; case TM_INVERSE: for (int x = x0; x < x1; x++) { - uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); fragcolor[x] = MAKEARGB(APART(texel), 0xff - RPART(texel), 0xff - BPART(texel), 0xff - GPART(texel)); } break; case TM_ALPHATEXTURE: for (int x = x0; x < x1; x++) { - uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); uint32_t gray = (RPART(texel) * 77 + GPART(texel) * 143 + BPART(texel) * 37) >> 8; uint32_t alpha = APART(texel); alpha += alpha >> 7; @@ -493,7 +505,7 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) for (int x = x0; x < x1; x++) { if (v[x] >= 0.0 && v[x] <= 1.0) - fragcolor[x] = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + fragcolor[x] = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); else fragcolor[x] = 0; } @@ -501,7 +513,7 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) case TM_INVERTOPAQUE: for (int x = x0; x < x1; x++) { - uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight); + uint32_t texel = sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); fragcolor[x] = MAKEARGB(0xff, 0xff - RPART(texel), 0xff - BPART(texel), 0xff - GPART(texel)); } } From 44c2223c2fde804aee04ece919817d646f418f0e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 2 Dec 2019 01:07:28 +0100 Subject: [PATCH 50/60] Draw 8-bit software renderer with polybackend (well, sort of!) --- src/rendering/polyrenderer/backend/poly_hwtexture.cpp | 1 + src/rendering/polyrenderer/drawers/poly_triangle.cpp | 10 +--------- src/rendering/polyrenderer/drawers/poly_triangle.h | 1 - src/rendering/polyrenderer/drawers/screen_triangle.cpp | 2 +- src/rendering/swrenderer/r_swscene.cpp | 2 +- src/rendering/swrenderer/scene/r_scene.cpp | 9 ++++++--- 6 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp index a16b58287..4f7b255d3 100644 --- a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp +++ b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp @@ -101,6 +101,7 @@ void PolyHardwareTexture::AllocateBuffer(int w, int h, int texelsize) { mCanvas.reset(new DCanvas(0, 0, texelsize == 4)); mCanvas->Resize(w, h, false); + bufferpitch = mCanvas->GetPitch(); } } diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 5cae9821c..a4bef00f6 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -39,13 +39,6 @@ #include "screen_triangle.h" #include "x86.h" -static bool isBgraRenderTarget = false; - -bool PolyTriangleDrawer::IsBgra() -{ - return isBgraRenderTarget; -} - void PolyTriangleDrawer::ClearDepth(const DrawerCommandQueuePtr &queue, float value) { queue->Push(value); @@ -63,7 +56,6 @@ void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, int dest_height = canvas->GetHeight(); int dest_pitch = canvas->GetPitch(); bool dest_bgra = canvas->IsBgra(); - isBgraRenderTarget = dest_bgra; queue->Push(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra, depthstencil); } @@ -413,7 +405,7 @@ void PolyTriangleThreadData::SetTexture(int unit, const void *pixels, int width, textures[unit].pixels = pixels; textures[unit].width = width; textures[unit].height = height; - textures[unit].bgra = true; + textures[unit].bgra = bgra; } void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode drawmode) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index f5a351994..9d7501cc7 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -73,7 +73,6 @@ public: static void ClearStencil(const DrawerCommandQueuePtr &queue, uint8_t value); static void Draw(const DrawerCommandQueuePtr &queue, int index, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); static void DrawIndexed(const DrawerCommandQueuePtr &queue, int index, int count, PolyDrawMode mode = PolyDrawMode::Triangles); - static bool IsBgra(); }; class PolyDepthStencil diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index d1a2ae621..7c19604d9 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -363,7 +363,7 @@ static uint32_t sampleTexture(float u, float v, const void* texPixels, int texWi else { uint32_t c = static_cast(texPixels)[texelOffset]; - return c | 0xff000000; + return (c << 16) | 0xff000000; } } diff --git a/src/rendering/swrenderer/r_swscene.cpp b/src/rendering/swrenderer/r_swscene.cpp index fcabe745c..68318f7f5 100644 --- a/src/rendering/swrenderer/r_swscene.cpp +++ b/src/rendering/swrenderer/r_swscene.cpp @@ -86,7 +86,7 @@ SWSceneDrawer::~SWSceneDrawer() sector_t *SWSceneDrawer::RenderView(player_t *player) { - if (!screen->IsPoly()) + if (!V_IsTrueColor() || !screen->IsPoly()) { // Avoid using the pixel buffer from the last frame FBTextureIndex = (FBTextureIndex + 1) % 2; diff --git a/src/rendering/swrenderer/scene/r_scene.cpp b/src/rendering/swrenderer/scene/r_scene.cpp index 280c9c1d0..a434bf6b6 100644 --- a/src/rendering/swrenderer/scene/r_scene.cpp +++ b/src/rendering/swrenderer/scene/r_scene.cpp @@ -136,9 +136,12 @@ namespace swrenderer RenderActorView(player->mo, true, false); - auto copyqueue = std::make_shared(MainThread()->FrameMemory.get()); - copyqueue->Push(videobuffer, bufferpitch, target->GetPixels(), target->GetWidth(), target->GetHeight(), target->GetPitch(), target->IsBgra() ? 4 : 1); - DrawerThreads::Execute(copyqueue); + if (videobuffer != target->GetPixels()) + { + auto copyqueue = std::make_shared(MainThread()->FrameMemory.get()); + copyqueue->Push(videobuffer, bufferpitch, target->GetPixels(), target->GetWidth(), target->GetHeight(), target->GetPitch(), target->IsBgra() ? 4 : 1); + DrawerThreads::Execute(copyqueue); + } DrawerWaitCycles.Clock(); DrawerThreads::WaitForWorkers(); From 865b7a1a2c6646900d70531fe9c6078c5a256723 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 2 Dec 2019 01:28:35 +0100 Subject: [PATCH 51/60] Implement func_paletted shader --- .../polyrenderer/drawers/screen_triangle.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index 7c19604d9..cf1586fb2 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -425,6 +425,20 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread) }*/ return; } + else if (thread->EffectState == SHADER_Paletted) // func_paletted + { + int texWidth = thread->textures[0].width; + int texHeight = thread->textures[0].height; + const void* texPixels = thread->textures[0].pixels; + bool texBgra = thread->textures[0].bgra; + + const uint32_t* lut = (const uint32_t*)thread->textures[1].pixels; + + for (int x = x0; x < x1; x++) + { + fragcolor[x] = lut[RPART(sampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra))] | 0xff000000; + } + } else if (thread->EffectState == SHADER_NoTexture) // func_notexture { uint32_t a = (int)(streamdata.uObjectColor.a * 255.0f); From f501e1bb49e19b31a53de67fa70543de03558768 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 2 Dec 2019 01:48:59 +0100 Subject: [PATCH 52/60] Fix texture binding bug --- src/rendering/polyrenderer/backend/poly_renderstate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index 56ea11a33..7c879d82c 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -241,7 +241,7 @@ void PolyRenderState::ApplyMaterial() FTexture* layer; auto systex = static_cast(mMaterial.mMaterial->GetLayer(i, 0, &layer)); - texcanvas = systex->GetImage(mMaterial); + texcanvas = systex->GetImage(layer, 0, mMaterial.mMaterial->isExpanded() ? CTF_Expand : 0); PolyTriangleDrawer::SetTexture(GetPolyFrameBuffer()->GetDrawCommands(), i, texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth(), texcanvas->IsBgra()); } } From 3269b61ffc4d8122f306e3d4e99fff7d38fbd0dc Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 2 Dec 2019 09:43:06 -0500 Subject: [PATCH 53/60] - change menu option for 'vid_preferbackend' --- src/rendering/v_video.cpp | 16 +++++++++++++--- wadsrc/static/menudef.txt | 9 ++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/rendering/v_video.cpp b/src/rendering/v_video.cpp index 9beb8e36b..607503bfc 100644 --- a/src/rendering/v_video.cpp +++ b/src/rendering/v_video.cpp @@ -114,9 +114,19 @@ CUSTOM_CVAR(Int, vid_preferbackend, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_N // yet - I'm pretty sure it's going to require a lot of reinits and destructions to // do it right without memory leaks - // 0 - OpenGL - // 1 - Vulkan - // 2 - SoftPoly v2 + switch(self) + { + case 2: + Printf("Selecting SoftPoly backend...\n"); + break; +#ifdef HAVE_VULKAN + case 1: + Printf("Selecting Vulkan backend...\n"); + break; +#endif + default: + Printf("Selecting OpenGL backend...\n"); + } Printf("Changing the video backend requires a restart for " GAMENAME ".\n"); } diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index d4d325e05..c6e5a4b4b 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -885,6 +885,12 @@ OptionValue GPUSwitch 2.0, "$OPTVAL_INTEGRATED" } +OptionValue PreferBackend +{ + 0, "$OPTVAL_OPENGL" + 1, "$OPTVAL_VULKAN" + 2, "$OPTVAL_SOFTPOLY" +} OptionMenu "TrueColorOptions" protected { @@ -918,6 +924,8 @@ OptionMenu "VideoOptions" protected Submenu "$GLMNU_TEXOPT", "GLTextureGLOptions" Submenu "$GLMNU_DYNLIGHT", "GLLightOptions" StaticText " " + Option "$DSPLYMNU_PREFERBACKEND", "vid_preferbackend", "PreferBackend" + StaticText " " Slider "$DSPLYMNU_SCREENSIZE", "screenblocks", 3.0, 12.0, 1.0, 0 Slider "$DSPLYMNU_GAMMA", "Gamma", 0.75, 3.0, 0.05, 2 @@ -2787,7 +2795,6 @@ OptionMenu "vkoptions" StaticText "$VK_WARNING" StaticText "$VK_RESTART" StaticText "" - Option "$VKMNU_ENABLE", "vid_enablevulkan", "OnOff" TextField "$VKMNU_DEVICE", vk_device Option "$VKMNU_HDR", "vk_hdr", "OnOff" } From 43139276d13819fbdf2ade10e2ccdf27ea68cd2a Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 2 Dec 2019 18:44:15 +0100 Subject: [PATCH 54/60] SSE2 version of wrap --- src/rendering/polyrenderer/drawers/screen_triangle.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/rendering/polyrenderer/drawers/screen_triangle.cpp index cf1586fb2..32226a108 100644 --- a/src/rendering/polyrenderer/drawers/screen_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/screen_triangle.cpp @@ -346,8 +346,10 @@ static float wrap(float value) #else static float wrap(float value) { - __m128 mvalue = _mm_set_ss(value); - return _mm_cvtss_f32(_mm_sub_ss(mvalue, _mm_floor_ss(_mm_setzero_ps(), mvalue))); + __m128 f = _mm_set_ss(value); + __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(f)); + __m128 r = _mm_sub_ps(t, _mm_and_ps(_mm_cmplt_ps(f, t), _mm_set_ss(1.0f))); + return _mm_cvtss_f32(_mm_sub_ss(f, r)); } #endif From a9e6592febd16aa89e124e0c7593be34b1f788d6 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 2 Dec 2019 20:05:13 +0100 Subject: [PATCH 55/60] Switch to the D3DSWAPEFFECT_FLIPEX swap model --- .../polyrenderer/backend/poly_framebuffer.cpp | 8 +++--- .../polyrenderer/backend/poly_framebuffer.h | 2 ++ src/win32/win32polyvideo.cpp | 27 +++++++++---------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index 023298806..8edca2e0e 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -49,12 +49,12 @@ extern FString gpuStatOutput; #ifdef WIN32 void I_PolyPresentInit(); -uint8_t *I_PolyPresentLock(int w, int h, int &pitch); +uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch); void I_PolyPresentUnlock(int x, int y, int w, int h); void I_PolyPresentDeinit(); #else void I_PolyPresentInit() { } -uint8_t *I_PolyPresentLock(int w, int h, int &pitch) { pitch = 0; return nullptr; } +uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch) { pitch = 0; return nullptr; } void I_PolyPresentUnlock(int x, int y, int w, int h) { } void I_PolyPresentDeinit() { } #endif @@ -157,7 +157,7 @@ void PolyFrameBuffer::Update() int pixelsize = 4; const uint8_t *src = (const uint8_t*)mCanvas->GetPixels(); int pitch = 0; - uint8_t *dst = I_PolyPresentLock(w, h, pitch); + uint8_t *dst = I_PolyPresentLock(w, h, cur_vsync, pitch); if (dst) { #if 1 @@ -444,7 +444,7 @@ uint32_t PolyFrameBuffer::GetCaps() void PolyFrameBuffer::SetVSync(bool vsync) { - // This is handled in PolySwapChain::AcquireImage. + cur_vsync = vsync; } void PolyFrameBuffer::CleanForRestart() diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.h b/src/rendering/polyrenderer/backend/poly_framebuffer.h index 08494a117..ba35b5a16 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.h +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.h @@ -83,6 +83,8 @@ private: std::unique_ptr mDepthStencil; std::shared_ptr mDrawCommands; RenderMemory mFrameMemory; + + bool cur_vsync = false; }; inline PolyFrameBuffer *GetPolyFrameBuffer() { return static_cast(screen); } diff --git a/src/win32/win32polyvideo.cpp b/src/win32/win32polyvideo.cpp index a6e74218a..2c2111979 100644 --- a/src/win32/win32polyvideo.cpp +++ b/src/win32/win32polyvideo.cpp @@ -19,14 +19,14 @@ namespace int ClientHeight = 0; bool CurrentVSync = false; - IDirect3D9 *d3d9 = nullptr; - IDirect3DDevice9 *device = nullptr; - IDirect3DSurface9 *surface = nullptr; + IDirect3D9Ex *d3d9 = nullptr; + IDirect3DDevice9Ex *device = nullptr; + IDirect3DSurface9* surface = nullptr; } void I_PolyPresentInit() { - d3d9 = Direct3DCreate9(D3D_SDK_VERSION); + Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9); if (!d3d9) { I_FatalError("Direct3DCreate9 failed"); @@ -35,33 +35,32 @@ void I_PolyPresentInit() RECT rect = {}; GetClientRect(Window, &rect); - CurrentVSync = vid_vsync; ClientWidth = rect.right; ClientHeight = rect.bottom; D3DPRESENT_PARAMETERS pp = {}; pp.Windowed = true; - pp.SwapEffect = D3DSWAPEFFECT_DISCARD; + pp.SwapEffect = D3DSWAPEFFECT_FLIPEX; pp.BackBufferWidth = ClientWidth; pp.BackBufferHeight = ClientHeight; pp.BackBufferCount = 1; pp.hDeviceWindow = Window; - pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE; - HRESULT result = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, &device); + HRESULT result = d3d9->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, nullptr, &device); if (FAILED(result)) { I_FatalError("IDirect3D9.CreateDevice failed"); } } -uint8_t *I_PolyPresentLock(int w, int h, int &pitch) +uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch) { HRESULT result; RECT rect = {}; GetClientRect(Window, &rect); - if (rect.right != ClientWidth || rect.bottom != ClientHeight || CurrentVSync != vid_vsync) + if (rect.right != ClientWidth || rect.bottom != ClientHeight || CurrentVSync != vsync) { if (surface) { @@ -69,18 +68,18 @@ uint8_t *I_PolyPresentLock(int w, int h, int &pitch) surface = nullptr; } - CurrentVSync = vid_vsync; + CurrentVSync = vsync; ClientWidth = rect.right; ClientHeight = rect.bottom; D3DPRESENT_PARAMETERS pp = {}; pp.Windowed = true; - pp.SwapEffect = D3DSWAPEFFECT_DISCARD; + pp.SwapEffect = D3DSWAPEFFECT_FLIPEX; pp.BackBufferWidth = ClientWidth; pp.BackBufferHeight = ClientHeight; pp.BackBufferCount = 1; pp.hDeviceWindow = Window; - pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE; device->Reset(&pp); } @@ -173,7 +172,7 @@ void I_PolyPresentUnlock(int x, int y, int width, int height) result = device->EndScene(); if (SUCCEEDED(result)) - device->Present(nullptr, nullptr, 0, nullptr); + device->PresentEx(nullptr, nullptr, 0, nullptr, CurrentVSync ? 0 : D3DPRESENT_FORCEIMMEDIATE); } backbuffer->Release(); From 0f6aec5e99c71c46be35122cda88288d28b83afa Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 2 Dec 2019 20:12:27 +0100 Subject: [PATCH 56/60] Some vid_preferbackend compile fixes --- src/posix/cocoa/i_video.mm | 4 ++-- src/posix/sdl/sdlglvideo.cpp | 4 ++-- src/win32/i_system.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index deb65ae69..97da4360a 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -94,7 +94,7 @@ EXTERN_CVAR(Bool, vid_hidpi) EXTERN_CVAR(Int, vid_defwidth) EXTERN_CVAR(Int, vid_defheight) -EXTERN_CVAR(Int, vid_enablevulkan) +EXTERN_CVAR(Int, vid_preferbackend) EXTERN_CVAR(Bool, vk_debug) CVAR(Bool, mvk_debug, false, 0) @@ -348,7 +348,7 @@ class CocoaVideo : public IVideo public: CocoaVideo() { - ms_isVulkanEnabled = vid_enablevulkan == 1 && NSAppKitVersionNumber >= 1404; // NSAppKitVersionNumber10_11 + ms_isVulkanEnabled = vid_preferbackend == 1 && NSAppKitVersionNumber >= 1404; // NSAppKitVersionNumber10_11 } ~CocoaVideo() diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index 39eae8b76..49463e0ac 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -73,7 +73,7 @@ EXTERN_CVAR (Int, vid_adapter) EXTERN_CVAR (Int, vid_displaybits) EXTERN_CVAR (Int, vid_defwidth) EXTERN_CVAR (Int, vid_defheight) -EXTERN_CVAR (Int, vid_enablevulkan) +EXTERN_CVAR (Int, vid_preferbackend) EXTERN_CVAR (Bool, cl_capfps) // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -246,7 +246,7 @@ SDLVideo::SDLVideo () } #ifdef HAVE_VULKAN - Priv::vulkanEnabled = vid_enablevulkan == 1 + Priv::vulkanEnabled = vid_preferbackend == 1 && Priv::Vulkan_GetDrawableSize && Priv::Vulkan_GetInstanceExtensions && Priv::Vulkan_CreateSurface; if (Priv::vulkanEnabled) diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index 36e042b1f..6e435e26f 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -119,8 +119,7 @@ EXTERN_CVAR (Bool, queryiwad); EXTERN_CVAR (Bool, disableautoload) EXTERN_CVAR (Bool, autoloadlights) EXTERN_CVAR (Bool, autoloadbrightmaps) -//EXTERN_CVAR (Int, vid_enablevulkan) // hack - we're just disabling it for now, this code does nothing -uint32_t vid_enablevulkan = 0; +EXTERN_CVAR (Int, vid_preferbackend) extern HWND Window, ConWindow, GameTitleWindow; extern HANDLE StdOut; @@ -590,7 +589,7 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa // Check the current video settings. //SendDlgItemMessage( hDlg, vid_renderer ? IDC_WELCOME_OPENGL : IDC_WELCOME_SOFTWARE, BM_SETCHECK, BST_CHECKED, 0 ); SendDlgItemMessage( hDlg, IDC_WELCOME_FULLSCREEN, BM_SETCHECK, fullscreen ? BST_CHECKED : BST_UNCHECKED, 0 ); - SendDlgItemMessage( hDlg, IDC_WELCOME_VULKAN, BM_SETCHECK, vid_enablevulkan ? BST_CHECKED : BST_UNCHECKED, 0 ); + SendDlgItemMessage( hDlg, IDC_WELCOME_VULKAN, BM_SETCHECK, (vid_preferbackend == 1) ? BST_CHECKED : BST_UNCHECKED, 0 ); // [SP] This is our's SendDlgItemMessage( hDlg, IDC_WELCOME_NOAUTOLOAD, BM_SETCHECK, disableautoload ? BST_CHECKED : BST_UNCHECKED, 0 ); @@ -636,7 +635,8 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa SetQueryIWad(hDlg); // [SP] Upstreamed from Zandronum fullscreen = SendDlgItemMessage( hDlg, IDC_WELCOME_FULLSCREEN, BM_GETCHECK, 0, 0 ) == BST_CHECKED; - vid_enablevulkan = SendDlgItemMessage( hDlg, IDC_WELCOME_VULKAN, BM_GETCHECK, 0, 0 ) == BST_CHECKED; + if (SendDlgItemMessage(hDlg, IDC_WELCOME_VULKAN, BM_GETCHECK, 0, 0) == BST_CHECKED) vid_preferbackend = 1; + else if (SendDlgItemMessage(hDlg, IDC_WELCOME_VULKAN, BM_GETCHECK, 0, 0) != BST_CHECKED && vid_preferbackend == 1) vid_preferbackend = 0; // [SP] This is our's. disableautoload = SendDlgItemMessage( hDlg, IDC_WELCOME_NOAUTOLOAD, BM_GETCHECK, 0, 0 ) == BST_CHECKED; From e4bd2483e5ca646f635c7375291400487f41bb1d Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 5 Dec 2019 21:26:01 +0100 Subject: [PATCH 57/60] Implement SDL present functions --- src/posix/cocoa/i_video.mm | 17 +++ src/posix/sdl/sdlglvideo.cpp | 118 ++++++++++++++++++ src/rendering/i_video.h | 5 + .../polyrenderer/backend/poly_framebuffer.cpp | 14 +-- 4 files changed, 142 insertions(+), 12 deletions(-) diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index 97da4360a..399e7eda8 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -955,3 +955,20 @@ bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface) return result == VK_SUCCESS; } #endif + +void I_PolyPresentInit() +{ +} + +uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch) +{ + return nullptr; +} + +void I_PolyPresentUnlock(int x, int y, int w, int h) +{ +} + +void I_PolyPresentDeinit() +{ +} diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index 49463e0ac..ed04451fe 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -57,6 +57,8 @@ #include "rendering/vulkan/system/vk_framebuffer.h" #endif +#include "rendering/polyrenderer/backend/poly_framebuffer.h" + // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- @@ -113,6 +115,7 @@ namespace Priv SDL_Window *window; bool vulkanEnabled; + bool softpolyEnabled; bool fullscreenSwitch; void CreateWindow(uint32_t extraFlags) @@ -230,6 +233,101 @@ bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface) } #endif +namespace +{ + SDL_Surface* polysurface = nullptr; +} + +void I_PolyPresentInit() +{ + assert(Priv::softpolyEnabled); + assert(Priv::window != nullptr); +} + +uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch) +{ + if (!polysurface || polysurface->w != w || polysurface->h != h) + { + if (polysurface) + { + SDL_FreeSurface(polysurface); + polysurface = nullptr; + } + polysurface = SDL_CreateRGBSurface(0, w, h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); + SDL_SetSurfaceBlendMode(polysurface, SDL_BLENDMODE_NONE); + } + + SDL_LockSurface(polysurface); + pitch = polysurface->pitch; + return (uint8_t*)polysurface->pixels; +} + +void I_PolyPresentUnlock(int x, int y, int width, int height) +{ + SDL_UnlockSurface(polysurface); + + SDL_Surface* windowsurface = SDL_GetWindowSurface(Priv::window); + int ClientWidth = windowsurface->w; + int ClientHeight = windowsurface->h; + + SDL_Rect clearrects[4]; + int count = 0; + if (y > 0) + { + clearrects[count].x = 0; + clearrects[count].y = 0; + clearrects[count].w = ClientWidth; + clearrects[count].h = y; + count++; + } + if (y + height < ClientHeight) + { + clearrects[count].x = 0; + clearrects[count].y = y + height; + clearrects[count].w = ClientWidth; + clearrects[count].h = ClientHeight - clearrects[count].y; + count++; + } + if (x > 0) + { + clearrects[count].x = 0; + clearrects[count].y = y; + clearrects[count].w = x; + clearrects[count].h = height; + count++; + } + if (x + width < ClientWidth) + { + clearrects[count].x = x + width; + clearrects[count].y = y; + clearrects[count].x = ClientWidth - clearrects[count].x; + clearrects[count].y = height - clearrects[count].y; + count++; + } + + if (count > 0) + SDL_FillRects(windowsurface, clearrects, count, 0xff000000); + + SDL_Rect dstrect; + dstrect.x = x; + dstrect.y = y; + dstrect.w = width; + dstrect.h = height; + SDL_BlitScaled(polysurface, nullptr, windowsurface, &dstrect); + + SDL_UpdateWindowSurface(Priv::window); +} + +void I_PolyPresentDeinit() +{ + if (polysurface) + { + SDL_FreeSurface(polysurface); + polysurface = nullptr; + } +} + + SDLVideo::SDLVideo () { @@ -248,6 +346,7 @@ SDLVideo::SDLVideo () #ifdef HAVE_VULKAN Priv::vulkanEnabled = vid_preferbackend == 1 && Priv::Vulkan_GetDrawableSize && Priv::Vulkan_GetInstanceExtensions && Priv::Vulkan_CreateSurface; + Priv::softpolyEnabled = vid_preferbackend == 2; if (Priv::vulkanEnabled) { @@ -258,6 +357,10 @@ SDLVideo::SDLVideo () Priv::vulkanEnabled = false; } } + else if (Priv::softpolyEnabled) + { + Priv::CreateWindow(SDL_WINDOW_HIDDEN); + } #endif } @@ -294,6 +397,11 @@ DFrameBuffer *SDLVideo::CreateFrameBuffer () } #endif + if (Priv::softpolyEnabled) + { + fb = new PolyFrameBuffer(nullptr, fullscreen); + } + if (fb == nullptr) { fb = new OpenGLRenderer::OpenGLFrameBuffer(0, fullscreen); @@ -325,6 +433,11 @@ int SystemBaseFrameBuffer::GetClientWidth() { int width = 0; + if (Priv::softpolyEnabled) + { + return SDL_GetWindowSurface(Priv::window)->w; + } + #ifdef HAVE_VULKAN assert(Priv::vulkanEnabled); Priv::Vulkan_GetDrawableSize(Priv::window, &width, nullptr); @@ -336,6 +449,11 @@ int SystemBaseFrameBuffer::GetClientWidth() int SystemBaseFrameBuffer::GetClientHeight() { int height = 0; + + if (Priv::softpolyEnabled) + { + return SDL_GetWindowSurface(Priv::window)->h; + } #ifdef HAVE_VULKAN assert(Priv::vulkanEnabled); diff --git a/src/rendering/i_video.h b/src/rendering/i_video.h index d67891201..f2c1abeda 100644 --- a/src/rendering/i_video.h +++ b/src/rendering/i_video.h @@ -22,6 +22,11 @@ void I_ShutdownGraphics(); extern IVideo *Video; +void I_PolyPresentInit(); +uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch); +void I_PolyPresentUnlock(int x, int y, int w, int h); +void I_PolyPresentDeinit(); + // Pause a bit. // [RH] Despite the name, it apparently never waited for the VBL, even in diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index 8edca2e0e..1915b3177 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -8,6 +8,8 @@ #include "g_game.h" #include "gamedata/fonts/v_text.h" +#include "rendering/i_video.h" + #include "hwrenderer/utility/hw_clock.h" #include "hwrenderer/utility/hw_vrmodes.h" #include "hwrenderer/utility/hw_cvars.h" @@ -47,18 +49,6 @@ extern bool gpuStatActive; extern bool keepGpuStatActive; extern FString gpuStatOutput; -#ifdef WIN32 -void I_PolyPresentInit(); -uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch); -void I_PolyPresentUnlock(int x, int y, int w, int h); -void I_PolyPresentDeinit(); -#else -void I_PolyPresentInit() { } -uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch) { pitch = 0; return nullptr; } -void I_PolyPresentUnlock(int x, int y, int w, int h) { } -void I_PolyPresentDeinit() { } -#endif - PolyFrameBuffer::PolyFrameBuffer(void *hMonitor, bool fullscreen) : Super(hMonitor, fullscreen) { I_PolyPresentInit(); From ab4f3ee0b16cd6899c1e79e3f98c8e818be426d1 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 5 Dec 2019 22:04:28 +0100 Subject: [PATCH 58/60] Fix black border clears --- src/posix/sdl/sdlglvideo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index ed04451fe..efd870817 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -300,13 +300,13 @@ void I_PolyPresentUnlock(int x, int y, int width, int height) { clearrects[count].x = x + width; clearrects[count].y = y; - clearrects[count].x = ClientWidth - clearrects[count].x; - clearrects[count].y = height - clearrects[count].y; + clearrects[count].w = ClientWidth - clearrects[count].x; + clearrects[count].h = height; count++; } if (count > 0) - SDL_FillRects(windowsurface, clearrects, count, 0xff000000); + SDL_FillRects(windowsurface, clearrects, count, SDL_MapRGBA(windowsurface->format, 0, 0, 0, 255)); SDL_Rect dstrect; dstrect.x = x; From 9b7db26a3797807098cfae494dedf676a2d1bd7d Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 5 Dec 2019 21:18:11 +0100 Subject: [PATCH 59/60] Fix the compile error on Windows --- src/rendering/i_video.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rendering/i_video.h b/src/rendering/i_video.h index f2c1abeda..d9a9b9701 100644 --- a/src/rendering/i_video.h +++ b/src/rendering/i_video.h @@ -1,6 +1,7 @@ #ifndef __I_VIDEO_H__ #define __I_VIDEO_H__ +#include class DFrameBuffer; From c646478aa0218196961e2664bec24c2767b00fa0 Mon Sep 17 00:00:00 2001 From: Madame Rachelle Date: Thu, 5 Dec 2019 18:27:46 -0500 Subject: [PATCH 60/60] - allow SDL to use OpenGL acceleration for polybackend --- src/posix/sdl/sdlglvideo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index efd870817..8efb73acb 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -359,7 +359,7 @@ SDLVideo::SDLVideo () } else if (Priv::softpolyEnabled) { - Priv::CreateWindow(SDL_WINDOW_HIDDEN); + Priv::CreateWindow(SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL); } #endif }