Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Проекты > Проекты на Unity

Ответ
 
Опции темы
Старый 04.04.2013, 20:29   #16
m_512
Элита
 
Аватар для m_512
 
Регистрация: 17.04.2007
Сообщений: 1,950
Написано 1,506 полезных сообщений
(для 7,979 пользователей)
Ответ: Еще один Minecraft на юнити

Сообщение от WISHMASTER35 Посмотреть сообщение
Думаю даже если создать что-то лучше, то все равно будешь лишь клоном.
Попробуй сделать генерацию мягкой поверхности, по типу как делают геометрию воды на основе сфер.

Вот это будет что-то кардинально новое.

Идея с шутером мне нравится)
Миниатюры
Нажмите на изображение для увеличения
Название: soft.jpg
Просмотров: 1315
Размер:	125.1 Кб
ID:	19000  
(Offline)
 
Ответить с цитированием
Эти 2 пользователя(ей) сказали Спасибо m_512 за это полезное сообщение:
Igor (06.07.2013), LLI.T.A.L.K.E.R. (14.04.2013)
Старый 14.04.2013, 14:04   #17
WISHMASTER35
Бывалый
 
Аватар для WISHMASTER35
 
Регистрация: 21.12.2008
Адрес: UA
Сообщений: 878
Написано 105 полезных сообщений
(для 357 пользователей)
Ответ: Еще один Minecraft на юнити

m_512, это называется marching cubes. Хотелось бы сделать, но как не знаю. Когда-то видел статью на русском, но теперь не могу найти.
(Offline)
 
Ответить с цитированием
Старый 19.04.2013, 01:03   #18
m_512
Элита
 
Аватар для m_512
 
Регистрация: 17.04.2007
Сообщений: 1,950
Написано 1,506 полезных сообщений
(для 7,979 пользователей)
Ответ: Еще один Minecraft на юнити

