Показать сообщение отдельно
Старый 14.02.2015, 01:41   #29
WISHMASTER35
Бывалый
 
Аватар для WISHMASTER35
 
Регистрация: 21.12.2008
Адрес: UA
Сообщений: 878
Написано 105 полезных сообщений
(для 357 пользователей)
Ответ: Еще один Minecraft на юнити

Другие методы вычисления освещения.
1)
Можно сгруппировать источники света в боксы. Тогда чтобы вычислить свет в любой ячейки, достаточно будет вычислить расстояние до ближайшего LightBox.
    private static int ComputeLight(Map map, int x, int y) {
        int light = 0;
        for(VoxelBox box : map.lightBoxes) {
            int tLight = ComputeLight(box, x, y);
            light = Math.max(light, tLight);
        }
        return light;
    }
    
    private static int ComputeLight(VoxelBox box, int x, int y) {
        int closestX = x, closestY = y; 
        closestX = Math.max(closestX, box.x);
        closestX = Math.min(closestX, box.x+box.w-1);
        
        closestY = Math.max(closestY, box.y);
        closestY = Math.min(closestY, box.y+box.h-1);
        
        int dx = Math.abs( x - closestX );
        int dy = Math.abs( y - closestY );
        return Map.MAX_LIGHT - (dx + dy);
    }




Но это без учета непрозрачных блоков.
А вот как учитывать непрозрачные блоки, не представляю.
Возможно, в каждом LightBox'е хранить расстояние до которого он досвечивает. А там, где свет заворачивает, создавать вторичные источники света.
Т.е. типа разрезать этот желтый ромб, на несколько простых фигур, точно описывающих форму света.
Получаются такие себе объемы распространения света.
+ расчет этих объемов для каждого чанка - независим и может быть распараллелен. Т.е. 1 thread == 1 chunk. А может и несколько потоков на чанк.
+ расчет света в ячейках, тоже может быть параллелен.
+ для хранения этих объемов должно требоваться намного меньше памяти.
На LightChunk(32x32x32) нужно 32кб. Если использовать 4 бита на ячейку света, то 16 кб.
Для хранения LightBox'а нужно: (byte x,y,z, xSize, ySize. zSize, light) == 7 байт. На 32кб можно хранить 4681 таких LightBox'ов.
Можно сжать, если на координату и размер использовать 5 бит, а на свет 4 бита, то нужно 34 бита == 5 байт. Может можно еще как-то сжать.

Никто не знает быстрого алгоритма для объединения одинаковых ячеек в один бокс? Мой алгоритм очень примитивный.
        ArrayList<VoxelBox> boxes = new ArrayList();

        for (int y = 0; y < map.height; y++) {
            for (int x = 0; x < map.width; x++) {
                int light = map.getLight(x, y);

                if (light == Map.MAX_LIGHT) {
                    VoxelBox box = new VoxelBox(x, y, 1, 1);
                    while (x++ < map.width && map.getLight(x, y) == Map.MAX_LIGHT) {
                        box.w++;
                    }
                    boxes.add(box);
                }
            }
        }

        for (int i = 0; i < boxes.size(); i++) {
            VoxelBox box = boxes.get(i);
            for (int j = i + 1; j < boxes.size();) {
                VoxelBox tBox = boxes.get(j);
                if (box.x == tBox.x && box.w == tBox.w && box.y + box.h == tBox.y) {
                    box.h += tBox.h;
                    boxes.remove(j);
                } else {
                    j++;
                }
            }
        }


2)
Есть идея разбить пространство на такие боксы, чтобы внутри бокса, между любыми двумя ячейками, не было преград.
Имея список LightPoint'ов внутри бокса, вычислить освещение для любой ячейки бокса будет очень просто.
Но есть вопрос, как передать освещение из одного бокса в другой.
Можно в light list соседних боксов добавлять вторичные источники света.
Или искать свет и в соседних боксах.
Но пока я даже не представляю как вычислить такие боксы.

3
Хорошо бы перенести освещение из вершин в постобработку.
Тогда надо решить два вопроса:
* как хранить освещение на видюхе.
Обычно освещение хранится в octree. Я предпочел бы Grid of Chunks.
Grid - 3д массив чанков.
Chunk - или просто 3д массив ячеек света, или octree, или список только ячеек, которые граничат с геометрией, или другой сжатый формат.
* как наложить освещение в пост обработке. Или может быть сразу во время рендеринга освещать. (deferred \ forward)
С этим должно быть проще. Только вероятно надо будет в каком-то буфере хранить тип и позицию блока.
Не знаю возможно ли такое создать на DX11 и юнити сделать.

4
А может было бы проще сделать физически корректное Global Illumination, в котором свет отражается, а не заполняет пустые ячейки.
Voxel Cone Tracing вычисляется свет для каждой группы пикселей 4x4, и каждый кадр. На моем железе это выдает несколько фпс.
Думаю можно оптимизировать для MineCraft. Для этого нужно:
* вычислять свет для блоков, а не пикселей (На чанк таких блоков обычно ~2тыс).
* вычислять только после изменения геометрии и сохранять. А не каждый кадр.
К сожалению VCT дает утечки света, но если бы удалось его реализовать без тормозов, то все равно было бы круто.

Или сферические гармоники использовать, но я пока точно не понимаю как они работают.

Если не получится улучшить освещение, то лучше его вообще удалю.
Вроде все идеи описал. Не знаю осилит ли кто-то прочитать эти посты))
Может у кого-то есть еще идеи по освещению?
Миниатюры
Нажмите на изображение для увеличения
Название: LightBox 1.png
Просмотров: 1375
Размер:	30.3 Кб
ID:	21506  Нажмите на изображение для увеличения
Название: LightBox 2.png
Просмотров: 1320
Размер:	12.0 Кб
ID:	21507  
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
impersonalis (14.02.2015)