纹理VBO(顶点缓冲对象)

时间:2010-11-07 14:47:52

标签: opengl texture-mapping vertex-buffer texturing

我目前正在开发一个程序行星生成工具,它通过采用立方体,将其映射到球体,然后将高度图应用于每个面来生成地形。

我正在使用VBO为每个面使用以下方法创建:

void Planet::setVertexBufferObject()
{
 Vertex* vertices;
 int currentVertex;
 Vertex* vertex;

 for(int i = 0; i < 6; i++)
 {
  // bottom face
  if(i == 0)
  {
   glBindBuffer(GL_ARRAY_BUFFER, bottomVBO);    
  }
  // top face
  else if(i == 1)
  {
   glBindBuffer(GL_ARRAY_BUFFER, topVBO);    
  }
  // front face
  else if(i == 2)
  {
   glBindBuffer(GL_ARRAY_BUFFER, frontVBO);    
  }
  // back face
  else if(i == 3)
  {
   glBindBuffer(GL_ARRAY_BUFFER, backVBO);    
  }
  // left face
  else if(i == 4)
  {
   glBindBuffer(GL_ARRAY_BUFFER, leftVBO);    
  }
  // right face
  else
  {
   glBindBuffer(GL_ARRAY_BUFFER, rightVBO);    
  } 

  vertices = (Vertex*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

  currentVertex = 0;

  for(int x = 0; x < size; x++)
  {
   for(int z = 0; z < size; z++)
   {
    currentVertex = z * size + x;

    vertex = &vertices[currentVertex];

    vertex->xTextureCoord = (x * 1.0f) / 512.0f;
    vertex->zTextureCoord = (z * 1.0f) / 512.0f;

    Vector3 normal;

    vertex->xNormal = normal.x;
    vertex->yNormal = normal.y;
    vertex->zNormal = normal.z;

    vertex->x = heightMapCubeFace[i][x][z][0];
    vertex->y = heightMapCubeFace[i][x][z][1];
    vertex->z = heightMapCubeFace[i][x][z][2];

    vertex->x *= (1.0f +((heightMaps[i][z][x]/256.0f) * 0.1));
    vertex->y *= (1.0f +((heightMaps[i][z][x]/256.0f) * 0.1));
    vertex->z *= (1.0f +((heightMaps[i][z][x]/256.0f) * 0.1));
   }
  }
  glUnmapBuffer(GL_ARRAY_BUFFER);
  glBindBuffer(GL_ARRAY_BUFFER, 0);
 }
}

我省略了setIndexBufferObject()方法,因为它工作正常。

然后我使用这种方法渲染球体:

void Planet::render()
{
    // bottom face

    glBindBuffer(GL_ARRAY_BUFFER, bottomVBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bottomIBO);

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(6 * sizeof(float)));

    glEnableClientState(GL_NORMAL_ARRAY);
    glNormalPointer(GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(3 * sizeof(float)));

    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(0));

 TextureManager::Inst()->BindTexture(textueIDs[0]);
 glClientActiveTexture(GL_TEXTURE0+textueIDs[0]);
 glDrawElements(GL_TRIANGLE_STRIP, numberOfIndices, GL_UNSIGNED_INT, BUFFER_OFFSET(0)); 

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

 // next face and so on...

正在使用免费图像加载纹理,正如您从上面的代码中可以看到的,我只是使用了带有freeimage的示例纹理管理器。

为什么绑定纹理不起作用?

2 个答案:

答案 0 :(得分:1)

  

为什么绑定纹理不起作用?

非常具体地描述您所看到的行为,或者更好地将网址附加到屏幕截图,在尝试解决图形问题时会有很长的路要走。

接下来,如果glGetError()没有返回GL_NO_ERROR,则需要包含gl错误状态或者至少在代码中证明你正在检查和失败。

你的VBO / draw元素状态看起来很合理,虽然你故意省略了索引缓冲区对象的定义,所以我们会相信你正在向glDrawElements()调用发送真正的索引。对于完整性检查,使用原始索引指针执行glDrawElements()调用,而不是为元素绑定VBO。

您还省略了Vertex的类型定义,这需要知道您为glTexCoordPointer()提供的偏移量是否与结构定义一致。

最后,我猜测论坛上的大多数人都不知道“免费图片”,我相信这就是你所说的用于加载纹理的内容。如果出现纹理问题,则无法看到,因为使用此第三方库代表您设置纹理的不透明性。

如果他们混淆了纹理ID,请设置不支持的包装模式,不要将缩小过滤器设置为与预期的mipmapping(开/关)一致,不启用纹理,或者设置纹理环境模式,使得使用基本几何颜色的调制并不像您期望的那样 - 所有这些都会使纹理不起作用/看起来不起作用。

要进行故障排除,只需使用库进行纹理加载,并使用它们提供的纹理ID。然后自己设置过滤模式和纹理环境。在排除故障时关闭mipmapping。纹理化时,不完整的mipmap链是一个非常常见的错误。

您还可以关闭每个片段操作以简化故障排除。禁用混合,深度测试和剪裁。

假设您的纹理是二维的力量或您的实现支持NPOT,请在绘制前立即尝试这些设置

glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glDisable(GL_SCISSOR_TEST);
glColor4f(1.0f,1.0f,1.0f,1.0f);
glBindTexture(GL_TEXTURE_2D,texID);
glTexEnvi(GL_TEXTURE_ENV_MODE,GL_REPLACE); //关闭调制
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //关闭mipmapping
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); //关闭重复
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);

答案 1 :(得分:1)

glClientActiveTexture(GL_TEXTURE0+textueIDs[0]);

你想在这做什么?

活动纹理单元与随机纹理对象无关。