2013-03-06 104 views
0

我已经实现了一个简单的(慢)方法,可以模拟OpenGL即时模式绘制线条。每个框架,我添加一对顶点,这些顶点指示向量结构的行,以及添加一些指定的或默认的颜色到另一个向量结构。glDrawArrays中的大型模型崩溃

void WindowsGraphicsManager::vertex(float x, float y, float z) { 
vertices_.push_back(x); 
vertices_.push_back(y); 
vertices_.push_back(z); 
colors_.push_back(vertexColor_.getR()); 
colors_.push_back(vertexColor_.getG()); 
colors_.push_back(vertexColor_.getB()); 
colors_.push_back(vertexColor_.getA()); 
} 

然后在每帧的结尾我清除这些向量。 我的渲​​染代码如下所示:

void WindowsGraphicsManager::renderVertices(Mat4 mat) { 
if (vertices_.size() == 0) { 
    return; 
} 
static Shader* shader = (Shader*) services_->getRM()->get(
    Resource::SHADER, "openglimmediate"); 
glUseProgram(shader->getId()); 
shader->setMatrix4(Shader::WVP, mat); 
glEnableVertexAttribArray(shader->getHandle(Shader::POS)); 
glVertexAttribPointer(shader->getHandle(Shader::POS), 
    3, GL_FLOAT, GL_FALSE, 0, &vertices_[0]); 
glEnableVertexAttribArray(shader->getHandle(Shader::COL)); 
glVertexAttribPointer(shader->getHandle(Shader::COL), 
    4, GL_FLOAT, GL_FALSE, 0, &colors_[0]); 
//LOGI("Before crash."); 
//LOGI("Vertices size: %d", vertices_.size()); 
//LOGI("Colors size: %d", colors_.size()); 
//INFO: Vertices size: 607590 
//INFO: Colors size: 810120 
glDrawArrays(GL_LINES, 0, vertices_.size()/3); 
CHECK_GL_ERROR("Rendering lines."); 
//LOGI("After crash."); 
glDisableVertexAttribArray(shader->getHandle(Shader::COL)); 
glDisableVertexAttribArray(shader->getHandle(Shader::POS)); 
vertices_.clear(); 
colors_.clear(); 

}

当我添加607590辆花车(除以3个顶点)到顶点向量,渲染与调用glDrawArrays功能线崩溃。奇怪的是,当我第一次最大化窗口和渲染时,它对607590浮点模型的效果很好,虽然它仍然对〜800k场景的模型崩溃。

什么可能导致这种情况?

[编辑]在渲染顶点之前,我调用另一个方法。删除它后,渲染停止崩溃,所以我想我在这里做错了什么。

