Używam C # i XNA. Mój obecny algorytm oświetlenia to metoda rekurencyjna. Jest jednak drogi , do tego stopnia, że jeden fragment 8 x 128 x 8 obliczany co 5 sekund.
- Czy istnieją inne metody oświetlenia, które będą tworzyć cienie o zmiennej ciemności?
- A może metoda rekurencyjna jest dobra i może po prostu robię to źle?
Wydaje się, że rekurencyjne rzeczy są zasadniczo drogie (zmuszone przejść przez około 25 000 bloków na porcję). Myślałem o użyciu metody podobnej do ray tracingu, ale nie mam pojęcia, jak to zadziała. Inną rzeczą, którą próbowałem, było przechowywanie źródeł światła na liście, a dla każdego bloku uzyskanie odległości do każdego źródła światła i użycie go do oświetlenia go na odpowiednim poziomie, ale wtedy światło przechodziło przez ściany.
Mój aktualny kod rekurencyjny znajduje się poniżej. Jest to wywoływane z dowolnego miejsca w kawałku, które nie ma poziomu światła zerowego, po wyczyszczeniu i ponownym dodaniu światła słonecznego i pochodni.
world.get___at
jest funkcją, która może przenosić bloki poza tę porcję (jest to wewnątrz klasy porcji). Location
to moja własna struktura, która jest jak a Vector3
, ale używa liczb całkowitych zamiast wartości zmiennoprzecinkowych. light[,,]
jest lightmapą dla fragmentu.
private void recursiveLight(int x, int y, int z, byte lightLevel)
{
Location loc = new Location(x + chunkx * 8, y, z + chunky * 8);
if (world.getBlockAt(loc).BlockData.isSolid)
return;
lightLevel--;
if (world.getLightAt(loc) >= lightLevel || lightLevel <= 0)
return;
if (y < 0 || y > 127 || x < -8 || x > 16 || z < -8 || z > 16)
return;
if (x >= 0 && x < 8 && z >= 0 && z < 8)
light[x, y, z] = lightLevel;
recursiveLight(x + 1, y, z, lightLevel);
recursiveLight(x - 1, y, z, lightLevel);
recursiveLight(x, y + 1, z, lightLevel);
recursiveLight(x, y - 1, z, lightLevel);
recursiveLight(x, y, z + 1, lightLevel);
recursiveLight(x, y, z - 1, lightLevel);
}