【发布时间】:2011-01-16 05:33:28
【问题描述】:
我正在尝试从 3ds Max 正确导入 .OBJ 文件。我在这里的上一个问题中使用 glBegin() 和 glEnd() 得到了这个工作,但显然性能很差,所以我现在正在尝试使用 glDrawElements。
我正在导入棋盘、棋子等。棋盘、棋子和棋盘上的每个方格都存储在结构体GroupObject 中。我存储数据的方式是这样的:
struct Vertex
{
float position[3];
float texCoord[2];
float normal[3];
float tangent[4];
float bitangent[3];
};
struct Material
{
float ambient[4];
float diffuse[4];
float specular[4];
float shininess; // [0 = min shininess, 1 = max shininess]
float alpha; // [0 = fully transparent, 1 = fully opaque]
std::string name;
std::string colorMapFilename;
std::string bumpMapFilename;
std::vector<int> indices;
int id;
};
//A chess piece or square
struct GroupObject
{
std::vector<Material *> materials;
std::string objectName;
std::string groupName;
int index;
};
所有顶点都是三角形,所以总是有 3 个点。当我遍历 obj 文件中的面 f 部分时,我将 v0、v1 和 v2 存储在 Material->indices 中。 (我正在做 v[0-2] - 1 来说明 obj 文件是基于 1 的,而我的向量是基于 0 的。
所以当我使用渲染方法时,我试图循环遍历每个对象,该对象循环遍历附加到该对象的每个材质。我设置了材质信息并尝试使用 glDrawElements。但是,屏幕是黑色的。当我使用与该材料相关的所有索引循环遍历每种不同的材料时,我能够很好地绘制模型,并且它可以很好地绘制模型。这一次,我可以使用模板缓冲区来选择GroupObjects,我改变了循环,但屏幕是黑色的。
更新 将原始渲染循环替换为当前渲染循环及其结果的屏幕截图 这是我的渲染循环。我唯一更改的是 for 循环,因此它们依次遍历每个对象和对象中的每种材质。
void GLEngine::drawModel()
{
ModelTextures::const_iterator iter;
GLuint texture = 0;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Vertex arrays setup
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer(3, GL_FLOAT, model.getVertexSize(), model.getVertexBuffer()->position);
glEnableClientState( GL_NORMAL_ARRAY );
glNormalPointer(GL_FLOAT, model.getVertexSize(), model.getVertexBuffer()->normal);
glClientActiveTexture( GL_TEXTURE0 );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, model.getVertexSize(), model.getVertexBuffer()->texCoord);
glUseProgram(blinnPhongShader);
objects = model.getObjects();
// Loop through objects...
for( int i=0 ; i < objects.size(); ++i )
{
ModelOBJ::GroupObject *object = objects[i];
// Loop through materials used by object...
for( int j=0 ; j<object->materials.size() ; ++j )
{
ModelOBJ::Material *pMaterial = object->materials[j];
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, pMaterial->ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pMaterial->diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, pMaterial->specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, pMaterial->shininess * 128.0f);
if (pMaterial->bumpMapFilename.empty())
{
//Bind the color map texture.
texture = nullTexture;
if (enableTextures)
{
iter = modelTextures.find(pMaterial->colorMapFilename);
if (iter != modelTextures.end())
texture = iter->second;
}
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
//Update shader parameters.
glUniform1i(glGetUniformLocation(
blinnPhongShader, "colorMap"), 0);
glUniform1f(glGetUniformLocation(
blinnPhongShader, "materialAlpha"), pMaterial->alpha);
}
//glDrawElements( GL_TRIANGLES, pMaterial->triangleCount * 3, GL_UNSIGNED_INT, &pMaterial->indices.front() );
glDrawElements( GL_TRIANGLES, pMaterial->triangleCount * 3, GL_UNSIGNED_INT, model.getIndexBuffer() + pMaterial->startIndex );
}
}
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
glDisable(GL_BLEND);
}
以下是上述方法绘制的内容: http://img844.imageshack.us/img844/3793/chess4.png
我不知道我错过了什么重要的。如果它也有帮助,这里是我读取“f”面线并将信息存储在 pMaterial->indices 中的 obj 导入器中的位置。
else if (sscanf(buffer, "%d/%d/%d", &v[0], &vt[0], &vn[0]) == 3) // v/vt/vn
{
fscanf(pFile, "%d/%d/%d", &v[1], &vt[1], &vn[1]);
fscanf(pFile, "%d/%d/%d", &v[2], &vt[2], &vn[2]);
v[0] = (v[0] < 0) ? v[0] + numVertices - 1 : v[0] - 1;
v[1] = (v[1] < 0) ? v[1] + numVertices - 1 : v[1] - 1;
v[2] = (v[2] < 0) ? v[2] + numVertices - 1 : v[2] - 1;
currentMaterial->indices.push_back(v[0]);
currentMaterial->indices.push_back(v[1]);
currentMaterial->indices.push_back(v[2]);
更新 2
【问题讨论】:
-
嗯,肯定有一个问题是您应该像上次引用中那样执行 glDrawElements。或者更好,&pMaterial->indices.front()。我已经看了一段时间了,以为我发现了其他问题,但我仍然没有真正想出其他任何问题。
-
嗯...也许它正在绘制,但由于材料或纹理的问题,它在您绘制的内容之上绘制黑色?说到纹理,我看不到你绑定纹理,这很可能是问题所在!此外,您检查是否应该禁用底部的东西,但它们在顶部启用而不检查。
-
我可能是错的,但在我看来,您不需要 DrawElements 行上的 *3。因为您不只是绘制顶点,而是从所有数组中绘制,当您指定每个数组时,您告诉它有多少是一个“元素”。编辑:哦,我所说的启用/禁用是 glEnableClientState 的东西;你在顶部启用了所有这些,但不一定在底部禁用所有它们(真的你应该检查两个地方)。
-
我猜这只是意味着你两次画了一堆东西,看起来并没有什么不同。
-
我同意现在问题似乎不在绘图方法上。我克隆了 git 存储库,但我还没有编译它,因为我在 Mac 上并且我不想启动我的 VM 来运行 Windows(它使用大量 ram)。