opengl vbo 纹理
我还是 vbo 的初学者,我想渲染一个 collada 模型。从cae文件中获取有关顶点、法线和纹理的所有所需信息以及分别用于顶点、法线和纹理的索引后,我将它们作为模型对象放置在内存中。剩下的事情是如何使用 vbo 和纹理来渲染这个对象。我成功地渲染了对象,方法是获取顶点和索引,然后在 vbo 渲染的情况下应用drawlelement。但是,当我尝试渲染纹理时,它会失败,而使用显示列表渲染它们可以正常工作,那是因为我正在遍历每个三角形并根据顶点索引和纹理索引正确应用顶点和纹理坐标。那么我如何应用在 vbo 中的对象中找到的纹理索引以便正确渲染纹理?
这是该项目的代码:
#include "bmp.h"
struct mdl_vert
{
float x,y,z;
};
struct mdl_normal
{
float x,y,z;
};
struct mdl_texCoord
{
float u,v;
};
struct mdl_capacity
{
int vertsSize,indicesSize,normalsSize,texCoordsSize;
};
struct mdl_indices
{
int *vertIndices;
int *normalIndices;
int *texIndices;
};
class Group
{
public:
mdl_capacity capacity;
mdl_vert *verts;
mdl_normal *normals;
mdl_texCoord *texCoords;
mdl_indices indices;
char grp_name[64];
Group()
{
capacity.texCoordsSize=0;
capacity.normalsSize=0;
capacity.indicesSize=0;
capacity.vertsSize=0;
verts=NULL;
normals=NULL;
texCoords=NULL;
indices.vertIndices=NULL;
indices.normalIndices=NULL;
indices.texIndices=NULL;
for(int i=0;i<64;i++)
grp_name[i]='\0';
}
};
class Model
{
public:
char tex_name[512];
std::string Name;
Group **groups;
int groupsSize;
}
#define VBO_BUFFER_SIZE 4
struct GroupObject
{
GLuint *buffer;
};
class ModelObject
{
private:
GLuint displayList;
GroupObject *groupBuffer;
bool isLoaded;
GLuint tex;
float ang,iniRotX,iniRotY,iniRotZ;
Model *mdl;
bool Hide;
AUX_RGBImageRec* m_pTextureImage; // Heightmap Data
public:
ModelObject(Model* mdl)
{
this->mdl=mdl;
Redraw();
}
void Redraw()
{
Hide=false;
ang=-0;
iniRotX=1;
iniRotY=0;
iniRotZ=0;
if(displayList!=-1)
displayList=-1;
groupBuffer=NULL;
}
void BuildTexture(int i)
{
if(mdl->groups[i]->capacity.texCoordsSize>0)
{
try
{
m_pTextureImage = auxDIBImageLoad( mdl->tex_name ); // Utilize GLaux's Bitmap Load Routine
glGenTextures( 1, &tex ); // Get An Open ID
glBindTexture( GL_TEXTURE_2D, tex ); // Bind The Texture
glTexImage2D( GL_TEXTURE_2D, 0, 3, m_pTextureImage->sizeX, m_pTextureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, m_pTextureImage->data );
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
// Free The Texture Data
if( m_pTextureImage )
{
if( m_pTextureImage->data )
free( m_pTextureImage->data );
free( m_pTextureImage );
}
}
catch(std::exception &ex)
{
}
}
}
void BuildVBO()
{
int index=0;
groupBuffer=new GroupObject[mdl->groupsSize];
for(int i=0;i<mdl->groupsSize;i++)
{
BuildTexture(i);
groupBuffer[i].buffer=new GLuint[VBO_BUFFER_SIZE];
// Generate And Bind The Vertex Buffer
glGenBuffersARB( 1, &groupBuffer[i].buffer[0] ); // Get A Valid Name
glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[0] ); // Bind The Buffer
glBufferDataARB( GL_ARRAY_BUFFER_ARB,mdl->groups[i]->capacity.vertsSize*sizeof(mdl_vert), mdl->groups[i]->verts, GL_STATIC_DRAW_ARB );
// Generate And Bind The Normal Buffer
glGenBuffersARB( 1, &groupBuffer[i].buffer[1] ); // Get A Valid Name
glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[1] ); // Bind The Buffer
glBufferDataARB( GL_ARRAY_BUFFER_ARB,mdl->groups[i]->capacity.normalsSize*sizeof(mdl_normal), mdl->groups[i]->normals, GL_STATIC_DRAW_ARB );
// Generate And Bind The Texture Buffer
glGenBuffersARB( 1, &groupBuffer[i].buffer[2] ); // Get A Valid Name
glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[2] ); // Bind The Buffer
glBufferDataARB( GL_ARRAY_BUFFER_ARB,mdl->groups[i]->capacity.texCoordsSize*sizeof(mdl_texCoord), mdl->groups[i]->texCoords, GL_STATIC_DRAW_ARB );
// Generate And Bind The Index Buffer
glGenBuffersARB(1, &groupBuffer[i].buffer[3]);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[3]);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mdl->groups[i]->capacity.indicesSize*sizeof(unsigned int), mdl->groups[i]->indices.vertIndices, GL_STATIC_DRAW_ARB);
}
}
void render()
{
if(!Hide)
{
if(Drawer.vboSupported())
{
if(groupBuffer==NULL)
BuildVBO();
glRotatef(ang,iniRotX,iniRotY,iniRotZ);
for(int i=0;i<mdl->groupsSize;i++)
{
// Enable Pointers
glEnableClientState( GL_VERTEX_ARRAY ); // Disable Vertex Arrays
glEnableClientState( GL_NORMAL_ARRAY ); // Enable Normal Arrays
glEnableClientState( GL_TEXTURE_COORD_ARRAY ); // Enable Texture Coord Arrays
glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[0] );
glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));
glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[1] );
glNormalPointer(GL_FLOAT,0, BUFFER_OFFSET(0));
glClientActiveTexture(GL_TEXTURE0);
glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[2] );
glTexCoordPointer(2,GL_FLOAT,0,BUFFER_OFFSET(0));
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, groupBuffer[i].buffer[3]);
glIndexPointer(GL_UNSIGNED_INT,0,BUFFER_OFFSET(0));
glDrawElements( GL_TRIANGLES, mdl->groups[i]->capacity.indicesSize,GL_UNSIGNED_INT, 0); // Draw All Of The Triangles At Once
// Disable Pointers
glDisableClientState( GL_VERTEX_ARRAY ); // Disable Vertex Arrays
glDisableClientState( GL_NORMAL_ARRAY ); // Enable Normal Arrays
glDisableClientState( GL_TEXTURE_COORD_ARRAY ); // Enable Texture Coord Arrays
}
glRotatef(-ang,iniRotX,iniRotY,iniRotZ);
}
else
{
if(this->displayList==-1)
{
displayList = glGenLists(1);
glNewList(displayList,GL_COMPILE_AND_EXECUTE);
glRotatef(ang,iniRotX,iniRotY,iniRotZ);
for(int j=0;j<mdl->groupsSize;j++)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex);
// Enable Pointers
BuildTexture(j);
//glColor3f(((float)(rand()%256)/256.0f),((float)(rand()%256)/256.0f),((float)(rand()%256)/256.0f));
for(int i=0;i<mdl->groups[j]->capacity.indicesSize;i+=3)
{
int iv1=mdl->groups[j]->indices.vertIndices[i];
int in1=mdl->groups[j]->indices.normalIndices[i];
int it1=mdl->groups[j]->indices.texIndices[i];
int iv2=mdl->groups[j]->indices.vertIndices[i+1];
int in2=mdl->groups[j]->indices.normalIndices[i+1];
int it2=mdl->groups[j]->indices.texIndices[i+1];
int iv3=mdl->groups[j]->indices.vertIndices[i+2];
int in3=mdl->groups[j]->indices.normalIndices[i+2];
int it3=mdl->groups[j]->indices.texIndices[i+2];
glBegin(GL_TRIANGLES);
glTexCoord2f(mdl->groups[j]->texCoords[it1].u,mdl->groups[j]->texCoords[it1].v);
glNormal3f(mdl->groups[j]->normals[in1].x,mdl->groups[j]->normals[in1].y,mdl->groups[j]->normals[in1].z);
glVertex3f(mdl->groups[j]->verts[iv1].x,mdl->groups[j]->verts[iv1].y,mdl->groups[j]->verts[iv1].z);
glTexCoord2f(mdl->groups[j]->texCoords[it2].u,mdl->groups[j]->texCoords[it2].v);
glNormal3f(mdl->groups[j]->normals[in2].x,mdl->groups[j]->normals[in2].y,mdl->groups[j]->normals[in2].z);
glVertex3f(mdl->groups[j]->verts[iv2].x,mdl->groups[j]->verts[iv2].y,mdl->groups[j]->verts[iv2].z);
glTexCoord2f(mdl->groups[j]->texCoords[it3].u,mdl->groups[j]->texCoords[it3].v);
glNormal3f(mdl->groups[j]->normals[in3].x,mdl->groups[j]->normals[in3].y,mdl->groups[j]->normals[in3].z);
glVertex3f(mdl->groups[j]->verts[iv3].x,mdl->groups[j]->verts[iv3].y,mdl->groups[j]->verts[iv3].z);
glEnd();
}
glDisable(GL_TEXTURE_2D);
}
glRotatef(-ang,iniRotX,iniRotY,iniRotZ);
glEndList();
glCallList(displayList);
}
else
glCallList(displayList);
}
}
}
I am still a beginner in vbo and I want to render a collada model. After taking all the needed info from the cae file about the vertices, normals and textures and indices for the vertices, normals and textures respectively, then i placed them in memory as a Model object. the thing that remained is how to render this object using vbo with the textures. I managed to render the object successfully by taking the vertices and indices then applying drawlelement for that in case of vbo render. But when I try to render textures it fails while rendering them using the display list works correctly thats because I am passing through every triangle and applying the vertex and texcoord correctly according to the vertex index and texture index. So how can i apply the texture indices found in the object in vbo in order for the texture to be rendered correctly?
This is the code for the project:
#include "bmp.h"
struct mdl_vert
{
float x,y,z;
};
struct mdl_normal
{
float x,y,z;
};
struct mdl_texCoord
{
float u,v;
};
struct mdl_capacity
{
int vertsSize,indicesSize,normalsSize,texCoordsSize;
};
struct mdl_indices
{
int *vertIndices;
int *normalIndices;
int *texIndices;
};
class Group
{
public:
mdl_capacity capacity;
mdl_vert *verts;
mdl_normal *normals;
mdl_texCoord *texCoords;
mdl_indices indices;
char grp_name[64];
Group()
{
capacity.texCoordsSize=0;
capacity.normalsSize=0;
capacity.indicesSize=0;
capacity.vertsSize=0;
verts=NULL;
normals=NULL;
texCoords=NULL;
indices.vertIndices=NULL;
indices.normalIndices=NULL;
indices.texIndices=NULL;
for(int i=0;i<64;i++)
grp_name[i]='\0';
}
};
class Model
{
public:
char tex_name[512];
std::string Name;
Group **groups;
int groupsSize;
}
#define VBO_BUFFER_SIZE 4
struct GroupObject
{
GLuint *buffer;
};
class ModelObject
{
private:
GLuint displayList;
GroupObject *groupBuffer;
bool isLoaded;
GLuint tex;
float ang,iniRotX,iniRotY,iniRotZ;
Model *mdl;
bool Hide;
AUX_RGBImageRec* m_pTextureImage; // Heightmap Data
public:
ModelObject(Model* mdl)
{
this->mdl=mdl;
Redraw();
}
void Redraw()
{
Hide=false;
ang=-0;
iniRotX=1;
iniRotY=0;
iniRotZ=0;
if(displayList!=-1)
displayList=-1;
groupBuffer=NULL;
}
void BuildTexture(int i)
{
if(mdl->groups[i]->capacity.texCoordsSize>0)
{
try
{
m_pTextureImage = auxDIBImageLoad( mdl->tex_name ); // Utilize GLaux's Bitmap Load Routine
glGenTextures( 1, &tex ); // Get An Open ID
glBindTexture( GL_TEXTURE_2D, tex ); // Bind The Texture
glTexImage2D( GL_TEXTURE_2D, 0, 3, m_pTextureImage->sizeX, m_pTextureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, m_pTextureImage->data );
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
// Free The Texture Data
if( m_pTextureImage )
{
if( m_pTextureImage->data )
free( m_pTextureImage->data );
free( m_pTextureImage );
}
}
catch(std::exception &ex)
{
}
}
}
void BuildVBO()
{
int index=0;
groupBuffer=new GroupObject[mdl->groupsSize];
for(int i=0;i<mdl->groupsSize;i++)
{
BuildTexture(i);
groupBuffer[i].buffer=new GLuint[VBO_BUFFER_SIZE];
// Generate And Bind The Vertex Buffer
glGenBuffersARB( 1, &groupBuffer[i].buffer[0] ); // Get A Valid Name
glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[0] ); // Bind The Buffer
glBufferDataARB( GL_ARRAY_BUFFER_ARB,mdl->groups[i]->capacity.vertsSize*sizeof(mdl_vert), mdl->groups[i]->verts, GL_STATIC_DRAW_ARB );
// Generate And Bind The Normal Buffer
glGenBuffersARB( 1, &groupBuffer[i].buffer[1] ); // Get A Valid Name
glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[1] ); // Bind The Buffer
glBufferDataARB( GL_ARRAY_BUFFER_ARB,mdl->groups[i]->capacity.normalsSize*sizeof(mdl_normal), mdl->groups[i]->normals, GL_STATIC_DRAW_ARB );
// Generate And Bind The Texture Buffer
glGenBuffersARB( 1, &groupBuffer[i].buffer[2] ); // Get A Valid Name
glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[2] ); // Bind The Buffer
glBufferDataARB( GL_ARRAY_BUFFER_ARB,mdl->groups[i]->capacity.texCoordsSize*sizeof(mdl_texCoord), mdl->groups[i]->texCoords, GL_STATIC_DRAW_ARB );
// Generate And Bind The Index Buffer
glGenBuffersARB(1, &groupBuffer[i].buffer[3]);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[3]);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mdl->groups[i]->capacity.indicesSize*sizeof(unsigned int), mdl->groups[i]->indices.vertIndices, GL_STATIC_DRAW_ARB);
}
}
void render()
{
if(!Hide)
{
if(Drawer.vboSupported())
{
if(groupBuffer==NULL)
BuildVBO();
glRotatef(ang,iniRotX,iniRotY,iniRotZ);
for(int i=0;i<mdl->groupsSize;i++)
{
// Enable Pointers
glEnableClientState( GL_VERTEX_ARRAY ); // Disable Vertex Arrays
glEnableClientState( GL_NORMAL_ARRAY ); // Enable Normal Arrays
glEnableClientState( GL_TEXTURE_COORD_ARRAY ); // Enable Texture Coord Arrays
glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[0] );
glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));
glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[1] );
glNormalPointer(GL_FLOAT,0, BUFFER_OFFSET(0));
glClientActiveTexture(GL_TEXTURE0);
glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[2] );
glTexCoordPointer(2,GL_FLOAT,0,BUFFER_OFFSET(0));
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, groupBuffer[i].buffer[3]);
glIndexPointer(GL_UNSIGNED_INT,0,BUFFER_OFFSET(0));
glDrawElements( GL_TRIANGLES, mdl->groups[i]->capacity.indicesSize,GL_UNSIGNED_INT, 0); // Draw All Of The Triangles At Once
// Disable Pointers
glDisableClientState( GL_VERTEX_ARRAY ); // Disable Vertex Arrays
glDisableClientState( GL_NORMAL_ARRAY ); // Enable Normal Arrays
glDisableClientState( GL_TEXTURE_COORD_ARRAY ); // Enable Texture Coord Arrays
}
glRotatef(-ang,iniRotX,iniRotY,iniRotZ);
}
else
{
if(this->displayList==-1)
{
displayList = glGenLists(1);
glNewList(displayList,GL_COMPILE_AND_EXECUTE);
glRotatef(ang,iniRotX,iniRotY,iniRotZ);
for(int j=0;j<mdl->groupsSize;j++)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex);
// Enable Pointers
BuildTexture(j);
//glColor3f(((float)(rand()%256)/256.0f),((float)(rand()%256)/256.0f),((float)(rand()%256)/256.0f));
for(int i=0;i<mdl->groups[j]->capacity.indicesSize;i+=3)
{
int iv1=mdl->groups[j]->indices.vertIndices[i];
int in1=mdl->groups[j]->indices.normalIndices[i];
int it1=mdl->groups[j]->indices.texIndices[i];
int iv2=mdl->groups[j]->indices.vertIndices[i+1];
int in2=mdl->groups[j]->indices.normalIndices[i+1];
int it2=mdl->groups[j]->indices.texIndices[i+1];
int iv3=mdl->groups[j]->indices.vertIndices[i+2];
int in3=mdl->groups[j]->indices.normalIndices[i+2];
int it3=mdl->groups[j]->indices.texIndices[i+2];
glBegin(GL_TRIANGLES);
glTexCoord2f(mdl->groups[j]->texCoords[it1].u,mdl->groups[j]->texCoords[it1].v);
glNormal3f(mdl->groups[j]->normals[in1].x,mdl->groups[j]->normals[in1].y,mdl->groups[j]->normals[in1].z);
glVertex3f(mdl->groups[j]->verts[iv1].x,mdl->groups[j]->verts[iv1].y,mdl->groups[j]->verts[iv1].z);
glTexCoord2f(mdl->groups[j]->texCoords[it2].u,mdl->groups[j]->texCoords[it2].v);
glNormal3f(mdl->groups[j]->normals[in2].x,mdl->groups[j]->normals[in2].y,mdl->groups[j]->normals[in2].z);
glVertex3f(mdl->groups[j]->verts[iv2].x,mdl->groups[j]->verts[iv2].y,mdl->groups[j]->verts[iv2].z);
glTexCoord2f(mdl->groups[j]->texCoords[it3].u,mdl->groups[j]->texCoords[it3].v);
glNormal3f(mdl->groups[j]->normals[in3].x,mdl->groups[j]->normals[in3].y,mdl->groups[j]->normals[in3].z);
glVertex3f(mdl->groups[j]->verts[iv3].x,mdl->groups[j]->verts[iv3].y,mdl->groups[j]->verts[iv3].z);
glEnd();
}
glDisable(GL_TEXTURE_2D);
}
glRotatef(-ang,iniRotX,iniRotY,iniRotZ);
glEndList();
glCallList(displayList);
}
else
glCallList(displayList);
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
OpenGL 中没有纹理索引。这种位置和纹理的分离在建模软件中很常见,因为它更易于管理。但在 OpenGL 中,您需要拥有与位置完全相同的纹理坐标计数,因此可以使用相同的索引对它们进行索引。
这将要求您重建所有缓冲区,以便模型中出现的顶点索引、法线索引和纹理坐标索引的每个组合都可以映射到用于 OpenGL 渲染的单个索引。我将尝试编写一些伪代码:
现在您可以将 new_indices、new_positions、new_normals 和 new_texcoords 放入 VBO 并渲染它们。我希望这有帮助...
There are no texture indices in OpenGL. This separation of positions and textures is quite common in modelling software, as it is simpler to manage. But in OpenGL, you need to have the exactly same count of texture coordinates as there are positions, so they could both be indexed using the same index.
This will require you to rebuild all the buffers, so that every combination of vertex index, normal index and texcoord index that occurs in your model can be mapped to a single index for OpenGL rendering. I'll try and write some pseudocode:
Now you can put new_indices, new_positions, new_normals and new_texcoords to VBOs and render them. I hope this helps ...