From dc234ea72daf52e5983d4d94aad50d43a612d470 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Apr 2021 22:52:46 +0200 Subject: [PATCH] - implemented RR's geometry effect. The grossest of all gross render hack that were ever done with Build... --- source/core/automap.cpp | 4 +- source/core/gamestruct.h | 14 ++++ source/core/rendering/hw_entrypoint.cpp | 2 +- source/core/rendering/scene/hw_drawinfo.cpp | 75 ++++++++++++++++++++ source/core/rendering/scene/hw_drawinfo.h | 4 +- source/core/rendering/scene/hw_drawstructs.h | 1 + source/core/rendering/scene/hw_flats.cpp | 7 +- source/core/sectorgeometry.cpp | 16 +++-- source/core/sectorgeometry.h | 8 +-- source/games/duke/src/duke3d.h | 1 + source/games/duke/src/render.cpp | 17 +++++ 11 files changed, 131 insertions(+), 18 deletions(-) diff --git a/source/core/automap.cpp b/source/core/automap.cpp index 1589708a1..902ab46a3 100644 --- a/source/core/automap.cpp +++ b/source/core/automap.cpp @@ -478,7 +478,7 @@ static void drawwhitelines(int cposx, int cposy, int czoom, int cang) for (j = startwall, wal = &wall[startwall]; j < endwall; j++, wal++) { if (wal->nextwall >= 0) continue; - if (!tileGetTexture(wal->picnum)->isValid()) continue; + if (!gFullMap && !tileGetTexture(wal->picnum)->isValid()) continue; if ((g_gameType & GAMEFLAG_SW) && !gFullMap && !show2dwall[j]) continue; @@ -588,7 +588,7 @@ void renderDrawMapView(int cposx, int cposy, int czoom, int cang) int picnum = sector[i].floorpicnum; if ((unsigned)picnum >= (unsigned)MAXTILES) continue; - auto mesh = sectorGeometry.get(i, 0); + auto mesh = sectorGeometry.get(i, 0, { 0.f,0.f }); vertices.Resize(mesh->vertices.Size()); for (unsigned j = 0; j < mesh->vertices.Size(); j++) { diff --git a/source/core/gamestruct.h b/source/core/gamestruct.h index 8262df663..96a45c238 100644 --- a/source/core/gamestruct.h +++ b/source/core/gamestruct.h @@ -47,6 +47,19 @@ struct MapRecord; extern cycle_t drawtime, actortime, thinktime, gameupdatetime; +struct GeoEffect +{ + int* geosectorwarp; + int* geosectorwarp2; + int* geosector; + int* geox; + int* geoy; + int* geox2; + int* geoy2; + int geocnt; + +}; + struct GameInterface { virtual const char* Name() { return "$"; } @@ -107,6 +120,7 @@ struct GameInterface virtual void UpdateCameras(double smoothratio) {} virtual void EnterPortal(spritetype* viewer, int type) {} virtual void LeavePortal(spritetype* viewer, int type) {} + virtual bool GetGeoEffect(GeoEffect* eff, int viewsector) { return false; } virtual FString statFPS() { diff --git a/source/core/rendering/hw_entrypoint.cpp b/source/core/rendering/hw_entrypoint.cpp index cf3462c2d..08c0248ea 100644 --- a/source/core/rendering/hw_entrypoint.cpp +++ b/source/core/rendering/hw_entrypoint.cpp @@ -6,7 +6,7 @@ // // 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 2 of the License, or +// 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, diff --git a/source/core/rendering/scene/hw_drawinfo.cpp b/source/core/rendering/scene/hw_drawinfo.cpp index f5085f964..89b55d39f 100644 --- a/source/core/rendering/scene/hw_drawinfo.cpp +++ b/source/core/rendering/scene/hw_drawinfo.cpp @@ -384,6 +384,8 @@ void HWDrawInfo::CreateScene() screen->mLights->Map(); spritesortcnt = 0; + ingeo = false; + geoofs = { 0,0 }; vec2_t view = { int(vp.Pos.X * 16), int(vp.Pos.Y * -16) }; mDrawer.Init(this, mClipper, view); @@ -397,6 +399,79 @@ void HWDrawInfo::CreateScene() DispatchSprites(); SetupSprite.Unclock(); + GeoEffect eff; + int effsect = vp.SectNums ? vp.SectNums[0] : vp.SectCount; + int drawsect = effsect; + // RR geometry hack. Ugh... + // This just adds to the existing render list, so we must offset the effect areas to the same xy-space as the main one as we cannot change the view matrix. + if (gi->GetGeoEffect(&eff, effsect)) + { + ingeo = true; + geoofs = { (float)eff.geox[0], (float)eff.geoy[0] }; + // process the first layer. + for (int i = 0; i < eff.geocnt; i++) + { + auto sect = §or[eff.geosectorwarp[i]]; + for (auto w = 0; w < sect->wallnum; w++) + { + auto wal = &wall[sect->wallptr + w]; + wal->x += eff.geox[i]; + wal->y += eff.geoy[i]; + } + sect->dirty = 255; + if (eff.geosector[i] == effsect) drawsect = eff.geosectorwarp[i]; + } + + mClipper->Clear(); + mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1)); + mDrawer.Init(this, mClipper, view); + mDrawer.RenderScene(&drawsect, 1); + + for (int i = 0; i < eff.geocnt; i++) + { + auto sect = §or[eff.geosectorwarp[i]]; + for (auto w = 0; w < sect->wallnum; w++) + { + auto wal = &wall[sect->wallptr + w]; + wal->x -= eff.geox[i]; + wal->y -= eff.geoy[i]; + } + } + + // Now the second layer. Same shit, different arrays. + geoofs = { (float)eff.geox2[0], (float)eff.geoy2[0] }; + for (int i = 0; i < eff.geocnt; i++) + { + auto sect = §or[eff.geosectorwarp2[i]]; + for (auto w = 0; w < sect->wallnum; w++) + { + auto wal = &wall[sect->wallptr + w]; + wal->x += eff.geox2[i]; + wal->y += eff.geoy2[i]; + } + sect->dirty = 255; + if (eff.geosector[i] == effsect) drawsect = eff.geosectorwarp2[i]; + } + + mClipper->Clear(); + mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1)); + mDrawer.Init(this, mClipper, view); + mDrawer.RenderScene(&drawsect, 1); + + for (int i = 0; i < eff.geocnt; i++) + { + auto sect = §or[eff.geosectorwarp2[i]]; + for (auto w = 0; w < sect->wallnum; w++) + { + auto wal = &wall[sect->wallptr + w]; + wal->x -= eff.geox2[i]; + wal->y -= eff.geoy2[i]; + } + } + ingeo = false; + } + + screen->mLights->Unmap(); screen->mVertexData->Unmap(); diff --git a/source/core/rendering/scene/hw_drawinfo.h b/source/core/rendering/scene/hw_drawinfo.h index a8da9ed56..dc223ed21 100644 --- a/source/core/rendering/scene/hw_drawinfo.h +++ b/source/core/rendering/scene/hw_drawinfo.h @@ -109,10 +109,12 @@ struct HWDrawInfo HWViewpointUniforms VPUniforms; // per-viewpoint uniform state TArray Portals; spritetype tsprite[MAXSPRITESONSCREEN]; - int spritesortcnt = 0; + int spritesortcnt; // This is needed by the BSP traverser. bool multithread; + bool ingeo; + FVector2 geoofs; private: bool inview; diff --git a/source/core/rendering/scene/hw_drawstructs.h b/source/core/rendering/scene/hw_drawstructs.h index e1723b8e1..4d4d75277 100644 --- a/source/core/rendering/scene/hw_drawstructs.h +++ b/source/core/rendering/scene/hw_drawstructs.h @@ -258,6 +258,7 @@ public: FRenderStyle RenderStyle; int iboindex; bool stack; + FVector2 geoofs; //int vboheight; int plane; diff --git a/source/core/rendering/scene/hw_flats.cpp b/source/core/rendering/scene/hw_flats.cpp index c7415e3df..525cfd8e1 100644 --- a/source/core/rendering/scene/hw_flats.cpp +++ b/source/core/rendering/scene/hw_flats.cpp @@ -101,7 +101,7 @@ void HWFlat::MakeVertices() bool canvas = texture->isHardwareCanvas(); if (sprite == nullptr) { - auto mesh = sectorGeometry.get(sec - sector, plane); + auto mesh = sectorGeometry.get(sec - sector, plane, geoofs); if (!mesh) return; auto ret = screen->mVertexData->AllocVertices(mesh->vertices.Size()); auto vp = ret.first; @@ -161,7 +161,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) if (!sprite) { - auto mesh = sectorGeometry.get(sec - sector, plane); + auto mesh = sectorGeometry.get(sec - sector, plane, geoofs); state.SetNormal(mesh->normal); } else @@ -231,7 +231,7 @@ void HWFlat::PutFlat(HWDrawInfo *di, int whichplane) { vertcount = 0; plane = whichplane; - if (!screen->BuffersArePersistent() || sprite) // should be made static buffer content later (when the logic is working) + if (!screen->BuffersArePersistent() || sprite || di->ingeo) // should be made static buffer content later (when the logic is working) { #if 0 if (di->Level->HasDynamicLights && texture != nullptr && !di->isFullbrightScene() && !(hacktype & (SSRF_PLANEHACK | SSRF_FLOODHACK))) @@ -273,6 +273,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sectortype * frontsector, int which) visibility = sectorVisibility(frontsector); sec = frontsector; sprite = nullptr; + geoofs = di->geoofs; // // diff --git a/source/core/sectorgeometry.cpp b/source/core/sectorgeometry.cpp index 7099771ef..c39e11042 100644 --- a/source/core/sectorgeometry.cpp +++ b/source/core/sectorgeometry.cpp @@ -99,17 +99,19 @@ class UVCalculator FGameTexture* tex; float xpanning, ypanning; float xscaled, yscaled; + FVector2 offset; public: // Moved in from pragmas.h - UVCalculator(sectortype* sec, int plane, FGameTexture* tx) + UVCalculator(sectortype* sec, int plane, FGameTexture* tx, const FVector2& off) { float xpan, ypan; sect = sec; tex = tx; myplane = plane; + offset = off; auto firstwall = &wall[sec->wallptr]; ix1 = firstwall->x; @@ -188,8 +190,8 @@ public: } else { - tu = x; - tv = -y; + tu = x - offset.X; + tv = -y - offset.Y; } if (stat & CSTAT_SECTOR_SWAPXY) @@ -212,7 +214,7 @@ public: // //========================================================================== -void SectorGeometry::MakeVertices(unsigned int secnum, int plane) +void SectorGeometry::MakeVertices(unsigned int secnum, int plane, const FVector2& offset) { auto sec = §or[secnum]; int numvertices = sec->wallnum; @@ -297,7 +299,7 @@ void SectorGeometry::MakeVertices(unsigned int secnum, int plane) auto texture = tileGetTexture(plane ? sec->ceilingpicnum : sec->floorpicnum); - UVCalculator uvcalc(sec, plane, texture); + UVCalculator uvcalc(sec, plane, texture, offset); for(unsigned i = 0; i < entry.vertices.Size(); i++) { @@ -317,7 +319,7 @@ void SectorGeometry::MakeVertices(unsigned int secnum, int plane) // //========================================================================== -void SectorGeometry::ValidateSector(unsigned int secnum, int plane) +void SectorGeometry::ValidateSector(unsigned int secnum, int plane, const FVector2& offset) { auto sec = §or[secnum]; auto compare = &data[secnum].compare[plane]; @@ -350,5 +352,5 @@ void SectorGeometry::ValidateSector(unsigned int secnum, int plane) *compare = *sec; data[secnum].poscompare[plane] = wall[sec->wallptr].pos; data[secnum].poscompare2[plane] = wall[wall[sec->wallptr].point2].pos; - MakeVertices(secnum, plane); + MakeVertices(secnum, plane, offset); } diff --git a/source/core/sectorgeometry.h b/source/core/sectorgeometry.h index cc6665f9c..75026d028 100644 --- a/source/core/sectorgeometry.h +++ b/source/core/sectorgeometry.h @@ -23,14 +23,14 @@ class SectorGeometry { TArray data; - void ValidateSector(unsigned sectnum, int plane); - void MakeVertices(unsigned sectnum, int plane); + void ValidateSector(unsigned sectnum, int plane, const FVector2& offset); + void MakeVertices(unsigned sectnum, int plane, const FVector2& offset); public: - SectorGeometryPlane* get(unsigned sectnum, int plane) + SectorGeometryPlane* get(unsigned sectnum, int plane, const FVector2& offset) { if (sectnum >= data.Size()) return nullptr; - ValidateSector(sectnum, plane); + ValidateSector(sectnum, plane, offset); return &data[sectnum].planes[plane]; } diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h index cda00ae23..4afd5ec7e 100644 --- a/source/games/duke/src/duke3d.h +++ b/source/games/duke/src/duke3d.h @@ -69,6 +69,7 @@ struct GameInterface : public ::GameInterface void UpdateCameras(double smoothratio) override; void EnterPortal(spritetype* viewer, int type) override; void LeavePortal(spritetype* viewer, int type) override; + bool GetGeoEffect(GeoEffect* eff, int viewsector) override; }; diff --git a/source/games/duke/src/render.cpp b/source/games/duke/src/render.cpp index ed807f4a3..1bfe527ed 100644 --- a/source/games/duke/src/render.cpp +++ b/source/games/duke/src/render.cpp @@ -144,6 +144,23 @@ void GameInterface::LeavePortal(spritetype* viewer, int type) if (type == PORTAL_WALL_MIRROR) display_mirror--; } +bool GameInterface::GetGeoEffect(GeoEffect* eff, int viewsector) +{ + if (!isRR() || sector[viewsector].lotag == 848) + { + eff->geocnt = geocnt; + eff->geosector = geosector; + eff->geosectorwarp = geosectorwarp; + eff->geosectorwarp2 = geosectorwarp2; + eff->geox = geox; + eff->geoy = geoy; + eff->geox2 = geox2; + eff->geoy2 = geoy2; + return true; + } + return false; +} + //--------------------------------------------------------------------------- // // RRRA's drug distortion effect