我已经阅读了这个答案,并且已经尝试过:
for (int i = 0; i < mapArray.GetLength(0); i++)
{
for (int j = 0; j < mapArray.GetLength(1); j++)
{
if (mapArray[i, j] == null)
CurrentLight = 0f;
else
{
mapArray[i, j].Light = CurrentLight;
CurrentLight += Tiles.Absorb;
}
}
}
结果如下:
如您所见,我的问题是照明不真实,如果当前图块是一个块,该函数将穿过各列并以0.05F的光吸收光线;如果不是图块,则它将重置为0(这是全亮度)。
那棵树主要进入我的眼睛,而光线不是那么好..我应该如何改善它?
谢谢。
The most important phenomenon in this scenario is light scattering. Light scattering takes place in every direction, not only downwards as you modelled it. You can calculate the lighting with a big linear system of equations, but this is potentially slow (see radiosity). Here is an approximative alternative:
The basic idea is that a block distributes its light to all neighbouring blocks. We start with a 1
for unfilled blocks and 0
for filled blocks (note that I use 0
for "no light" and 1
for "full light"; this seems to be more intuitive"). After we have initialized all blocks with their respective values, we can start the following distribution pass (I omitted range checks; that's up to you):
float[, ] incomingLight; // should have the same size as the map
// and saves the additional light for each block
for each i,j in the map
float myLight = (map[i, j] == null ? 1 : map[i, j].Light)
incomingLight[i - 1, j ] += 0.10f * myLight //Add light to the left neighbour
incomingLight[i - 1, j - 1] += 0.07f * myLight //top left neighbour
incomingLight[i , j - 1] += 0.10f * myLight //top neighbour
//do the same for all remaining neighbours
incomingLight[i, j] -= (sumOfWeights) * myLight //preserve overall light intensity
// ...
next
for each i,j in the map
if(map[i, j] != null)
map[i, j].Light = min(1, map[i, j].Light + incomingLight[i, j])
incomingLight[i, j] = 0
next
Now we have illuminated all blocks that are adjacent to a light block. You might need to adjust the weights for the distribution.
We can repeat this pass to create a more realistic lighting. The more often the pass is executed, the deeper the light will scatter. Note that each pass will brighten up the entire scene because unfilled blocks have basically an infinite light intensity.
Another approach, which should be faster but slightly more imprecise, is to calculate the distance of each block to the nearest unblocked tile and use this as a coefficient for the lighting. There are very efficient algorithms to calculate the distance (see distance transform). Calculating the block distance (Manhattan distance) is quite simple and should suffice in your case:
用无穷大或很大的数字初始化填充块,用0初始化未填充的块。然后执行四遍:
float [,] distances //initialized with 0 or infinity
//from top left corner
for y from 0 to height - 1
for x from 0 to width - 1
distances[x, y] = min(distances[x, y], distances[x - 1, y] + 1, distances[x, y - 1] + 1)
//from top right corner
for y from 0 to height - 1
for x width - 1 to 0
distances[x, y] = min(distances[x, y], distances[x + 1, y] + 1, distances[x, y - 1] + 1)
//from bottom left corner
for y from height - 1 to 0
for x 0 to width - 1
distances[x, y] = min(distances[x, y], distances[x - 1, y] + 1, distances[x, y + 1] + 1)
//from bottom rightcorner
for y from height - 1 to 0
for x width - 1 to 0
distances[x, y] = min(distances[x, y], distances[x + 1, y] + 1, distances[x, y + 1] + 1)
在那四次通过之后,您具有到distances
数组中最近的空闲块的块距。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句