Use a faster way to find the closest light probe

Fix light probe not being applied to psprite
This commit is contained in:
Magnus Norddahl 2021-10-14 05:43:35 +02:00
commit 764a08752f
8 changed files with 103 additions and 28 deletions

View file

@ -433,6 +433,7 @@ 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

@ -45,6 +45,50 @@ 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
float radiusSquared = 32.0f * 32.0f;
float lastdist = 0.0f;
BSPWalkCircle(level, x, y, radiusSquared, [&](subsector_t* subsector) // Iterate through all subsectors potentially touched by actor
{
for (uint32_t i = 0; i < subsector->numprobes; i++)
{
LightProbe* probe = subsector->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;
}
//==========================================================================
//
// Sets a single light value from all dynamic lights affecting the specified location
@ -57,7 +101,15 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FLig
float frac, lr, lg, lb;
float radius;
Level->GetLightProbeLight(x, y, z, out);
out[0] = out[1] = out[2] = 0.f;
LightProbe* probe = FindLightProbe(Level, x, y, z);
if (probe)
{
out[0] = probe->Red;
out[1] = probe->Green;
out[2] = probe->Blue;
}
// Go through both light lists
while (node)

View file

@ -172,6 +172,12 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent)
di->GetDynSpriteLight(gl_light_sprites ? actor : nullptr, gl_light_particles ? particle : nullptr, out);
state.SetDynLight(out[0], out[1], out[2]);
}
else if (di->Level->LightProbes.Size() > 0)
{
LightProbe* probe = FindLightProbe(di->Level, actor->X(), actor->Y(), actor->Center());
if (probe)
state.SetDynLight(probe->Red, probe->Green, probe->Blue);
}
}
sector_t *cursec = actor ? actor->Sector : particle ? particle->subsector->sector : nullptr;
if (cursec != nullptr)

View file

@ -641,6 +641,14 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area)
{
hw_GetDynModelLight(playermo, lightdata);
hudsprite.lightindex = screen->mLights->UploadLights(lightdata);
LightProbe* probe = FindLightProbe(playermo->Level, playermo->X(), playermo->Y(), playermo->Center());
if (probe)
{
hudsprite.dynrgb[0] = probe->Red;
hudsprite.dynrgb[1] = probe->Green;
hudsprite.dynrgb[2] = probe->Blue;
}
}
}