Remove light probes completely and make decals use the lightmap

This commit is contained in:
Magnus Norddahl 2022-09-21 22:43:43 +02:00 committed by Christoph Oelckers
parent b81a51dabe
commit 34a1ecdee1
7 changed files with 48 additions and 159 deletions

View file

@ -396,9 +396,9 @@ void D_Render(std::function<void()> action, bool interpolate)
for (auto Level : AllLevels())
{
// Check for the presence of dynamic lights at the start of the frame once.
if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4) || Level->LightProbes.Size() > 0)
if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4) || Level->LMTextureCount > 0)
{
Level->HasDynamicLights = Level->lights || Level->LightProbes.Size() > 0;
Level->HasDynamicLights = Level->lights || Level->LMTextureCount > 0;
}
else Level->HasDynamicLights = false; // lights are off so effectively we have none.
if (interpolate) Level->interpolator.DoInterpolations(I_GetTimeFrac());

View file

@ -459,13 +459,6 @@ public:
int LMTextureCount = 0;
int LMTextureSize = 0;
TArray<uint16_t> LMTextureData;
TArray<LightProbe> LightProbes;
int LPMinX = 0;
int LPMinY = 0;
int LPWidth = 0;
int LPHeight = 0;
static const int LPCellSize = 32;
TArray<LightProbeCell> LPCells;
// Portal information.
FDisplacementTable Displacements;

View file

@ -61,7 +61,6 @@ class AActor;
struct FSection;
struct FLevelLocals;
struct LightmapSurface;
struct LightProbe;
const uint16_t NO_INDEX = 0xffffu;
const uint32_t NO_SIDE = 0xffffffffu;
@ -1710,18 +1709,6 @@ struct LightmapSurface
float *TexCoords;
};
struct LightProbe
{
float X, Y, Z;
float Red, Green, Blue;
};
struct LightProbeCell
{
LightProbe* FirstProbe = nullptr;
int NumProbes = 0;
};
//
// OTHER TYPES
//

View file

@ -3325,17 +3325,11 @@ void MapLoader::SetSideLightmap(const LightmapSurface &surface)
void MapLoader::LoadLightmap(MapData *map)
{
// We have to reset everything as FLevelLocals is recycled between maps
Level->LightProbes.Reset();
Level->LPCells.Reset();
Level->LMTexCoords.Reset();
Level->LMSurfaces.Reset();
Level->LMTextureData.Reset();
Level->LMTextureCount = 0;
Level->LMTextureSize = 0;
Level->LPMinX = 0;
Level->LPMinY = 0;
Level->LPWidth = 0;
Level->LPHeight = 0;
if (!Args->CheckParm("-enablelightmaps"))
return; // this feature is still too early WIP to allow general access
@ -3375,61 +3369,8 @@ void MapLoader::LoadLightmap(MapData *map)
if (numLightProbes > 0)
{
Level->LightProbes.Resize(numLightProbes);
fr.Read(&Level->LightProbes[0], sizeof(LightProbe) * numLightProbes);
// Sort the light probes so that they are ordered by cell.
// This lets us point at the first probe knowing all other probes in the cell will follow.
// Also improves locality.
double rcpCellSize = 1.0 / Level->LPCellSize;
auto cellCompareLess = [=](const LightProbe& a, const LightProbe& b)
{
double cellY_A = std::floor(a.Y * rcpCellSize);
double cellY_B = std::floor(b.Y * rcpCellSize);
if (cellY_A != cellY_B)
return cellY_A < cellY_B;
double cellX_A = std::floor(a.X * rcpCellSize);
double cellX_B = std::floor(b.X * rcpCellSize);
return cellX_A < cellX_B;
};
std::sort(Level->LightProbes.begin(), Level->LightProbes.end(), cellCompareLess);
// Find probe bounds and the grid that covers it
float probesMinX = Level->LightProbes[0].X;
float probesMaxX = Level->LightProbes[0].X;
float probesMinY = Level->LightProbes[0].Y;
float probesMaxY = Level->LightProbes[0].Y;
for (const LightProbe& p : Level->LightProbes)
{
probesMinX = std::min(probesMinX, p.X);
probesMaxX = std::max(probesMaxX, p.X);
probesMinY = std::min(probesMinY, p.Y);
probesMaxY = std::max(probesMaxY, p.Y);
}
Level->LPMinX = (int)std::floor(probesMinX * rcpCellSize);
Level->LPMinY = (int)std::floor(probesMinY * rcpCellSize);
Level->LPWidth = (int)std::floor(probesMaxX * rcpCellSize) + 1 - Level->LPMinX;
Level->LPHeight = (int)std::floor(probesMaxY * rcpCellSize) + 1 - Level->LPMinY;
// Place probes in a grid for faster search
Level->LPCells.Resize(Level->LPWidth * Level->LPHeight);
int minX = Level->LPMinX;
int minY = Level->LPMinY;
int width = Level->LPWidth;
int height = Level->LPHeight;
for (LightProbe& p : Level->LightProbes)
{
int gridX = (int)std::floor(p.X * rcpCellSize) - minX;
int gridY = (int)std::floor(p.Y * rcpCellSize) - minY;
if (gridX >= 0 && gridY >= 0 && gridX < width && gridY < height)
{
LightProbeCell& cell = Level->LPCells[gridX + (size_t)gridY * width];
if (!cell.FirstProbe)
cell.FirstProbe = &p;
cell.NumProbes++;
}
}
Printf(PRINT_HIGH, "LoadLightmap: This is an old unsupported alpha version of the lightmap lump. Please rebuild the map with a newer version of zdray.\n");
return;
}
Level->LMTexCoords.Resize(numTexCoords * 2);

View file

@ -59,21 +59,7 @@ void HWDecal::DrawDecal(HWDrawInfo *di, FRenderState &state)
if (!di->isFullbrightScene()) DecalColor = DecalColor.Modulate(frontsector->SpecialColors[sector_t::sprites]);
state.SetObjectColor(DecalColor);
state.SetLightIndex(dynlightindex);
// add light probe contribution
if (di->Level->LightProbes.Size() > 0)
{
double x, y;
decal->GetXY(decal->Side, x, y);
LightProbe *probe = FindLightProbe(di->Level, x, y, decal->GetRealZ(decal->Side) * 0.5);
if (probe)
{
state.SetDynLight(probe->Red, probe->Green, probe->Blue);
}
}
state.SetTextureMode(decal->RenderStyle);
state.SetRenderStyle(decal->RenderStyle);
state.SetMaterial(texture, UF_Sprite, 0, CLAMP_XY, decal->Translation, -1);
@ -197,6 +183,11 @@ void HWWall::DrawDecalsForMirror(HWDrawInfo *di, FRenderState &state, TArray<HWD
//
//==========================================================================
static float mix(float a, float b, float t)
{
return a * (1.0f - t) + b * t;
}
void HWWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &normal)
{
line_t * line = seg->linedef;
@ -342,7 +333,31 @@ void HWWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
dv[UL].u = dv[LL].u = lefttex / decalscale;
dv[LR].u = dv[UR].u = righttex / decalscale;
dv[LL].v = dv[LR].v = 1.f;
// lightmap texture index
for (i = 0; i < 4; i++)
{
dv[i].lindex = lindex;
}
// lightmap texture coordinates
float tleft = left / linelength;
float tright = right / linelength;
float tuplft = ztop[0] != zbottom[0] ? (dv[UL].z - zbottom[0]) / (ztop[0] - zbottom[0]) : 0.0f;
float tuprgt = ztop[1] != zbottom[1] ? (dv[UR].z - zbottom[1]) / (ztop[1] - zbottom[1]) : 0.0f;
float tlolft = ztop[0] != zbottom[0] ? (dv[LL].z - zbottom[0]) / (ztop[0] - zbottom[0]) : 0.0f;
float tlorgt = ztop[1] != zbottom[1] ? (dv[LR].z - zbottom[1]) / (ztop[1] - zbottom[1]) : 0.0f;
dv[LL].lu = mix(lightuv[LOLFT].u, lightuv[LORGT].u, tleft);
dv[LR].lu = mix(lightuv[LOLFT].u, lightuv[LORGT].u, tright);
dv[UL].lu = mix(lightuv[UPLFT].u, lightuv[UPRGT].u, tleft);
dv[UR].lu = mix(lightuv[UPLFT].u, lightuv[UPRGT].u, tright);
dv[LL].lv = mix(lightuv[LOLFT].v, lightuv[UPLFT].v, tlolft);
dv[LR].lv = mix(lightuv[LORGT].v, lightuv[UPRGT].v, tlorgt);
dv[UL].lv = mix(lightuv[LOLFT].v, lightuv[UPLFT].v, tuplft);
dv[UR].lv = mix(lightuv[LORGT].v, lightuv[UPRGT].v, tuprgt);
// now clip to the top plane
float vzt = (ztop[UL] - ztop[LL]) / linelength;
float topleft = ztop[LL] + vzt * left;
@ -356,8 +371,12 @@ void HWWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
{
// decal has to be clipped at the top
// let texture clamping handle all extreme cases
dv[UL].v = (dv[UL].z - topleft) / (dv[UL].z - dv[LL].z)*dv[LL].v;
dv[UR].v = (dv[UR].z - topright) / (dv[UR].z - dv[LR].z)*dv[LR].v;
float t0 = (dv[UL].z - topleft) / (dv[UL].z - dv[LL].z);
float t1 = (dv[UR].z - topright) / (dv[UR].z - dv[LR].z);
dv[UL].v = t0 * dv[LL].v;
dv[UR].v = t1 * dv[LR].v;
dv[UL].lv = mix(dv[UL].lv, dv[LL].lv, t0);
dv[UR].lv = mix(dv[UR].lv, dv[LR].lv, t1);
dv[UL].z = topleft;
dv[UR].z = topright;
}
@ -375,8 +394,12 @@ void HWWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
{
// decal has to be clipped at the bottom
// let texture clamping handle all extreme cases
dv[LL].v = (dv[UL].z - bottomleft) / (dv[UL].z - dv[LL].z)*(dv[LL].v - dv[UL].v) + dv[UL].v;
dv[LR].v = (dv[UR].z - bottomright) / (dv[UR].z - dv[LR].z)*(dv[LR].v - dv[UR].v) + dv[UR].v;
float t0 = (dv[UL].z - bottomleft) / (dv[UL].z - dv[LL].z);
float t1 = (dv[UR].z - bottomright) / (dv[UR].z - dv[LR].z);
dv[LL].v = t0 * (dv[LL].v - dv[UL].v) + dv[UL].v;
dv[LR].v = t1 * (dv[LR].v - dv[UR].v) + dv[UR].v;
dv[LL].lv = mix(dv[UL].lv, dv[LL].lv, t0);
dv[LR].lv = mix(dv[UR].lv, dv[LR].lv, t1);
dv[LL].z = bottomleft;
dv[LR].z = bottomright;
}
@ -427,7 +450,7 @@ void HWWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
for (i = 0; i < 4; i++)
{
verts.first[i].Set(dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v);
verts.first[i].Set(dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v, dv[i].lu, dv[i].lv, dv[i].lindex);
}
}

View file

@ -401,6 +401,7 @@ struct DecalVertex
{
float x, y, z;
float u, v;
float lu, lv, lindex;
};
struct HWDecal
@ -433,7 +434,6 @@ inline float Dist2(float x1,float y1,float x2,float y2)
bool hw_SetPlaneTextureRotation(const HWSectorPlane * secplane, FGameTexture * gltexture, VSMatrix &mat);
void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata);
LightProbe* FindLightProbe(FLevelLocals* level, float x, float y, float z);
extern const float LARGE_VALUE;

