| Гость |
Вы не зарегистрированны? Нажмите здесь для регистрации.
Забыли пароль? Запросите новый здесь.
|
|
| Сейчас на сайте |
Гостей: 3
На сайте нет зарегистрированных пользователей
Пользователей: 1,795
новичок: BlitzID
|
|
|
| Обсуждение «Рендеринг тайловой карты» |

|
| Опубликовано 04.03.2014 06:27 (12 лет назад) # |
Здравствуйте. В игрострое я новичок, вот пытаюсь разобраться как в играх рендерится 2D тайловая карта игрового уровня. Применительно к OpenGL.
С ходу в голову пришло два варианта:
1. Создается плоскость в размер экрана и массив текстурных координат. Берем координаты из массива и натягиваем тайлы на плоскость.
2. Сдвигаем 0 системы координат в левый нижний/верхний угол (ортографическая проекция) и рисуем сетку QUADов, на которые натягиваем текстуры.
Вопрос, собственно, какой подход лучше, может вообще какой-то третий или четвертый до которого я еще не додумался? И где будет меньше проблем с прокруткой карты на экране? |
|
|
|

|
| Опубликовано 04.03.2014 09:13 (12 лет назад) # |
я обычно делаю так.... массив[0..MapWidth,0..MapHeight], значения массива - тип тайла(или одно из значений записи, если нужна еще карта проходимости и прочая инфа), ну а дальше просто отображаешь квады, используя положение в массиве как координаты, а текстурные координаты берешь исходя из значения массива либо для каждого тайла отдельную текстуру.
Если нужно прокрутить карту, то просто сдвигаешь камеру. |
|
|
|

|
| Опубликовано 04.03.2014 09:28 (12 лет назад) # |
| То есть получается выводим целиком локацию, полагаясь на плоскости отсечения а потом елозим по ней камерой?
редакция от IvanN, 04.03.2014 11:22 |
|
|
|
Инженер‑космогоник

|
| Опубликовано 04.03.2014 18:34 (12 лет назад) # |
IvanN
Первый вариант не понял совершенно, как простыми средствами можно натянуть на одну плоскость(полигон?) несколько тайлов с разными текстурными координатами? Только если шейдерами.
Предложенный CoderInTank вариант очень простой, и для 2д вполне годный.
База всегда примерно одна:
У тебя есть массив тайлов(каждый элемент - либо номер тайла в сете либо 2 текстурные координаты сдвига). При каждой отрисовке просто рисуется куча квадов стык в стык с динамически вычисляемыми из массива тайлов текстурными координатами.
Я обычно двигал камеру не трансформом, а делал чуть сложнее - заводил 2 координаты сдвига и при отрисовке каждого квада вычислял его координату, а потом отнимал сдвиг. Координаты сдвига и есть камера. Правда в более поздних реализациях Я сделал сразу управление матрицами камеры, так что получилось одно и то же.
Сдвигать камеру в ортопроекцию с основанием от угла можно, но совершенно не обязательно, для многих случаев центральное расположение куда удобнее.
Насчет оптимизаций можно предложить 2 основных.
Первая - сделать сразу массивы вершин, текстур, цветов и т.д. и рисовать все поле тайлов за раз. Будет быстрее и через glBegin / glEnd и если рисовать сразу буфферами. Подходит больше для неизменяемых тайлов, для персонажей и прочего надо координаты менять.
Вторая - самому считать видимое количество тайлов и отрисовывать поле не от начала до конца, а только то, что видно.
примерно так:
MapXB:= trunc(Camera.X / TILE_SIZE); // сдвиги камеры от начала
MapYB:= trunc(Camera.Y / TILE_SIZE);
MapXE:= MapXB + trunc(Window.Width / TILE_SIZE) + 1; // сдвиг к концу
MapYE:= MapYB + trunc(Window.Height/ TILE_SIZE) + 1;
// проверки на выход за границы массива
if MapXB < 0 then MapXB:= 0;
if MapYB < 0 then MapYB:= 0;
if MapXE > MAP_X then MapXE:= MAP_X;
if MapYE > MAP_Y then MapYE:= MAP_Y;
ViewLeft:= -Camera.X;
ViewTop := -Camera.Y;
// отрисовка только видимой области, от начала до конца будет от 0 до MAP_X / MAP_Y
for i:= MapXB to MapXE do
for j:= MapYB to MapYE do
begin
Resources.TileTexture.Draw(ViewLeft + i * 64, ViewTop + j * 64, Color, Map[i,j].Tile);
end;
Здесь сдвиги находятся для обычных оконных координат, если камера рисует от центра, то MapXB, MapYB, MapXE, MapYE находятся чуть по другому:
MapXB:= trunc(Camera.X / TILE_SIZE) - X_TILE_ON_SCREEN / 2;
MapYB:= trunc(Camera.Y / TILE_SIZE) - Y_TILE_ON_SCREEN / 2;
MapXE:= trunc(Camera.X / TILE_SIZE) + X_TILE_ON_SCREEN / 2;
MapYE:= trunc(Camera.Y / TILE_SIZE) + Y_TILE_ON_SCREEN / 2; |
|
|
|

