forked from Mirrors/openclonk
Don't update relights array while relighting (#1371)
Removing solidmasks temporarily as part of the relighting procedure caused a landscape update which modified the list of to-be-relighted regions that is currently being iterated over. This could cause relighting of a region in which solidmasks have not been removed, leading to vehicle pixels in the landscape surface used by the landscape shader, which show up pink on the screen. Fixed this by introducing C4Landscape::_SetPix2Tmp, which changes a pixel without causing relighting (or material count updates), and use that when temporarily removing or putting solidmasks. This should also avoid unnecessary computations (relighting, material count updates) when updating the landscape or moving objects with solidmasks.shapetextures
parent
9a9486d0fe
commit
236759b1db
|
@ -329,7 +329,6 @@ bool C4Landscape::DoRelights()
|
|||
if (!Relights[i].Wdt)
|
||||
break;
|
||||
// Remove all solid masks in the (twice!) extended region around the change
|
||||
// TODO: Isn't Relights[i] already an "affected" rect? Might save a bit here...
|
||||
C4Rect SolidMaskRect = pLandscapeRender->GetAffectedRect(Relights[i]);
|
||||
C4SolidMask * pSolid;
|
||||
for (pSolid = C4SolidMask::Last; pSolid; pSolid = pSolid->Prev)
|
||||
|
@ -704,20 +703,6 @@ bool C4Landscape::SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix)
|
|||
// no change?
|
||||
if ((fgPix == Transparent || fgPix == _GetPix(x, y)) && (bgPix == Transparent || bgPix == Surface8Bkg->_GetPix(x, y)))
|
||||
return true;
|
||||
// note for relight (TODO: Why is this not in _SetPix2?)
|
||||
if(pLandscapeRender)
|
||||
{
|
||||
C4Rect CheckRect = pLandscapeRender->GetAffectedRect(C4Rect(x, y, 1, 1));
|
||||
for (int32_t i = 0; i < C4LS_MaxRelights; i++)
|
||||
if (!Relights[i].Wdt || Relights[i].Overlap(CheckRect) || i + 1 >= C4LS_MaxRelights)
|
||||
{
|
||||
Relights[i].Add(CheckRect);
|
||||
break;
|
||||
}
|
||||
// Invalidate FoW
|
||||
if (pFoW)
|
||||
pFoW->Invalidate(CheckRect);
|
||||
}
|
||||
// set pixel
|
||||
return _SetPix2(x, y, fgPix, bgPix);
|
||||
}
|
||||
|
@ -788,10 +773,32 @@ bool C4Landscape::_SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix)
|
|||
// set 8bpp-surface only!
|
||||
Surface8->SetPix(x, y, fgPix);
|
||||
Surface8Bkg->SetPix(x, y, bgPix);
|
||||
// note for relight
|
||||
if(pLandscapeRender)
|
||||
{
|
||||
C4Rect CheckRect = pLandscapeRender->GetAffectedRect(C4Rect(x, y, 1, 1));
|
||||
for (int32_t i = 0; i < C4LS_MaxRelights; i++)
|
||||
if (!Relights[i].Wdt || Relights[i].Overlap(CheckRect) || i + 1 >= C4LS_MaxRelights)
|
||||
{
|
||||
Relights[i].Add(CheckRect);
|
||||
break;
|
||||
}
|
||||
// Invalidate FoW
|
||||
if (pFoW)
|
||||
pFoW->Invalidate(CheckRect);
|
||||
}
|
||||
// success
|
||||
return true;
|
||||
}
|
||||
|
||||
void C4Landscape::_SetPix2Tmp(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix)
|
||||
{
|
||||
// set 8bpp-surface only!
|
||||
assert(x >= 0 && y >= 0 && x < Width && y < Height);
|
||||
if (fgPix != Transparent) Surface8->SetPix(x, y, fgPix);
|
||||
if (bgPix != Transparent) Surface8Bkg->SetPix(x, y, bgPix);
|
||||
}
|
||||
|
||||
bool C4Landscape::CheckInstability(int32_t tx, int32_t ty, int32_t recursion_count)
|
||||
{
|
||||
int32_t mat=GetMat(tx,ty);
|
||||
|
|
|
@ -111,6 +111,7 @@ public:
|
|||
bool SetMode(int32_t iMode);
|
||||
bool SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix); // set landscape pixel (bounds checked)
|
||||
bool _SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix); // set landsape pixel (bounds not checked)
|
||||
void _SetPix2Tmp(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix); // set landsape pixel (bounds not checked, no material count updates, no landscape relighting). Material must be reset to original value with this function before modifying landscape in any other way. Only used for temporary pixel changes by SolidMask (C4SolidMask::RemoveTemporary, C4SolidMask::PutTemporary).
|
||||
bool InsertMaterial(int32_t mat, int32_t *tx, int32_t *ty, int32_t vx = 0, int32_t vy = 0, bool query_only=false); // modifies tx/ty to actual insertion position
|
||||
bool InsertDeadMaterial(int32_t mat, int32_t tx, int32_t ty);
|
||||
bool FindMatPath(int32_t &fx, int32_t &fy, int32_t ydir, int32_t mdens, int32_t mslide) const;
|
||||
|
|
|
@ -354,7 +354,7 @@ void C4SolidMask::RemoveTemporary(C4Rect where)
|
|||
{
|
||||
// restore
|
||||
assert(IsSomeVehicle(GBackPix(x,y)));
|
||||
::Landscape.SetPix2(x, y, *pPix, ::Landscape.Transparent);
|
||||
::Landscape._SetPix2Tmp(x, y, *pPix, ::Landscape.Transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +375,7 @@ void C4SolidMask::PutTemporary(C4Rect where)
|
|||
{
|
||||
// put
|
||||
assert(GBackPix(x,y)==*pPix);
|
||||
::Landscape.SetPix2(x, y, MaskMaterial, ::Landscape.Transparent);
|
||||
::Landscape._SetPix2Tmp(x, y, MaskMaterial, ::Landscape.Transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue