diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index a0cdaee9c6..e00bdfe304 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -90,10 +90,8 @@ struct LevelMeshSurface // inline uint32_t Area() const { return texWidth * texHeight; } - // Touching light sources - std::vector LightList; - int LightListPos = -1; + int LightListCount = 0; int LightListResetCounter = -1; }; @@ -209,7 +207,7 @@ public: virtual unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const { return 0xffffffff; } virtual int GetSurfaceCount() { return 0; } - virtual void UpdateLightLists() { } + virtual int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) { return 0; } TArray SmoothingGroups; TArray Portals; diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp index abe7a6d96c..ba38a3530d 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp @@ -30,6 +30,8 @@ VkLightmap::VkLightmap(VulkanRenderDevice* fb) : fb(fb) { useRayQuery = fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery; + templightlist.Resize(128); + CreateUniformBuffer(); CreateLightBuffer(); CreateTileBuffer(); @@ -158,11 +160,11 @@ void VkLightmap::Render() auto& selectedSurface = selectedSurfaces[i]; LevelMeshSurface* targetSurface = selectedSurface.Surface; - if (targetSurface->LightList.empty() && (targetSurface->plane.XYZ() | mesh->SunDirection) < 0.0f) // No lights, no sun + /*if (targetSurface->LightList.empty() && (targetSurface->plane.XYZ() | mesh->SunDirection) < 0.0f) // No lights, no sun { selectedSurface.Rendered = true; continue; - } + }*/ LightmapRaytracePC pc; pc.TileX = (float)selectedSurface.X; @@ -193,10 +195,10 @@ void VkLightmap::Render() // Paint all surfaces visible in the tile for (LevelMeshSurface* surface : targetSurface->tileSurfaces) { - int lightCount = (int)surface->LightList.size(); - if (surface->LightListResetCounter != lights.ResetCounter) { + int lightCount = mesh->AddSurfaceLights(surface, templightlist.Data(), (int)templightlist.Size()); + if (lights.Pos + lightCount > lights.BufferSize) { // Our light buffer is full. Postpone the rest. @@ -205,11 +207,13 @@ void VkLightmap::Render() } surface->LightListPos = lights.Pos; + surface->LightListCount = lightCount; surface->LightListResetCounter = lights.ResetCounter; LightInfo* lightinfo = &lights.Lights[lights.Pos]; - for (const LevelMeshLight* light : surface->LightList) + for (int i = 0; i < lightCount; i++) { + const LevelMeshLight* light = &templightlist[i]; lightinfo->Origin = light->Origin; lightinfo->RelativeOrigin = light->RelativeOrigin; lightinfo->Radius = light->Radius; @@ -225,7 +229,7 @@ void VkLightmap::Render() } pc.LightStart = surface->LightListPos; - pc.LightEnd = pc.LightStart + lightCount; + pc.LightEnd = pc.LightStart + surface->LightListCount; cmdbuffer->pushConstants(raytrace.pipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(LightmapRaytracePC), &pc); cmdbuffer->drawIndexed(surface->numElements, 1, surface->startElementIndex, 0, 0); } diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.h b/src/common/rendering/vulkan/accelstructs/vk_lightmap.h index 056ccd450f..7acaaaa471 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.h +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.h @@ -159,6 +159,7 @@ private: TArray selectedSurfaces; TArray> copylists; + TArray templightlist; struct { diff --git a/src/common/rendering/vulkan/vk_renderdevice.cpp b/src/common/rendering/vulkan/vk_renderdevice.cpp index 5413ccd330..1e4e9cc5a4 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.cpp +++ b/src/common/rendering/vulkan/vk_renderdevice.cpp @@ -483,7 +483,6 @@ void VulkanRenderDevice::BeginFrame() if (levelMesh && levelMesh->GetSurfaceCount() > 0) { - levelMesh->UpdateLightLists(); GetTextureManager()->CreateLightmap(levelMesh->LMTextureSize, levelMesh->LMTextureCount, std::move(levelMesh->LMTextureData)); GetLightmap()->SetLevelMesh(levelMesh); } diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index f7e90e137c..4bcbdb3706 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -363,6 +363,72 @@ void DoomLevelMesh::CreatePortals() } } +int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) +{ + const DoomLevelMeshSurface* doomsurf = static_cast(surface); + + FLightNode* node = nullptr; + if (doomsurf->Type == ST_FLOOR || doomsurf->Type == ST_CEILING) + { + node = doomsurf->Subsector->section->lighthead; + } + else if (doomsurf->Type == ST_MIDDLESIDE || doomsurf->Type == ST_UPPERSIDE || doomsurf->Type == ST_LOWERSIDE) + { + node = doomsurf->Side->lighthead; + } + if (!node) + return 0; + + int listpos = 0; + while (node && listpos < listMaxSize) + { + FDynamicLight* light = node->lightsource; + if (light && light->Trace()) + { + DVector3 pos = light->Pos; //light->PosRelative(portalgroup); + + LevelMeshLight& meshlight = list[listpos++]; + meshlight.Origin = { (float)pos.X, (float)pos.Y, (float)pos.Z }; + meshlight.RelativeOrigin = meshlight.Origin; + meshlight.Radius = (float)light->GetRadius(); + meshlight.Intensity = (float)light->target->Alpha; + if (light->IsSpot()) + { + meshlight.InnerAngleCos = (float)light->pSpotInnerAngle->Cos(); + meshlight.OuterAngleCos = (float)light->pSpotOuterAngle->Cos(); + + DAngle negPitch = -*light->pPitch; + DAngle Angle = light->target->Angles.Yaw; + double xzLen = negPitch.Cos(); + meshlight.SpotDir.X = float(-Angle.Cos() * xzLen); + meshlight.SpotDir.Y = float(-Angle.Sin() * xzLen); + meshlight.SpotDir.Z = float(-negPitch.Sin()); + } + else + { + meshlight.InnerAngleCos = -1.0f; + meshlight.OuterAngleCos = -1.0f; + meshlight.SpotDir.X = 0.0f; + meshlight.SpotDir.Y = 0.0f; + meshlight.SpotDir.Z = 0.0f; + } + meshlight.Color.X = light->GetRed() * (1.0f / 255.0f); + meshlight.Color.Y = light->GetGreen() * (1.0f / 255.0f); + meshlight.Color.Z = light->GetBlue() * (1.0f / 255.0f); + + if (light->Sector) + meshlight.SectorGroup = sectorGroup[light->Sector->Index()]; + else + meshlight.SectorGroup = 0; + } + + node = node->nextLight; + } + + return listpos; +} + +#if 0 void DoomLevelMesh::PropagateLight(const LevelMeshLight* light, std::set& touchedPortals, int lightPropagationRecursiveDepth) { if (++lightPropagationRecursiveDepth > 32) // TODO is this too much? @@ -495,11 +561,7 @@ void DoomLevelMesh::CreateLightList() PropagateLight(Lights[i].get(), touchedPortals, 0); } } - -void DoomLevelMesh::UpdateLightLists() -{ - CreateLightList(); // full recreation -} +#endif void DoomLevelMesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap) { diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h index 41387f999e..2269850431 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.h +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -39,13 +39,12 @@ public: return surface && surface->bSky; } - void UpdateLightLists() override; + int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) override; LevelMeshSurface* GetSurface(int index) override { return &Surfaces[index]; } unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const override { return (unsigned int)(ptrdiff_t)(static_cast(surface) - Surfaces.Data()); } int GetSurfaceCount() override { return Surfaces.Size(); } - TArray Surfaces; std::vector> Lights; TArray LightmapUvs; @@ -72,9 +71,6 @@ private: void SetSideLightmap(DoomLevelMeshSurface* surface); void SetupLightmapUvs(FLevelLocals& doomMap); - void PropagateLight(const LevelMeshLight* light, std::set& touchedPortals, int lightPropagationRecursiveDepth); - void CreateLightList(); - static bool IsTopSideSky(sector_t* frontsector, sector_t* backsector, side_t* side); static bool IsTopSideVisible(side_t* side); diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 9835448d5e..bf7914336d 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -429,12 +429,6 @@ void HWDrawInfo::UpdateLightmaps() } } } - - if (lm_always_update) // To do: this is stupid, but it lets us see the move for now! - { - //level.levelMesh->UpdateLightLists(); - } - screen->UpdateLightmaps(VisibleSurfaces); }