inline void WindowsGraphicsManager::renderNode(
Node* node, Mat4 mat, bool ortho) 
{ 
if (!node->getState(Node::RENDERABLE)) { 
    return; 
} 

// Retrieve model data. 
Renderable* renderable = 0; 
Resource* resource = 0; 
if (node->hasResource(Resource::SPRITE)) { 
    resource = node->getResource(Resource::SPRITE); 
    renderable = dynamic_cast<Renderable*>(resource); 
} 
else if (node->hasResource(Resource::STATIC_OBJECT)) { 
    resource = node->getResource(Resource::STATIC_OBJECT); 
    renderable = dynamic_cast<Renderable*>(resource); 
    StaticObject* so = static_cast<StaticObject*>(resource); 
    // Check for frustum culling. 
    if (so->getBoundingVolume() != 0 
     && so->getBoundingVolume()->isInFrustum(
     services_->getCamera(), node->getPos()) 
     == BoundingVolume::OUTSIDE) 
    { 
     return; 
    } 
} 
else if (node->hasResource(Resource::DYNAMIC_OBJECT)) { 
    resource = node->getResource(Resource::DYNAMIC_OBJECT); 
    renderable = dynamic_cast<Renderable*>(resource); 
} 

if (renderable == 0) { 
    LOGW("Renderable with name \"%s\" is null.", 
     node->getName().c_str()); 
    return; 
} 

// Retrieve node shader or use default. 
Shader* shader = static_cast<Shader*>(
    node->getResource(Resource::SHADER)); 
if (shader == 0) { 
    LOGW("Unable to retrieve shader for node: %s.", 
     node->getName().c_str()); 
    return; 
} 
int shaderId = shader->getId(); 

// Select shader program to use. 
glUseProgram(shaderId); 
CHECK_GL_ERROR("glUseProgram"); 

Mat4 res; 
if (!ortho) { 
    Matrix::multiply(mat, node->getMatrix(), res); 
} 
else { 
    Mat4 tmp; 
    Mat4 pos; 
    Mat4 rot; 
    Mat4 scale; 
    Vec3 p = node->getPos(); 
    Vec3 r = node->getRot(); 
    Vec3 s = node->getScale(); 
    float width = s.getX(); 
    float height = s.getY(); 
    float x = p.getX(); 
    float y = p.getY(); 
    Matrix::translate(pos, x, y, p.getZ()); 
    Matrix::rotateXYZ(rot, r.getX(), r.getY(), r.getZ()); 
    Matrix::scale(scale, width, height, 1.0f); 
    Matrix::multiply(mat, pos, res); 
    Matrix::multiply(res, rot, tmp); 
    Matrix::multiply(tmp, scale, res); 
} 
// World * View * Projection matrix. 
shader->setMatrix4(Shader::WVP, res); 
// World matrix. 
shader->setMatrix4(Shader::W, node->getMatrix()); 
// Normal matrix. 
if (shader->hasHandle(Shader::N)) { 
    Mat3 normalMatrix; 
    Matrix::toMat3(node->getMatrix(), normalMatrix); 
    shader->setMatrix3(Shader::N, normalMatrix); 
} 
// Light position. 
float* lightPos = new float[lights_.size() * 3]; 
if (lights_.size() > 0 && shader->hasHandle(Shader::LIGHT_POS)) { 
    for (UINT i = 0; i < lights_.size(); i++) { 
     Vec3& pos = lights_[i]->getPos(); 
     lightPos[i * 3 + 0] = pos.getX(); 
     lightPos[i * 3 + 1] = pos.getY(); 
     lightPos[i * 3 + 2] = pos.getZ(); 
    } 
    shader->setVector3(Shader::LIGHT_POS, lightPos, lights_.size()); 
} 
delete lightPos; 
// Light count. 
shader->setInt(Shader::LIGHT_COUNT, lights_.size()); 
//shader->setVector3(Shader::LIGHT_POS, 
// services_->getEnv()->getSunPos()->toArray()); 
// Eye position. 
shader->setVector3(Shader::EYE_POS, 
    services_->getCamera()->getPos().toArray()); 
// Fog color. 
if (shader->hasHandle(Shader::FOG_COLOR)) { 
    shader->setVector3(Shader::FOG_COLOR, 
     services_->getEnv()->getFogColor()); 
} 
// Fog density. 
shader->setFloat(Shader::FOG_DENSITY, services_->getEnv()->getFogDensity()); 
// Timer. 
shader->setFloat(Shader::TIMER, 
    (float) services_->getSystem()->getTimeElapsed()); 
// Bind combined buffer object. 
if (renderable->getCBO() > 0) { 
    int stride = renderable->getVertexStride(); 
    glBindBuffer(GL_ARRAY_BUFFER, renderable->getCBO()); 
    if (shader->hasHandle(Shader::POS)) { 
     glEnableVertexAttribArray(shader->getHandle(Shader::POS)); 
     glVertexAttribPointer(
      shader->getHandle(Shader::POS), 3, GL_FLOAT, GL_FALSE, 
      stride, ((char*) 0) + renderable->getPosOffset()); 
    } 
    if (renderable->getNormalOffset() != -1 
     && shader->hasHandle(Shader::NORMAL)) { 
     glEnableVertexAttribArray(shader->getHandle(Shader::NORMAL)); 
     glVertexAttribPointer(
      shader->getHandle(Shader::NORMAL), 3, GL_FLOAT, GL_FALSE, 
      stride, ((char*) 0) + renderable->getNormalOffset()); 
    } 
    if (renderable->getUVOffset() != -1 && shader->hasHandle(Shader::UV)) { 
     glEnableVertexAttribArray(shader->getHandle(Shader::UV)); 
     glVertexAttribPointer(
      shader->getHandle(Shader::UV), 2, GL_FLOAT, GL_FALSE, 
      stride, ((char*) 0) + renderable->getUVOffset()); 

    } 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
} 
else { 
    return; 
} 
// Bind cube map. 
if (node->hasResource(Resource::CUBE_MAP) 
    && shader->hasHandle(Shader::CUBE_MAP)) { 
    glActiveTexture(GL_TEXTURE0); 
    CHECK_GL_ERROR("glActiveTexture"); 
    CubeMap* t = static_cast<CubeMap*>(
     node->getResource(Resource::CUBE_MAP)); 
    glBindTexture(GL_TEXTURE_CUBE_MAP, t->getId()); 
    CHECK_GL_ERROR("glBindTexture"); 
    glUniform1i(shader->getHandle(Shader::CUBE_MAP), 0); 
    CHECK_GL_ERROR("glUniform1i"); 
} 

int hTextures[8]; 
hTextures[0] = glGetUniformLocation(shader->getId(), 
    SHADER_MAIN_TEXTURE); 
// Bind the texture. 
vector<Resource*> textures = node->getResources(Resource::TEXTURE_2D); 
UINT size = textures.size() < 8 ? textures.size() : 7; 
UINT texture = 0; 
for (UINT i = 0; i < size; i++) { 
    texture = i + 1; 
    const string& name = textures[i]->getName(); 
    Texture2D* tex = static_cast<Texture2D*>(textures[i]); 
    string textName = name.substr(0, name.length() - 4); 

    hTextures[texture] = glGetUniformLocation(shader->getId(), 
     textName.c_str()); 
    if (hTextures[texture] == -1) { 
     continue; 
    } 
    glActiveTexture(GL_TEXTURE0 + i + 1); 
    CHECK_GL_ERROR("glActiveTexture"); 
    glBindTexture(GL_TEXTURE_2D, tex->getId()); 
    CHECK_GL_ERROR("glBindTexture"); 
    glUniform1i(hTextures[texture], texture); 
    CHECK_GL_ERROR("glUniform1i"); 
} 

// Render node. 
//  BoundingVolume* volume = (*model->getBoundingVolumes())[i]; 
//  if (model->hasBoundingVolumes()) { 
//   if (volume->isInFrustum(services_->getCamera(), node) 
//    == BoundingVolume::OUTSIDE) { 
//    continue; 
//   } 
//  } 

int renderType; 
switch (renderable->getRenderType()) { 
    case Renderable::RENDER_TYPE_POINTS: 
     renderType = GL_POINTS; 
     //glPointSize(renderable->getPointSize()); 
    break; 
    case Renderable::RENDER_TYPE_LINES: 
     renderType = GL_LINES; 
     glLineWidth(renderable->getLineWidth()); 
    break; 
    case Renderable::RENDER_TYPE_TRIANGLE_FAN: 
     renderType = GL_TRIANGLE_FAN; 
    break; 
    case Renderable::RENDER_TYPE_TRIANGLE_STRIP: 
     renderType = GL_TRIANGLE_STRIP; 
    break; 
    default: 
     renderType = GL_TRIANGLES; 
    break; 
} 

if (renderable->getWindingType() == Renderable::WINDING_TYPE_CCW) { 
    glFrontFace(GL_CCW); 
} 
else { 
    glFrontFace(GL_CW); 
} 

if (renderable->getCullFace()) { 
    glEnable(GL_CULL_FACE); 
} 
else { 
    glDisable(GL_CULL_FACE); 
} 
UINT renderCount = renderable->getRenderCount(); 
int lastTexture = 0; 
for (UINT i = 0; i < renderable->getRenderCount(); i++) { 
    renderable->setRenderable(i); 
    // Ambient material color. 
    if (shader->hasHandle(Shader::AMBIENT)) { 
     shader->setVector3(Shader::AMBIENT, 
      renderable->getAmbient().toArray()); 
    } 
    // Diffuse material color. 
    if (shader->hasHandle(Shader::DIFFUSE)) { 
     shader->setVector3(Shader::DIFFUSE, 
      renderable->getDiffuse().toArray()); 
    } 
    // Specular material color. 
    if (shader->hasHandle(Shader::SPECULAR)) { 
     shader->setVector3(Shader::SPECULAR, 
      renderable->getSpecular().toArray()); 
    } 
    // Specular material color intensity. 
    shader->setFloat(Shader::SPECULARITY, renderable->getSpecularity()); 
    // Model transparency. 
    shader->setFloat(Shader::TRANSPARENCY, renderable->getTransparency()); 
    // Bind main texture. 
    if (renderable->getTexture() != lastTexture 
     && hTextures[0] != -1) { 
     lastTexture = renderable->getTexture(); 
     if (shader->hasHandle(Shader::MAIN_TEXTURE)) { 
      if (lastTexture == 0) { 
       shader->setFloat(Shader::MAIN_TEXTURE, 0.0f); 
      } 
      else { 
       shader->setFloat(Shader::MAIN_TEXTURE, 1.0f); 
      } 
     } 
     glActiveTexture(GL_TEXTURE0); 
     CHECK_GL_ERROR("glActiveTexture"); 
     glBindTexture(GL_TEXTURE_2D, renderable->getTexture()); 
     CHECK_GL_ERROR("glBindTexture"); 
     glUniform1i(hTextures[0], 0); 
     CHECK_GL_ERROR("glUniform1i"); 
    } 
    if (renderable->getIBO() > 0) { 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 
      renderable->getIBO()); 
     if (renderable->getIndexType() == 
      Renderable::INDEX_TYPE_USHORT) { 
      glDrawElements(renderType, 
       renderable->getIndexCount(), 
       GL_UNSIGNED_SHORT, 
       0); 
      CHECK_GL_ERROR("glDrawElements"); 
     } 
     else { 
      glDrawElements(renderType, 
       renderable->getIndexCount(), 
       GL_UNSIGNED_INT, 
       0); 
      CHECK_GL_ERROR("glDrawElementsInt"); 
     } 
    } 
    else { 
     glDrawArrays(renderType, 0, renderable->getVertexCount()/3); 
     CHECK_GL_ERROR("glDrawArrays"); 
    } 
} 
//// Unbind the cube map. 
//if (node->hasResource(Resource::CUBE_MAP)) { 
// glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 
//} 
//// Unbind the textures. 
//for (UINT i = 0; i < 8; i++) { 
// glActiveTexture(GL_TEXTURE0 + i); 
// CHECK_GL_ERROR("glActiveTexture"); 
// glBindTexture(GL_TEXTURE_2D, 0); 
//} 
} 

