Проблема glVertexAttribPointer (совместимый с OpenGL 3.x контекст) - PullRequest
0 голосов
/ 02 марта 2012

По современным стандартам предпочтительный способ рендеринга полигональных сеток, по-видимому, предусматривает использование объектов вершинных буферов в сочетании с индексными буферами (в конечном итоге, полученными при вызовах glDrawElements()), и именно поэтому я Я пытаюсь обернуть голову вокруг этих понятий. Кроме того, я настаиваю на использовании glVertexAttribPointer() вместо устаревших glVertexPointer(), glNormalPointer() и т. Д.

Я использую пользовательский двоичный 3d формат файла (производная Wavefront .OBJ), содержимое которого может быть более или менее непосредственно memcpy() 'd для массива вершин. Вот как я объявил мою vertex структуру:

   typedef struct vertex_ {

            float vx,vy,vz;
            float nx,ny,nz;
            float padding[2];  // align to 32 bytes 

   } vertex; 

Функция loadBObj() возвращает индексный буфер (реализованный в виде простого массива unsigned short int с) и заполняет массив вершин соответствующими данными вершин / нормалей (все используемые модели имеют было экспортировано, чтобы иметь на каждую вершину-нормали для более плавного результата затенения).

indices = loadBObj("pharaoh.bobj", false, &VBOid);

Сам код загрузки проверен для правильной работы.

Теперь, что также делается в loadBObj(), это создание нового VBO следующим образом:

    glGenBuffers(1, VBOid);
    glBindBuffer(GL_ARRAY_BUFFER, *VBOid);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex)*vcount, &vertarray[0].vx, GL_STATIC_DRAW);

После вызова loadBObj() объект буферного индекса (вероятно, не следует называть его таковым) создается следующим образом:

    glGenBuffers(1, &IBOid);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBOid);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short int)*qfcount*4, indices, GL_STATIC_DRAW);

OK. Когда дело доходит до фактического рендеринга меша, я использовал следующий код:

    #define BUFFER_OFFSET(i) ((char *)NULL + (i))
    ...
    glBindBuffer(GL_ARRAY_BUFFER, VBOid);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), BUFFER_OFFSET(0));
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), BUFFER_OFFSET(3*sizeof(float)));

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBOid);
    glDrawElements(GL_QUADS, qfcount*4, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));

, что приводит к абсолютно правильной геометрии, но затенение не совсем верно:

  • Вот изображение модели, отображенное в немедленном режиме:

img http://i44.tinypic.com/i36zcg.png

  • Вот один из созданных программой, описанной выше:

img2 http://i43.tinypic.com/sgmhhi.png

Что-то смешное происходит с моей обработкой VBO?

Ответы [ 3 ]

2 голосов
/ 02 марта 2012

Кажется, что ваши нормали не пройдены правильно

Это, вероятно, связано с тем, что у вас должно быть

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

, так как вы указываете и 0, и 1 указатель.(в настоящее время у вас есть только первая строка)

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

Вы используете шейдеры? Вы должны использовать только glVertexAttribPointer с шейдерами, и вы должны явно указать ему, какой массив атрибутов подходит для какой входной переменной. (GlGetAttribLocation / glBindAttribLocation).

Если вы используете фиксированный конвейер, вы должны придерживаться glVertexPointer / glNormalPointer.

0 голосов
/ 02 марта 2012

Я думаю, что здесь могло случиться, что треугольник * перевернут. Вы можете проверить это, просто поменяв местами каждую первую с каждой третьей вершиной.

  • Поскольку вы используете четырехугольники, это явно не ошибка. Но вы можете попробовать поменять каждую секунду каждой третьей вершиной.
...