Проблемы с отрисовкой объектов OpenGL из VBO с использованием текстур, нормалей и & amp; indexlist

Я надеюсь, что это не кажется слишком большой частью дампа кода, но я действительно понятия не имею, почему это не работает. Я пытался получить ошибки от glGetError (), и он всегда возвращает 0.
Я попытался включить только тот код, который, как мне кажется, влияет на проблему, так как другой код работал нормально в большинстве других ситуаций, в которых я его использовал.

В любом случае, код сначала:

Это мой основной цикл рендеринга:

float rotate = 0.0f;
void Render(SDL_Window *window)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

gluLookAt(-2,-2,-10,   0,0,0,   0,1,0);

glRotatef(rotate, 0, 1, 0);
// Start drawing
glUseProgramObjectARB( *shader->GetShaderProgram() );
texture->EnableTexture( *shader->GetShaderProgram(),"tex" );
cube->Render();
SDL_GL_SwapWindow(window);
rotate = rotate+1;
glUseProgramObjectARB(0);
}

Это мои объекты рендера (cube-> Render ()):

void Object3DVBO::Render()
{

//Bind the buffers and tell OpenGL to use the Vertex Buffer Objects (VBO's), which we already prepared earlier
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboID);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, texcoordsID);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, normalID);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indiceID);

//Enable states, and render (as if using vertex arrays directly)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

glTexCoordPointer(2, GL_FLOAT, 0, 0);
glNormalPointer(GL_FLOAT, 0, 0);
glVertexPointer(3, GL_FLOAT, 0,  0);

if(textureid > 0) {
glEnable(GL_TEXTURE_2D);      // Turn on Texturing
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBindTexture(GL_TEXTURE_2D, textureid);
}

//Draw the thing!
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_BYTE, 0);
//restore the GL state back
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if(textureid > 0) {
glDisable(GL_TEXTURE_2D);      // Turn off Texturing
glBindTexture(GL_TEXTURE_2D, textureid);
}

glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); //Restore non VBO mode
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
};

Это код для инициализации VBO:

void Object3DVBO::SetVBO()
{
// Vertices:
glGenBuffersARB(1, &vboID);
glBindBufferARB( GL_ARRAY_BUFFER_ARB, vboID);
glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(GLfloat)*vertices.size(), &vertices, GL_STATIC_DRAW_ARB );

// Vertices:
glGenBuffersARB(1, &indiceID);
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, indiceID);
glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(GLubyte)*indices.size(), &indices, GL_STATIC_DRAW_ARB );

// Normals:
glGenBuffersARB(1, &normalID);
glBindBufferARB( GL_ARRAY_BUFFER_ARB, normalID);
glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(GLfloat)*normals.size(), &normals, GL_STATIC_DRAW_ARB );

// Texture coordinates:
glGenBuffersARB(1, &texcoordsID);
glBindBufferARB( GL_ARRAY_BUFFER_ARB, texcoordsID);
glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(GLfloat)*texCoords.size(), &texCoords, GL_STATIC_DRAW_ARB );

vertices.clear();
normals.clear();
texCoords.clear();
indices.clear();
}

и, наконец, самая простая модель, которую я сделал в текстовом файле:

mesh:
-0.5 -0.5 0.0
0.5 -0.5 0.0
0.5 0.5 0.0
-0.5 0.5 0.0
normals:
0 0 -1
0 0 -1
0 0 -1
0 0 -1
texcoords:
0.0 0
1.0 0
1.0 1.0
0.0 1.0
indices:
0 0 0 1 1 1 2 2 2 0 0 0 2 2 2 3 3 3
end:

Что выходит за рамки этого — чтение текстового файла и сохранение его в векторах из функций.
Вот заголовочный файл для объекта:

class Object3DVBO
{
public:
Object3DVBO(const char* objectfilename, GLuint textureid);
~Object3DVBO();
void Render();
private:
GLuint  vboID,
texcoordsID,
normalID,
textureid,
indiceID;
int     vertCount,
indexCount;
std::vector<GLfloat> vertices;
std::vector<GLfloat> normals;
std::vector<GLfloat> texCoords;
std::vector<GLubyte> indices;

void ConvertToReadable( std::vector<GLfloat> v, std::vector<GLfloat> n, std::vector<GLfloat> tc, std::vector<GLint> i);
void ReadObjectData( const char* objectfilename);
void SetVBO();
};

Другие части в основном делают то же самое для шейдерной пары. & текстура, они, кажется, работают нормально (шейдер на данный момент только версия 120, поэтому он использует ftransform () и т. д.)

Проблема, которая у меня есть, заключается в том, что когда я использую этот код и glDrawElements с использованием индексов, я получаю черный экран (без ошибок), и если я затем переключаюсь на glDrawArrays, он работает (или, по крайней мере, я вижу ЧТО-ТО. Я читал много уроков, примеров и другие сообщения SO, пытающиеся найти то, что я делаю неправильно, но ни одно из решений / учебных пособий пока не имеет никакого значения.

Я делаю это в образовательных целях, поэтому мне действительно нужно использовать glDrawElements & индексы.
Любая помощь будет принята с благодарностью!

Ps. Если кто-то интересуется версией SDL, ее SDL2.

1

Решение

Вот суть вашей проблемы:

//Bind the buffers and tell OpenGL to use the Vertex Buffer Objects (VBO's), which we already prepared earlier
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboID);          // 1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, texcoordsID);    // 2
glBindBufferARB(GL_ARRAY_BUFFER_ARB, normalID);       // 3
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indiceID);

//Enable states, and render (as if using vertex arrays directly)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

glTexCoordPointer(2, GL_FLOAT, 0, 0);                 // 2
glNormalPointer(GL_FLOAT, 0, 0);                      // 3
glVertexPointer(3, GL_FLOAT, 0,  0);                  // 1

Линии, обозначенные 1, 2 и 3, должны быть в парах. То есть, поскольку вы можете иметь только один VBO, связанный одновременно, и это обеспечивает контекст для вызова glTexCoordPointer (...) например, вам нужно установить указатели, когда соответствующий VBO привязан.

Вы можете исправить это так:

//Bind the buffers and tell OpenGL to use the Vertex Buffer Objects (VBO's), which we already prepared earlier
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboID);          // 1
glVertexPointer(3, GL_FLOAT, 0,  0);                  // 1

glBindBufferARB(GL_ARRAY_BUFFER_ARB, texcoordsID);    // 2
glTexCoordPointer(2, GL_FLOAT, 0, 0);                 // 2

glBindBufferARB(GL_ARRAY_BUFFER_ARB, normalID);       // 3
glNormalPointer(GL_FLOAT, 0, 0);                      // 3glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indiceID);

//Enable states, and render (as if using vertex arrays directly)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

У вас есть еще одна проблема, которая на самом деле не столько ошибка, сколько проблема с производительностью. GL_UNSIGNED_BYTE не аппаратно поддерживаемый тип индекса вершины. Драйвер должен преобразовать ваш индексный массив в 16-битный тип, чтобы аппаратное обеспечение могло его использовать, поэтому нет никакой реальной выгоды использовать 8-битные индексы, когда вы собираетесь хранить их в VBO. Большинство профилировщиков и драйверов OpenGL с включенным выходом отладки выдают предупреждение о производительности, если вы попытаетесь это сделать.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]