mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-02-09 09:10:51 +00:00
Use a faster way to find the closest light probe
Fix light probe not being applied to psprite
This commit is contained in:
parent
b59bd46b79
commit
764a08752f
8 changed files with 103 additions and 28 deletions
|
@ -2282,27 +2282,3 @@ void FLevelLocals::SetMusic()
|
|||
{
|
||||
S_ChangeMusic(Music, musicorder);
|
||||
}
|
||||
|
||||
void FLevelLocals::GetLightProbeLight(float x, float y, float z, float* out)
|
||||
{
|
||||
out[0] = out[1] = out[2] = 0.f;
|
||||
|
||||
// To do: Pretty stupid algorithm. Use something better once we confirmed this looks alright.
|
||||
|
||||
float lastdist = 0.0f;
|
||||
for (unsigned int i = 0; i < LightProbes.Size(); i++)
|
||||
{
|
||||
const LightProbe& probe = 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)
|
||||
{
|
||||
out[0] = probe.Red;
|
||||
out[1] = probe.Green;
|
||||
out[2] = probe.Blue;
|
||||
lastdist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -429,8 +429,6 @@ public:
|
|||
|
||||
void SetMusic();
|
||||
|
||||
void GetLightProbeLight(float x, float y, float z, float* out);
|
||||
|
||||
TArray<vertex_t> vertexes;
|
||||
TArray<sector_t> sectors;
|
||||
TArray<extsector_t> extsectors; // container for non-trivial sector information. sector_t must be trivially copyable for *_fakeflat to work as intended.
|
||||
|
|
|
@ -59,6 +59,7 @@ class AActor;
|
|||
struct FSection;
|
||||
struct FLevelLocals;
|
||||
struct LightmapSurface;
|
||||
struct LightProbe;
|
||||
|
||||
const uint16_t NO_INDEX = 0xffffu;
|
||||
const uint32_t NO_SIDE = 0xffffffffu;
|
||||
|
@ -1621,6 +1622,8 @@ struct subsector_t
|
|||
FPortalCoverage portalcoverage[2];
|
||||
|
||||
LightmapSurface *lightmap[2];
|
||||
LightProbe* firstprobe;
|
||||
uint32_t numprobes;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -3335,19 +3335,27 @@ void MapLoader::LoadLightmap(MapData *map)
|
|||
|
||||
int version = fr.ReadInt32();
|
||||
if (version != 0)
|
||||
{
|
||||
Printf(PRINT_HIGH, "LoadLightmap: unsupported lightmap lump version\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t textureSize = fr.ReadUInt16();
|
||||
uint16_t numTextures = fr.ReadUInt16();
|
||||
uint32_t numSurfaces = fr.ReadUInt32();
|
||||
uint32_t numTexCoords = fr.ReadUInt32();
|
||||
uint32_t numLightProbes = fr.ReadUInt32();
|
||||
uint32_t numSubsectors = fr.ReadUInt32();
|
||||
uint32_t numTexBytes = numTextures * textureSize * textureSize * 3 * 2;
|
||||
|
||||
if (numSurfaces == 0 || numTexCoords == 0 || numTexBytes == 0)
|
||||
return;
|
||||
|
||||
Level->LMTexCoords.Resize(numTexCoords * 2);
|
||||
if (numSubsectors != Level->subsectors.Size())
|
||||
{
|
||||
Printf(PRINT_HIGH, "LoadLightmap: subsector count for level doesn't match\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (numLightProbes > 0)
|
||||
{
|
||||
|
@ -3355,6 +3363,29 @@ void MapLoader::LoadLightmap(MapData *map)
|
|||
fr.Read(&Level->LightProbes[0], sizeof(LightProbe) * numLightProbes);
|
||||
}
|
||||
|
||||
if (Level->subsectors.Size() > 0)
|
||||
{
|
||||
TArray<uint32_t> counts;
|
||||
counts.Resize(Level->subsectors.Size());
|
||||
fr.Read(&counts[0], sizeof(uint32_t) * Level->subsectors.Size());
|
||||
|
||||
unsigned int startIndex = 0;
|
||||
for (unsigned int i = 0; i < Level->subsectors.Size(); i++)
|
||||
{
|
||||
unsigned int count = counts[i];
|
||||
if (startIndex + count > Level->LightProbes.Size())
|
||||
{
|
||||
Printf(PRINT_HIGH, "LoadLightmap: invalid light probe data\n");
|
||||
break;
|
||||
}
|
||||
Level->subsectors[i].firstprobe = &Level->LightProbes[startIndex];
|
||||
Level->subsectors[i].numprobes = count;
|
||||
startIndex += count;
|
||||
}
|
||||
}
|
||||
|
||||
Level->LMTexCoords.Resize(numTexCoords * 2);
|
||||
|
||||
// Allocate room for all surfaces
|
||||
|
||||
unsigned int allSurfaces = 0;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue