使用纹理,法线和索引列表从VBO绘制OpenGL对象的问题
Problems with drawing OpenGL objects from VBO using textures,normals & 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);
}
这是我的对象render(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();
};
其他部分基本上是为着色器对和纹理做同样的事情,这些似乎工作正常(Shader 现在只有 120 版,所以它使用 ftransform() 等)。
我遇到的问题是,当我使用此代码并使用索引的glDrawElements时,我得到一个黑屏(任何地方都没有错误),如果我切换到glDrawArrays,它可以工作(或者至少我看到了一些东西。我阅读了很多教程,示例和其他SO帖子,试图找到我做错了什么,但到目前为止,没有任何解决方案/教程有任何区别。
我这样做是出于教育目的,所以我真的需要使用glDrawElements和索引。任何帮助将不胜感激!
附言。如果有人想知道 SDL 版本,它的 SDL2。
这是你问题的症结:
//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); // 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);
您还有一个额外的问题,与其说是错误,不如说是性能问题。 GL_UNSIGNED_BYTE
不是硬件支持的顶点索引类型。驱动程序必须将索引数组转换为 16 位类型,硬件才能使用它,因此,当您要将 8 位索引存储在 VBO 中时,使用 8 位索引没有实际好处。如果尝试执行此操作,大多数启用了调试输出的 OpenGL 探查器和驱动程序将生成性能警告。
- QuadTree只在窗口的右上角绘制
- 绘制旋转的三角形
- flutter:即使shouldRepaint()返回true,自定义画家也不会重新绘制
- 如何在QT中的自定义视频小工具t上绘制矩形
- 如何在Visual Basic中使用矩形函数OpenGL绘制矩形
- 如何使用多个VAO和VBO在OpenGL中绘制多个对象
- 使用 VBO 绘制不同宽度的彩色线条
- c++OpenGL发布用存储在对象中的vbo和vao绘制网格
- 在OpenGL中绘制VBO不起作用
- C++/OpenGL-用VBO绘制立方体
- 绘制 VBO 会导致分割错误
- 使用纹理,法线和索引列表从VBO绘制OpenGL对象的问题
- Vbo 如何绘制基元
- 在3.2中使用VAO和VBO绘制OpenGL线条和正方形
- 用VBO绘制OpenGL图形
- 在同一个VBO OpenGL上用不同的纹理绘制不同的对象
- Vbo -绘制法线与obj文件
- 绘制数以千计的多边形与OpenGL VBO
- 用VBO和FBO绘制一个移动的精灵
- VBO:数组未绘制