VBO с несколькими текстурами - PullRequest
       30

VBO с несколькими текстурами

3 голосов
/ 06 сентября 2011

Можете ли вы визуализировать VBO четырехугольников с различной текстурой? Теперь я читаю о сортировке по текстуре или по текстурным стеклам, но это все еще не отвечает на мой вопрос. Я работаю над 2D-игрой. Теперь мои анимированные спрайты будут иметь атлас текстуры для своих фреймов, а также карту нормалей, и все они будут использовать один и тот же VBO (если это возможно). Таким образом, у каждого спрайта будет свой атлас (некоторые анимации могут иметь много кадров и поз, которые могут заполнить текстуру 4096 * 4096). Так возможно ли это? Да или нет. Если нет, то эффективно ли иметь индексированный VBO для каждого спрайта со всеми координатами текстуры для всех его кадров анимации и посылать только 4 индекса в каждом кадре (для одного кадра анимации) и изменять текстуру для каждого VBO? РЕДАКТИРОВАТЬ: также некоторые из них могут двигаться (очевидно), а некоторые нет.


Подумав немного, я понял, что использование памяти также является проблемой. Эти текстурные очки съедят много памяти. Текстура RGBA 4096 * 4096 занимает 64 МБ, что очень много (и это без карты нормалей, которая бы удваивала использование). И я не думаю, что смог бы втиснуть столько анимаций в один атлас. В старых играх, таких как Diablo или Infinity Engine, требовалось всего несколько мегабайт VRAM, и они выглядели очень хорошо.

Ответы [ 2 ]

6 голосов
/ 06 сентября 2011

Просто чтобы уточнить, VBO может содержать текстурные координаты, но не знает, какие текстуры будут применены к нему.

Оставьте VBO независимым от текстур и вычислите текстурные координаты в фрагментном / пиксельном шейдерев соответствии с анимацией / индексом кадра.Предполагая, что у вас есть квадроциклы в вашем VBO, вы устанавливаете координаты текстуры, чтобы они просто отображали всю текстуру.Затем в своем шейдере вы масштабируете и переводите координаты текстуры, чтобы отобразить один кадр на текстурном атласе.Затем вы можете задать индекс анимации, количество кадров в атласе и т. Д. Как единые значения для шейдера.

Редактировать (для дальнейшего уточнения):

Текстуракоординаты для квада

(0,1)          (1,1)
  x-------------x
  |             |
  |             |
  |             |
  |             |
  |             |
  x-------------x
(0,0)          (1,0)

Это соответствует отображению всей текстуры в этот один квад.

Допустим, ваша текстура удобно разбита на 16x16 "кадров", расположенных в столбце-строкезакажите в вашем текстурном атласе.Следовательно, размер одного кадра составляет 1/16 в текстурных координатах в u и v соответственно.Это ваше движущееся окно.Теперь в вашем шейдере вы передаете номер «кадра» для вашей анимации, а координата текстуры для каждой вершины в вашем квадре - это ее координата текстуры, масштабированная на 16, а затем переведенная в кадр (целое число на основе 0):

float scale = 0.0625   // 1/16.
texCoord *= scale; 
texCoord += float2(scale*frame%16, scale*(frame/16))

Теперь я записываю это здесь изо всех сил, чтобы могли быть незначительные ошибки.также этот код предполагает, что texCoord является текстурной координатой фрагмента на кваде.Обратите внимание, что вычисление 1/16 один раз намного дешевле, чем повторное деление на 16, я могу добавить на пиксель.Строка float2 (scale * frame% 16, scale * (frame / 16)) может сбить вас с толку, если вы еще не подписаны на меня.Более простой случай:

(with a total of 64 frames in an 8x8 grid)
       frame   0  1  2  3  4  5  6  7  8  9  10  11  12
x = frame%8    0  1  2  3  4  5  6  7  0  1   2   3   4 
y = frame/8    0  0  0  0  0  0  0  0  1  1   1   1   1      
(note integer division)
1 голос
/ 06 сентября 2011

Конечно, это возможно (при условии, что координаты текстуры остаются прежними). Просто используйте glBindTexture(), чтобы прикрепить текстуру, которая будет использоваться, и glActiveTexture(), чтобы выбрать текстурный блок для модификации.

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE2D, texture_texid);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE2D, normalmap_texid);
DrawStuff();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE2D, texture2_texid);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE2D, normalmap2_texid);
DrawStuff();

Очевидно, glActiveTexture() можно пропустить, если вы работаете только с одной текстурой.

...