|
| Опубликовано 04.03.2014 20:13 (12 лет назад) # |
Mefistofel
Спасибо за развернутый ответ.
Я обычно двигал камеру не трансформом, а делал чуть сложнее - заводил 2 координаты сдвига и при отрисовке каждого квада вычислял его координату, а потом отнимал сдвиг.
Пошевелив полдня своей извилиной я примерно к этому и пришел. Вы подтвердили мои подозрения. Спасибо за пример кода. Мне так проще разбираться.
Первая - сделать сразу массивы вершин, текстур, цветов и т.д. и рисовать все поле тайлов за раз. Будет быстрее и через glBegin / glEnd и если рисовать сразу буфферами. Подходит больше для неизменяемых тайлов, для персонажей и прочего надо координаты менять.
Вторая - самому считать видимое количество тайлов и отрисовывать поле не от начала до конца, а только то, что видно.
Вот ради второй, собственно, я и задавал вопрос. На glBegin/Еnd я даже не смотрел, в стандарте они deprecated.
Подскажите мне еще одну вещь, пожалуйста:
я правильно понял, при вызове glBind* выполняется копирование данных и память занятую массивами можно освободить? |
|
|
|
Инженер‑космогоник

|
| Опубликовано 04.03.2014 21:48 (12 лет назад) # |
Никогда так не делал(оперативки всегда больше, чем видеопамяти, и проще при необходимости обновлять локальные массивы, поэтому храню. Да и вообще, на спичках экономить), но должно быть именно так.
Я так понимаю, уже с 3-го ОГЛ выпилены все иные способы передачи вершинных данных, кроме как бинд массивов в видеопамять.
Кстати - если дело касается только тайлов поверхности, то даже для сравнительно больших уровней(100*100) будет дешевле по производительности вывести все поле одним мешем, чем использовать оптимизацию процессора.
Для еще больших уровней оптимизацию применяют опять же не для отдельных квадов, а для кусков, к примеру 20*20 |
|
|
|

|
| Опубликовано 05.03.2014 07:21 (12 лет назад) # |
| Ну текстура с тайлами/спрайтами скушает не так уж мало оперативы, особенно если поддерживать несколько разрешений экрана. Я в основном про это. И теоритически файл можно вообще на загружать в буфер оперативы, можно "сказать" процессору что "вот этот файл" есть страница памяти, передать на нужный его участок указатель а потом его закрыть. Для мобильных устройств это может дать нехилый прирост и сэкономить память. Вроде как есть расширения которые позволяют передавать сжатые текстуры? Но все это при условии что Bind действительно выполняет копирование. |
|
|
|

|
| Опубликовано 05.03.2014 07:36 (12 лет назад) # |
Не на чем проверить, но загруженную в память текстуру/буфер можно удалять, по крайней мере я так делаю. Только не после bind, а после непосредственной загрузки. glTexImage2D, glBufferData и прочего.
С opengl es не знаю, но вряд ли что-то иначе. |
|
|
|
Инженер‑космогоник

|
| Опубликовано 05.03.2014 13:44 (12 лет назад) # |
Mefistofel
Ах, речь про текстуры.
Да, можно сносить. |
|
|
|
Перейти на форум:
|
|
|
|
| Конкурсы |
|
Открытые конкурсы:
|
|
|