diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 7f0ac962d..969dc1089 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -1051,36 +1051,52 @@ void DoomLevelMesh::CreateSide(FLevelLocals& doomMap, unsigned int sideIndex) sideBlock.Decals = result.decals; + state.SetDepthMask(true); + state.EnableFog(true); + state.SetRenderStyle(STYLE_Source); + // Part 1: solid geometry. This is set up so that there are no transparent parts state.SetDepthFunc(DF_LEqual); state.ClearDepthBias(); state.EnableTexture(true); state.EnableBrightmap(true); state.AlphaFunc(Alpha_GEqual, 0.f); - CreateWallSurface(side, disp, state, result.list, back ? LevelMeshDrawType::Masked : LevelMeshDrawType::Opaque, true, sideIndex, sideBlock.Lights); + CreateWallSurface(side, disp, state, result.opaque, LevelMeshDrawType::Opaque, sideIndex, sideBlock.Lights); - if (result.portals.Size() != 0 && !sideBlock.InSidePortalsList) - { - // Register side having portals - SidePortals.Push(sideIndex); - sideBlock.InSidePortalsList = true; - } + // Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show + state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); + CreateWallSurface(side, disp, state, result.masked, LevelMeshDrawType::Masked, sideIndex, sideBlock.Lights); + + // Part 3: masked geometry with polygon offset. + state.SetDepthBias(-1, -128); + CreateWallSurface(side, disp, state, result.maskedOffset, LevelMeshDrawType::MaskedOffset, sideIndex, sideBlock.Lights); + state.ClearDepthBias(); + + // Part 4: Draw decals (not a real pass) + state.SetDepthFunc(DF_LEqual); + // DrawDecals(state, Decals[0]); + + /* + // final pass: translucent stuff + state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); + state.SetRenderStyle(STYLE_Translucent); + state.EnableBrightmap(true); + CreateWallSurface(side, disp, state, result.translucent, LevelMeshDrawType::TranslucentBorder, sideIndex); + state.SetDepthMask(false); + CreateWallSurface(side, disp, state, result.translucent, LevelMeshDrawType::Translucent, sideIndex); + state.EnableBrightmap(false); + state.AlphaFunc(Alpha_GEqual, 0.f); + state.SetDepthMask(true); + state.SetRenderStyle(STYLE_Normal); + */ for (HWWall& portal : result.portals) { sideBlock.WallPortals.Push(portal); } - CreateWallSurface(side, disp, state, result.portals, LevelMeshDrawType::Portal, false, sideIndex, sideBlock.Lights); - - /* - // final pass: translucent stuff - state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); - state.SetRenderStyle(STYLE_Translucent); - CreateWallSurface(side, disp, state, result.translucent, LevelMeshDrawType::Translucent, true, sideIndex); - state.AlphaFunc(Alpha_GEqual, 0.f); - state.SetRenderStyle(STYLE_Normal); - */ + // Add portal surface to the level mesh so raytraces can see them + CreateWallSurface(side, disp, state, result.portals, LevelMeshDrawType::Portal, sideIndex, sideBlock.Lights); } void DoomLevelMesh::CreateFlat(FLevelLocals& doomMap, unsigned int sectorIndex) @@ -1215,7 +1231,7 @@ void DoomLevelMesh::SetFlatLights(FLevelLocals& doomMap, unsigned int sectorInde } } -void DoomLevelMesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray& list, LevelMeshDrawType drawType, bool translucent, unsigned int sideIndex, const LightListAllocInfo& lightlist) +void DoomLevelMesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray& list, LevelMeshDrawType drawType, unsigned int sideIndex, const LightListAllocInfo& lightlist) { for (HWWall& wallpart : list) { @@ -1250,7 +1266,7 @@ void DoomLevelMesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, Mesh state.AlphaFunc(Alpha_GEqual, 0.f); } - wallpart.DrawWall(&disp, state, translucent); + wallpart.DrawWall(&disp, state, drawType == LevelMeshDrawType::Translucent || drawType == LevelMeshDrawType::TranslucentBorder); } int numVertices = 0; diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h index 7a10b7f7a..c18cc50fd 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.h +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -74,7 +74,6 @@ struct SideSurfaceBlock TArray Uniforms; TArray WallPortals; TArray Decals; - bool InSidePortalsList = false; bool InSideDecalsList = false; TArray DrawRanges; SurfaceUpdateType UpdateType = SurfaceUpdateType::None; @@ -95,8 +94,10 @@ enum class LevelMeshDrawType { Opaque, Masked, + MaskedOffset, Portal, Translucent, + TranslucentBorder, NumDrawTypes }; @@ -147,7 +148,6 @@ public: TArray& GetSidePortals(int sideIndex); TArray SideDecals; - TArray SidePortals; TArray sectorGroup; // index is sector, value is sectorGroup TArray sectorPortals[2]; // index is sector+plane, value is index into the portal list @@ -217,7 +217,7 @@ private: void SetSubsectorLightmap(int surfaceIndex); void SetSideLightmap(int surfaceIndex); - void CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray& list, LevelMeshDrawType drawType, bool translucent, unsigned int sectorIndex, const LightListAllocInfo& lightlist); + void CreateWallSurface(side_t* side, HWWallDispatcher& disp, MeshBuilder& state, TArray& list, LevelMeshDrawType drawType, unsigned int sectorIndex, const LightListAllocInfo& lightlist); void CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& state, TArray& list, LevelMeshDrawType drawType, bool translucent, unsigned int sectorIndex, const LightListAllocInfo& lightlist, int lightlistSection); BBox GetBoundsFromSurface(const LevelMeshSurface& surface) const; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 68e94853c..dc550530d 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -861,6 +861,9 @@ void HWDrawInfo::RenderTranslucent(FRenderState &state) state.EnableBrightmap(true); drawlists[GLDL_TRANSLUCENTBORDER].Draw(this, state, true); + state.ApplyLevelMesh(); + state.DrawLevelMeshList(SeenSidesDrawLists.List[static_cast(LevelMeshDrawType::TranslucentBorder)], false, false); + state.DrawLevelMeshList(SeenFlatsDrawLists.List[static_cast(LevelMeshDrawType::TranslucentBorder)], false, false); state.SetDepthMask(false); // To do: this needs to be sorted diff --git a/src/rendering/hwrenderer/scene/hw_walldispatcher.h b/src/rendering/hwrenderer/scene/hw_walldispatcher.h index 678186294..15aec94af 100644 --- a/src/rendering/hwrenderer/scene/hw_walldispatcher.h +++ b/src/rendering/hwrenderer/scene/hw_walldispatcher.h @@ -9,8 +9,11 @@ struct HWMissing struct HWMeshHelper { - TArray list; + TArray opaque; + TArray masked; + TArray maskedOffset; TArray translucent; + TArray translucentBorder; TArray portals; TArray lower; TArray upper; @@ -66,11 +69,31 @@ struct HWWallDispatcher return di && di->isFullbrightScene(); } - void AddWall(HWWall* wal) + void AddWall(HWWall* wall) { - if (di) di->AddWall(wal); - else if (!(wal->flags & HWWall::HWF_TRANSLUCENT)) mh->list.Push(*wal); - else mh->translucent.Push(*wal); + if (di) di->AddWall(wall); + else + { + if (wall->flags & HWWall::HWF_TRANSLUCENT) + { + mh->translucent.Push(*wall); + } + else + { + if (wall->flags & HWWall::HWF_SKYHACK && wall->type == RENDERWALL_M2S) + { + mh->maskedOffset.Push(*wall); + } + else + { + bool masked = HWWall::passflag[wall->type] == 1 ? false : (wall->texture && wall->texture->isMasked()); + if (masked) + mh->masked.Push(*wall); + else + mh->opaque.Push(*wall); + } + } + } } void AddPortal(HWWall* wal)