回答

0

所以问题glBindBuffer()这部分代码后呼叫:

// Bind combined buffer object. 
if (renderable->getCBO() > 0) { 
    int stride = renderable->getVertexStride(); 
    glBindBuffer(GL_ARRAY_BUFFER, renderable->getCBO()); 
    if (shader->hasHandle(Shader::POS)) { 
     glEnableVertexAttribArray(shader->getHandle(Shader::POS)); 
     glVertexAttribPointer(
      shader->getHandle(Shader::POS), 3, GL_FLOAT, GL_FALSE, 
      stride, ((char*) 0) + renderable->getPosOffset()); 
    } 
    if (renderable->getNormalOffset() != -1 
     && shader->hasHandle(Shader::NORMAL)) { 
     glEnableVertexAttribArray(shader->getHandle(Shader::NORMAL)); 
     glVertexAttribPointer(
      shader->getHandle(Shader::NORMAL), 3, GL_FLOAT, GL_FALSE, 
      stride, ((char*) 0) + renderable->getNormalOffset()); 
    } 
    if (renderable->getUVOffset() != -1 && shader->hasHandle(Shader::UV)) { 
     glEnableVertexAttribArray(shader->getHandle(Shader::UV)); 
     glVertexAttribPointer(
      shader->getHandle(Shader::UV), 2, GL_FLOAT, GL_FALSE, 
      stride, ((char*) 0) + renderable->getUVOffset()); 
} 
glBindBuffer(GL_ARRAY_BUFFER, 0); 

我不得不glBindBuffer()移动到同样的方法结束了,我也写glDisableVertexAttribArray的位置,正常和UV缓冲液。这解决了这个问题,但我不知道为什么。我认为没有必要为VBO调用glDisableVertexAttribArray。 我认为这个问题是NVIDIA驱动程序特有的,并给nvoglv32.dll第一次机会例外。