Как использовать GL_TEXTURE_2D_ARRAY в OpenGL с использованием VBO - PullRequest
0 голосов
/ 15 марта 2012

Я пытаюсь нарисовать произвольный объект с количеством текстур "n" (6 в примерах), и у каждого лица есть одна (но, возможно, другая) текстура.

При использовании одной текстуры все работает нормально, но мне трудно заставить работать двухмерные массивы текстур.

Вот объект:

struct Vertex3f { float x, y, z; };
struct ObjectVertexfMT { // MT stands for Multi Texture
    struct Vertex3f coord;
    struct Vertex3f texcoord;
    struct Vertex3f normal;
};
struct ObjectVertexfMT GLEngine_CubeMT[] = {
    //    x,     y,     v,    u,    v,    r,    nx,    ny,    nz
    // Front
    { -1.0f, -1.0f,  1.0f, 0.0f, 0.0f, 0.0f,  0.0f,  0.0f,  1.0f },
    {  1.0f, -1.0f,  1.0f, 1.0f, 0.0f, 0.0f,  0.0f,  0.0f,  1.0f },
    {  1.0f,  1.0f,  1.0f, 1.0f, 1.0f, 0.0f,  0.0f,  0.0f,  1.0f },
    { -1.0f,  1.0f,  1.0f, 0.0f, 1.0f, 0.0f,  0.0f,  0.0f,  1.0f },
    // Back
    { -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,  0.0f,  0.0f, -1.0f },
    {  1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f,  0.0f,  0.0f, -1.0f },
    {  1.0f,  1.0f, -1.0f, 1.0f, 1.0f, 1.0f,  0.0f,  0.0f, -1.0f },
    { -1.0f,  1.0f, -1.0f, 0.0f, 1.0f, 1.0f,  0.0f,  0.0f, -1.0f },
    // Top
    { -1.0f,  1.0f, -1.0f, 0.0f, 1.0f, 2.0f,  0.0f,  1.0f,  0.0f },
    { -1.0f,  1.0f,  1.0f, 0.0f, 0.0f, 2.0f,  0.0f,  1.0f,  0.0f },
    {  1.0f,  1.0f,  1.0f, 1.0f, 0.0f, 2.0f,  0.0f,  1.0f,  0.0f },
    {  1.0f,  1.0f, -1.0f, 1.0f, 1.0f, 2.0f,  0.0f,  1.0f,  0.0f },
    // Bottom
    { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 3.0f,  0.0f, -1.0f,  0.0f },
    { -1.0f, -1.0f,  1.0f, 0.0f, 1.0f, 3.0f,  0.0f, -1.0f,  0.0f },
    {  1.0f, -1.0f,  1.0f, 0.0f, 0.0f, 3.0f,  0.0f, -1.0f,  0.0f },
    {  1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 3.0f,  0.0f, -1.0f,  0.0f },
    // Right
    {  1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 4.0f,  1.0f,  0.0f,  0.0f },
    {  1.0f,  1.0f, -1.0f, 1.0f, 1.0f, 4.0f,  1.0f,  0.0f,  0.0f },
    {  1.0f,  1.0f,  1.0f, 0.0f, 1.0f, 4.0f,  1.0f,  0.0f,  0.0f },
    {  1.0f, -1.0f,  1.0f, 0.0f, 0.0f, 4.0f,  1.0f,  0.0f,  0.0f },
    // Left
    { -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 5.0f, -1.0f,  0.0f,  0.0f },
    { -1.0f, -1.0f,  1.0f, 1.0f, 0.0f, 5.0f, -1.0f,  0.0f,  0.0f },
    { -1.0f,  1.0f,  1.0f, 1.0f, 1.0f, 5.0f, -1.0f,  0.0f,  0.0f },
    { -1.0f,  1.0f, -1.0f, 0.0f, 1.0f, 5.0f, -1.0f,  0.0f,  0.0f }
};

обратите внимание, что параметр "r" различен для каждого квада (указывая индекс текстуры, которую я хочу в этом конкретном квадре).

Я регистрирую текстуры так:

struct texInfo {
    int width, height;
    unsigned char *data;
};

// Loads texture from filename in a texInfo structure -- always 32 bit depth
struct texInfo *loadTexture(const char* filename);

unsigned int register3DTexture(const char *filenames[], unsigned int texcount) {
  unsigned int ret;
  unsigned int i;
  struct texInfo *tex;
  glGenTextures(1, &ret);
  glBindTexture(GL_TEXTURE_2D_ARRAY, ret);
  glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, 4, 256, 256, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  for (i = 0; i < texcount; i++) {
    tex = loadTexture(filenames[i]);
    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, tex->width, tex->height, 1, GL_RGBA, GL_UNSIGNED_BYTE, tex->data);
    free(tex);
  }

  return(ret);
}

... а потом я рисую:

  glPushMatrix();

  glClientActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D_ARRAY, textures[0]); // Same behaviour if I change to GL_TEXTURE_2D

  glTranslatef(pos.x, pos.y, pos.z);
  glRotatef(rot_angle, rot.x, rot.y, rot.z);

  glBindBuffer(GL_ARRAY_BUFFER, VobObject[0]);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VobObject[1]);

  glEnableClientState(GL_VERTEX_ARRAY);
  glEnableClientState(GL_NORMAL_ARRAY);

  glVertexPointer(3, GL_FLOAT, sizeof(struct ObjectVertexfMT), 0);
  glNormalPointer(GL_FLOAT, sizeof(struct ObjectVertexfMT), (void*)(sizeof(float) * 6));

  // Textures
  glClientActiveTexture(GL_TEXTURE0);
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  glTexCoordPointer(2, GL_FLOAT, sizeof(struct ObjectVertexfMT), (void*)(sizeof(float) * 3));

  glDrawElements(GL_QUADS, m_vertexcount, GL_UNSIGNED_SHORT, 0);

  glDisableClientState(GL_VERTEX_ARRAY);
  glDisableClientState(GL_NORMAL_ARRAY);
  glPopMatrix();

Объект нарисован правильно, но без текстур.

Еще несколько вопросов:

  • Предполагая, что это работает, это лучший способ достичь моей цели?

  • Могут ли "подтекстуры" иметь разные размеры "основной" текстуры ( параметры ширины и высоты на glTexImage3D() могут отличаться из glTexSubImage3D())?

1 Ответ

1 голос
/ 16 марта 2012

Вы должны использовать шейдер, чтобы использовать текстуры массива. Вы не можете использовать их с фиксированной функцией рендеринга.

Могут ли "подтексты" иметь разные размеры "основной" текстуры (параметры width и height в glTexImage3D () могут отличаться от параметров glTexSubImage3D ())?

Этот вопрос запутан. Как и в случае с массивами C ++, элементы текстурных массивов одинаковы. Если у вас есть массив int[30] в C ++, то каждый элемент будет иметь 30 целых чисел. То же самое касается массивов текстур. Текстура 2D-массива в целом имеет ширину и высоту, которые одинаковы для всех текстур в массиве.

glTexSubImage3D (и аналогичные функции) не влияет на размеры текстуры. Все, что он делает, это загружает данные пикселей в местоположение в текстуре. Только glTexImage3D (и аналогичные функции) влияют на размеры текстуры.

...