View file

@ -46,61 +46,6 @@ T smoothstep(const T edge0, const T edge1, const T x)
return t * t * (3.0 - 2.0 * t);
}
LightProbe* FindLightProbe(FLevelLocals* level, float x, float y, float z)
{
LightProbe* foundprobe = nullptr;
if (level->LightProbes.Size() > 0)
{
#if 1
double rcpCellSize = 1.0 / level->LPCellSize;
int gridCenterX = (int)std::floor(x * rcpCellSize) - level->LPMinX;
int gridCenterY = (int)std::floor(y * rcpCellSize) - level->LPMinY;
int gridWidth = level->LPWidth;
int gridHeight = level->LPHeight;
float lastdist = 0.0f;
for (int gridY = gridCenterY - 1; gridY <= gridCenterY + 1; gridY++)
{
for (int gridX = gridCenterX - 1; gridX <= gridCenterX + 1; gridX++)
{
if (gridX >= 0 && gridY >= 0 && gridX < gridWidth && gridY < gridHeight)
{
const LightProbeCell& cell = level->LPCells[gridX + (size_t)gridY * gridWidth];
for (int i = 0; i < cell.NumProbes; i++)
{
LightProbe* probe = cell.FirstProbe + i;
float dx = probe->X - x;
float dy = probe->Y - y;
float dz = probe->Z - z;
float dist = dx * dx + dy * dy + dz * dz;
if (!foundprobe || dist < lastdist)
{
foundprobe = probe;
lastdist = dist;
}
}
}
}
}
#else
float lastdist = 0.0f;
for (unsigned int i = 0; i < level->LightProbes.Size(); i++)
{
LightProbe *probe = &level->LightProbes[i];
float dx = probe->X - x;
float dy = probe->Y - y;
float dz = probe->Z - z;
float dist = dx * dx + dy * dy + dz * dz;
if (i == 0 || dist < lastdist)
{
foundprobe = probe;
lastdist = dist;
}
}
#endif
}
return foundprobe;
}
static bool TraceLightVisbility(FLightNode* node, const FVector3& L, float dist)
{
FDynamicLight* light = node->lightsource;