Можно сделать имитацию, просто заготовить геометрии мягких переходов и подставлять их.
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Phantom (29.06.2013)
Старый 28.06.2013, 23:52   #19
CPAHb
AnyKey`щик
 
Регистрация: 28.06.2013
Сообщений: 1
Написано 0 полезных сообщений
(для 0 пользователей)
Ответ: Еще один Minecraft на юнити

Не мог бы сделать удаление воды как обычного блока, ибо получается не очень с водой терминатором.
И взорвать THT никак)
А так норм
(Offline)
 
Ответить с цитированием
Старый 02.06.2014, 23:00   #20
WISHMASTER35
Бывалый
 
Аватар для WISHMASTER35
 
Регистрация: 21.12.2008
Адрес: UA
Сообщений: 878
Написано 105 полезных сообщений
(для 357 пользователей)
Ответ: Еще один Minecraft на юнити

V9.
Не знаю, что будет в Unity 5, но пока я пришел к выводу, что unity плохо подходит для таких проектов.
Нельзя читать\записывать в RenderTexture.
Нельзя создавать меш со своим набором данных. Например сейчас на позицию вершины уходит три float, а достаточно было бы трех байтов. Так же и с нормалью, освещением и uv.



Сглаживание блоков так и не пробовал делать, потому что не представляю как садить на такие блоки всякую траву, заборы и другое. Может получится, что трава весит в воздухе над сглаженным блоком земли.

Освещение для MineCraft это проблема. При его изменении, необходимо перестроить все чанки, у которых изменилось освещение.
Хорошо было бы хранить освещение не в меше, а в отдельной 3д текстуре. И в вершинном шейдере брать освещение. Но тогда размер текстуры будет под 1024x1024x256.
Возможно можно создать octree или тайловую текстуру.

Последний раз редактировалось impersonalis, 02.06.2014 в 23:21. Причина: исправил неправильное содержимое тега YOUTUBE
(Offline)
 
Ответить с цитированием
Эти 11 пользователя(ей) сказали Спасибо WISHMASTER35 за это полезное сообщение:
ABTOMAT (04.06.2014), Антихрист (20.07.2014), Arton (02.06.2014), DStalk (03.06.2014), Igor (06.06.2014), impersonalis (02.06.2014), LLI.T.A.L.K.E.R. (03.06.2014), pax (03.06.2014), St_AnGer (06.06.2014), tirarex (03.06.2014), Жека (03.06.2014)
Старый 02.06.2014, 23:22   #21
Arton
Быдлокодер
 
Аватар для Arton
 
Регистрация: 05.07.2009
Адрес: Проспит
Сообщений: 5,019
Написано 2,312 полезных сообщений
(для 5,349 пользователей)
Ответ: Еще один Minecraft на юнити

Круто выглядит! Демка будет?

В тег надо было запихать только эту часть "youtube.com/watch?v=LfJYNYPKi_w"
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
WISHMASTER35 (03.06.2014)
Старый 03.06.2014, 18:39   #22
WISHMASTER35
Бывалый
 
Аватар для WISHMASTER35
 
Регистрация: 21.12.2008
Адрес: UA
Сообщений: 878
Написано 105 полезных сообщений
(для 357 пользователей)
Ответ: Еще один Minecraft на юнити

Ссылки на демки в описании видео.
https://dl.dropboxusercontent.com/u/...nd%209.2.1.rar

Круто, но если бы не ограничения юнити, то было бы намного круче.
Хоть на с++ начинай писать плагины. Хотя тогда веб плеер сразу отпадет.
Да и черт знает как на с++ создать меш со своими данными и рендерить его.
(Offline)
 
Ответить с цитированием
Эти 3 пользователя(ей) сказали Спасибо WISHMASTER35 за это полезное сообщение:
ABTOMAT (04.06.2014), Arton (06.06.2014), LLI.T.A.L.K.E.R. (03.06.2014)
Старый 06.06.2014, 02:29   #23
Igor
Мастер
 
Аватар для Igor
 
Регистрация: 03.05.2010
Адрес: Подмосковье
Сообщений: 1,218
Написано 438 полезных сообщений
(для 790 пользователей)
Ответ: Еще один Minecraft на юнити

Выглядит явно симпатичнее оригинала. Это офигенно) Может, делать не совсем майнкрафт, а с какой-нибудь фичей?
Например, сделать игру про колонизаторов планет. Десантируются в определённую точку мира один или несколько игроков, строят базу, обороняют периметр от набегающей живности типа динозавров и добывают полезные ископаемые. Инвентарь и прочее крафтить в 3д принтере, дать игроку возможность создавать роботов и управлять ими, сидя на базе. Ещё добавить всякие солнечные батареи, лазеры, турельки, ретрансляторы сигнала (для управления роботами), а в конце надо будет собрать космический корабль и улететь.

P.S. Могу попробовать написать сервер на java, играть по сети на порядок интереснее.
__________________
О¯О ¡¡¡ʁɔvʎнdǝʚǝdǝu dиW
(Offline)
 
Ответить с цитированием
Эти 2 пользователя(ей) сказали Спасибо Igor за это полезное сообщение:
impersonalis (06.06.2014), LLI.T.A.L.K.E.R. (06.06.2014)
Старый 08.06.2014, 18:37   #24
WISHMASTER35
Бывалый
 
Аватар для WISHMASTER35
 
Регистрация: 21.12.2008
Адрес: UA
Сообщений: 878
Написано 105 полезных сообщений
(для 357 пользователей)
Ответ: Еще один Minecraft на юнити

Igor, оригинал сам по себе довольно простой. А вот с модами MineCraft бывает очень красивый.
Я насобирал текстуры из самого MineCraft, Worms3D, Terasology и др. А вот генератор мира у меня все еще простой.

Ты описываешь какую-то стратегию? Я если и сделаю из этого игру, то просто сетевой шутер. Но наверно я никогда не дойду до этого.
Сейчас у меня все еще есть идеи по оптимизации рендера, но времени нет.
(Offline)
 
Ответить с цитированием
Старый 20.07.2014, 18:09   #25
WISHMASTER35
Бывалый
 
Аватар для WISHMASTER35
 
Регистрация: 21.12.2008
Адрес: UA
Сообщений: 878
Написано 105 полезных сообщений
(для 357 пользователей)
Ответ: Еще один Minecraft на юнити

Производительность Mono - дело весьма странное.
Порой, чтобы функция работала в 2 раза быстрее, ее нужно разбить на несколько функций.

Наверно самым тормозным местом является функция получения соседних блоков. Переводить мировые координаты в координаты grid и local, а потом еще в индексы для массива - дело медленное. Поэтому написал такую весьма запутанную функцию.
    public DataBlock GetAdjacentBlock(int localIndex, CubeSide side) {
        const int LOCAL_MASK_X = Chunk.X_MASK; // 001
        const int LOCAL_MASK_Y = Chunk.Y_MASK << Chunk.X_BITS; // 010
        const int LOCAL_MASK_Z = Chunk.Z_MASK << Chunk.Y_BITS << Chunk.X_BITS; // 100
        // zzzzzyyyyyxxxxx

        const int CHUNK_DELTA_X = 1;
        const int CHUNK_DELTA_Y = ChunkGrid.X_SIZE;
        const int CHUNK_DELTA_Z = (ChunkGrid.X_SIZE * ChunkGrid.Y_SIZE);

        const int LOCAL_DELTA_X = Chunk.X_SIZE - 1;
        const int LOCAL_DELTA_Y = Chunk.X_SIZE * (Chunk.Y_SIZE - 1);
        const int LOCAL_DELTA_Z = Chunk.X_SIZE * Chunk.Y_SIZE * (Chunk.Z_SIZE - 1);

        switch(side) {
            case CubeSide.Front: // z+
                if((localIndex | LOCAL_MASK_Z) == localIndex) { // index == max
                    if(position.z == ChunkGrid.Z_MAX) return default( DataBlock );

                    int chunkIndex = this.chunkIndex + CHUNK_DELTA_Z;
                    localIndex -= LOCAL_DELTA_Z;
                    return Map.instance.GetBlock(chunkIndex, localIndex);
                } else { 
                    return blocks[ localIndex + (Chunk.X_SIZE * Chunk.Y_SIZE) ];
                }

            case CubeSide.Back: // z-
                if((localIndex & ~LOCAL_MASK_Z) == localIndex) { // index == min
                    if(position.z == 0) return default( DataBlock );

                    int chunkIndex = this.chunkIndex - CHUNK_DELTA_Z;
                    localIndex += LOCAL_DELTA_Z;
                    return Map.instance.GetBlock( chunkIndex, localIndex );
                } else {
                    return blocks[localIndex - (Chunk.X_SIZE * Chunk.Y_SIZE)];
                }

            case CubeSide.Right: // x+
                if((localIndex | LOCAL_MASK_X) == localIndex) { // index == max
                    if(position.x == ChunkGrid.X_MAX) return default( DataBlock );

                    int chunkIndex = this.chunkIndex + CHUNK_DELTA_X;
                    localIndex -= LOCAL_DELTA_X;
                    return Map.instance.GetBlock( chunkIndex, localIndex );
                } else {
                    return blocks[localIndex + 1];
                }

            case CubeSide.Left: // x-
                if((localIndex & ~LOCAL_MASK_X) == localIndex) { // index == min
                    if(position.x == 0) return default( DataBlock );

                    int chunkIndex = this.chunkIndex - CHUNK_DELTA_X;
                    localIndex += LOCAL_DELTA_X;
                    return Map.instance.GetBlock( chunkIndex, localIndex );
                } else {
                    return blocks[localIndex - 1];
                }

            case CubeSide.Top: // y+
                if((localIndex | LOCAL_MASK_Y) == localIndex) { // index == max
                    if(position.y == ChunkGrid.Y_MAX) return default( DataBlock );

                    int chunkIndex = this.chunkIndex + CHUNK_DELTA_Y;
                    localIndex -= LOCAL_DELTA_Y;
                    return Map.instance.GetBlock( chunkIndex, localIndex );
                } else {
                    return blocks[localIndex + Chunk.X_SIZE];
                }

            case CubeSide.Bottom: // y-
                if((localIndex & ~LOCAL_MASK_Y) == localIndex) { // index == min
                    if(position.y == 0) return default( DataBlock );

                    int chunkIndex = this.chunkIndex - CHUNK_DELTA_Y;
                    localIndex += LOCAL_DELTA_Y;
                    return Map.instance.GetBlock( chunkIndex, localIndex );
                } else {
                    return blocks[localIndex - Chunk.X_SIZE];
                }
        }

        return default(DataBlock);
    }

Теперь время снизилось с ~20 сек. до ~7 сек.
Если разделить это все на 7 функций:
    public DataBlock GetAdjacentBlock(int localIndex, CubeSide side) {
        switch(side) {
            case CubeSide.Front: return GetFrontBlock( localIndex );
            case CubeSide.Back: return GetBackBlock( localIndex );

            case CubeSide.Right: return GetRightBlock( localIndex );
            case CubeSide.Left: return GetLeftBlock( localIndex );

            case CubeSide.Top: return GetTopBlock( localIndex );
            case CubeSide.Bottom: return GetBottomBlock( localIndex );
        }
        return default(DataBlock);
    }

Теперь скорость ~4.9 сек. И это еще тратиться некоторое время на еще один вызов функции.

А если напрямую вызывать эти функции:

            DataBlock b1 = chunk.GetFrontBlock( i );
            DataBlock b2 = chunk.GetBackBlock( i );

            DataBlock b3 = chunk.GetRightBlock( i );
            DataBlock b4 = chunk.GetLeftBlock( i );

            DataBlock b5 = chunk.GetTopBlock( i );
            DataBlock b6 = chunk.GetBottomBlock( i );

Тогда вообще ~2.9 сек.
(Offline)
 
Ответить с цитированием
Эти 6 пользователя(ей) сказали Спасибо WISHMASTER35 за это полезное сообщение:
Igor (24.07.2014), impersonalis (20.07.2014), Mr_F_ (20.07.2014), pax (21.07.2014), Randomize (21.07.2014), St_AnGer (20.07.2014)
Старый 13.02.2015, 22:32   #26
WISHMASTER35
Бывалый
 
Аватар для WISHMASTER35
 
Регистрация: 21.12.2008
Адрес: UA
Сообщений: 878
Написано 105 полезных сообщений
(для 357 пользователей)
Ответ: Еще один Minecraft на юнити

Давно не выпускал новых версий. Уже не могу особо ничего сделать. Есть идеи, которые пока не знаю как реализовать или может быть их вообще не реализовать. Напишу их здесь.
1)
Хранить террейн, деревья и др в разных структурах.
+ Это позволило бы одним кликом добавлять\удалять целые объекты.
+ Вероятно сэкономило бы много памяти, т.к. хранить byte данных для блоков террейна или деревьев не нужно. Этот байт нужен лишь, блокам, которые имеют направление или для двери, которая имеет состояние открыто\закрыто.
+ Т.к. обычно блоков террейна меньше 15, то на блок можно выделить 4 бита, а для блока дерева вообще 2 бита.
- Преимущества есть, но недостатки тоже имеются. Нельзя будет просто и быстро получить блок в рандомной позиции. Это как минимум делает невозможным текущие освещение.
2)
Объединять одинаковые фейсы.
+ Было бы очень здорово значительно уменьшить количество полигонов.
- Из-за использования атласов, вероятно это невозможно. А Texture2DArray в юнити пока недоступен.
Из-за вершинного освещения можно будет соединить далеко не все фейсы.
- Соединить фейсы по одной оси - легко. Достаточно сравнивать текущий фейс с предыдущим. А как соединить фейсы по двум осям - я слабо представляю. И вопрос как это повлияет на скорость создания меша.
3)
Компактный формат вершин меша.
Сейчас только на позицию вершины выделяется 3 float == 12 байт. Хотя чтобы задать позицию достаточно 2х байт.
С остальным так же.
Если использовать геометрический шейдер, то можно хранить лишь одну координату, а из нее восстанавливать траву, фейс или целый бокс.
Это можно сделать используя ComputeBuffer и Graphics.DrawProcedural.
4)
Сжатие чанков.
Если забить на скорость рандомного доступа к блоку, то остаются такие требования:
* Быстрая итерация по чанку.
* Быстрый доступ к соседним блокам.
Первое легко выполняется в RLE и наверно в Octree. А вот со вторым выходит проблема. Но на самом деле необязательно иметь доступ к соседнему блоку. Достаточно знать заслоняет ли он фейс текущего блока или нет.
Т.е. для непрозрачных блоков нужно знать, соседний блок прозрачный или нет.
А для прозрачных блоков нужно знать, соседний блок такого же типа или нет. Ведь между двумя блоками воды не создаются фейсы.
Для блока забора и подобное тоже надо знать некую информацию о соседях.
В общем эту информацию можно уместить в 6 бит и вычислить до сжатия чанка.
+ экономия памяти.
+ Если использовать Octree, то возможно сделать LOD'ы.
+ итерация по чанку и создание меша может стать быстрее.
- но на предрасчет информации о соседях - нужно время. Для изменения блока, необходимо изменить и соседние блоки. Сжатый чанк усложняет изменение блока. В результате весь профит от быстрой итерации и создания меша пропадет.
5)
Освещение.
Это фейковое global illumination создает много!
- хранение света в вершинах меша.
- это вынуждает пересоздавать меш чанка, если свет в нем изменился. А за кадр освещение может изменится во многих чанках.
- если объединять одинаковые фейсы, то вершинное освещение сильно уменьшить количество объединенных фейсов.
- чтобы свет для всей карты считался максимально быстро, нужно все источники света добавить в одну FIFO очередь. А затем постепенно рассеивать свет из этой очереди. Для карты 512x512 размер такой очереди получается ~100тыс. И распараллелить этот алгоритм нельзя.
- необходимость быстрого рандомного доступа к блокам.
- потребление памяти. Прямой свет хранится просто в 2д массиве. А рассеянный свет хранится, как и блоки, в 3д массивах(чанках). Хотелось бы более экономную структуру для света.
+ для карты 512x512 свет рассчитывается за 2.5 сек. И это в редакторе Unity. Довольно хороший результат.
Более подробно об освещении в следующих постах.

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

Обычный алгоритм расчета освещения(2д версия):
list это FIFO очередь. 
Важно, чтобы очередь была FIFO. 
Тогда сначала будят рассеиваться все первичные источники света, 
затем вторичные, затем третичные и тд.
........................
        while( !list.isEmpty() ) {
            LightPoint pnt = list.poll();
            int x = pnt.x;
            int y = pnt.y;
            int nextLight = pnt.light - 1;
            
            if (pnt.dir != Dir.RIGHT || pnt.dir == Dir.All) { // spread to left
                setMaxLight(map, x-1, y, nextLight, Dir.LEFT);
            }
            if (pnt.dir != Dir.LEFT || pnt.dir == Dir.All) { // spread to right
                setMaxLight(map, x+1, y, nextLight, Dir.RIGHT);
            }
            if (pnt.dir != Dir.UP || pnt.dir == Dir.All) { // spread to down
                setMaxLight(map, x, y-1, nextLight, Dir.DOWN);
            }
            if (pnt.dir != Dir.DOWN || pnt.dir == Dir.All) { // spread to up
                setMaxLight(map, x, y+1, nextLight, Dir.UP);
            }
            
        }
.........................................

    private static void setMaxLight(Map map,int x, int y, int light, Dir dir) {
        if (map.setMaxLight(x, y, light)) {
            addLight(x, y, light, dir);
        }
    }
    
    private static void addLight(int x, int y, int light, Dir dir) {
        list.add( new LightPoint(x, y, light, dir) );
    }

В общем суть такова, что каждая LightPoint из очереди пытается осветить все соседние ячейки. С учетом Dir, все, кроме одной.
Если осветить соседнюю ячейку получилось, то ее координата добавляется в очередь.
Миниатюры
Нажмите на изображение для увеличения
Название: 2.png
Просмотров: 1019
Размер:	17.0 Кб
ID:	21501  

Последний раз редактировалось WISHMASTER35, 14.02.2015 в 02:26.
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
impersonalis (13.02.2015)
Старый 13.02.2015, 23:05   #28
WISHMASTER35
Бывалый
 
Аватар для WISHMASTER35
 
Регистрация: 21.12.2008
Адрес: UA
Сообщений: 878
Написано 105 полезных сообщений
(для 357 пользователей)
Ответ: Еще один Minecraft на юнити

Сжатие света.
LightChunk можно хорошо сжать, если хранить только максимальные точки света(maxLightPoint) в каждом столбце. Тогда, чтобы вычислить свет в любой ячейки, надо найти в столбце ближайшую maxLightPoint. Только надо учитывать, что между текущей ячейкой и maxLightPoint может быть непрозрачный блок.
Или в maxLightPoint хранить до куда она достает. Т.е. получится такая структура градиента {y1, light_1, y2, light_2}. Тогда надо просто найти градиент, в которую попадает наша ячейка.
Миниатюры
Нажмите на изображение для увеличения
Название: 1_ with max lights.png
Просмотров: 1023
Размер:	12.7 Кб
ID:	21502  Нажмите на изображение для увеличения
Название: 2_ with max lights.png
Просмотров: 950
Размер:	17.9 Кб
ID:	21503  

Последний раз редактировалось WISHMASTER35, 14.02.2015 в 02:24.
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
impersonalis (13.02.2015)
Старый 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
Просмотров: 1345
Размер:	30.3 Кб
ID:	21506  Нажмите на изображение для увеличения
Название: LightBox 2.png
Просмотров: 1283
Размер:	12.0 Кб
ID:	21507  
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
impersonalis (14.02.2015)
Старый 15.02.2015, 20:47   #30
WISHMASTER35
Бывалый
 
Аватар для WISHMASTER35
 
Регистрация: 21.12.2008
Адрес: UA
Сообщений: 878
Написано 105 полезных сообщений
(для 357 пользователей)
Ответ: Еще один Minecraft на юнити

2)
Есть идея разбить пространство на такие боксы, чтобы внутри бокса, между любыми двумя ячейками, не было преград.
Вот что я имел ввиду.
Внутри красного бокса все прозрачные ячейки имеют прямой доступ ко всем другим прозрачным ячейкам.
А синие точки это ячейки, которые не имеют прямого доступа друг к другу.
Но не представляю как разбить пространство на такие боксы.
Миниатюры
Нажмите на изображение для увеличения
Название: image 5469276089839570469.png
Просмотров: 1061
Размер:	8.4 Кб
ID:	21508  
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 19:44.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com