OpenGL - 重新排序渲染方法后崩溃

Posted

技术标签:

【中文标题】OpenGL - 重新排序渲染方法后崩溃【英文标题】:OpenGL - crash after reorder rendering methods 【发布时间】:2013-10-04 20:32:14 【问题描述】:

正如标题所说,我的问题是当我渲染一个“对象”,尤其是地形,并且在水网格之后,它很顺利,但是如果我只是将地形渲染放在水渲染之后,它会与这个错误:

已解决 - 文本底部。

Pan3Da Engine.exe 中 0x55C3B970 (atioglxx.dll) 处的未处理异常: 0xC0000005:访问冲突读取位置0x00000000。

    void PNDHEIGHTMAP::p_renderwater()

    waterShader->bindShader();
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D,waterReflection.fbo_texture);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D,waterRefraction.fbo_texture);
    glActiveTexture(GL_TEXTURE5);
    glBindTexture(GL_TEXTURE_2D,waterGlobalReflection.fbo_texture);
    glActiveTexture(GL_TEXTURE6);
    glBindTexture(GL_TEXTURE_2D,waterDepthBufferID);

    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D,water_normal_map1);
    glActiveTexture(GL_TEXTURE3);
    glBindTexture(GL_TEXTURE_2D,water_normal_map2);
    glActiveTexture(GL_TEXTURE4);
    glBindTexture(GL_TEXTURE_2D,water_dudv_map);

    waterShader->sendUniform("water_level",waterlevel);
    waterShader->sendUniform("reflection_texture",0);
    waterShader->sendUniform("reflection_global_texture",5);
    waterShader->sendUniform("water_depth_texture",6);
    waterShader->sendUniform("refraction_texture",1);
    waterShader->sendUniform("bump_map_1",2);
    waterShader->sendUniform("bump_map_2",3);
    waterShader->sendUniform("dudv_map",4);


    glEnableVertexAttribArray(0);
    glBindVertexArray(waterVertArrayBuffer);
    for(unsigned long indRow=0;indRow<pndwater.indexRows;indRow++)
    glDrawElements(GL_TRIANGLES,pndwater.indexRange,GL_UNSIGNED_INT,(void*)(sizeof(unsigned long)*pndwater.indexRange*indRow));  <--------crash
;

这是我的水渲染代码,地形相同,但有 2 个 VertexAttribArrays:(0) 和 (1),纹理更少。程序在最后一行崩溃。

glEnable(GL_POLYGON_OFFSET_EXT);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    glPolygonOffset(0.5f,0.5f);
    glDisable(GL_CULL_FACE);
    waterShader->bindShader();
    waterShader->sendUniform("light_position",pndskybox.light_position.x,pndskybox.light_position.y,pndskybox.light_position.z);
    waterShader->sendUniform("camera_position",camera.cameraPosition.x,camera.cameraPosition.y,camera.cameraPosition.z);
    waterShader->sendUniform("d_time",timer);
    pndheightmap.p_renderwater();
    glEnable(GL_CULL_FACE);
    glPolygonOffset(0,0);
    glDisable(GL_BLEND);
    glDisable(GL_POLYGON_OFFSET_EXT);

我不想发布所有代码,因为它很长。我用 fbo-s 渲染水的纹理。然后绑定water-shader,用贴出的方法渲染水。

我的地形也是这样:

terrainShader->bindShader();
terrainShader>sendUniform("light_position",pndskybox.light_position.x,pndskybox.light_position.y,pndskybox.light_position.z);
pndheightmap.p_rendermap_h();

我的主要渲染方式如下:

void PNDRENDER::render()

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    maprenderer.p_renderskybox();
    maprenderer.p_renderHeightMap();
    maprenderer.p_renderWater();

但如果我改变它们:

....
maprenderer.p_renderWater();
maprenderer.p_renderHeightMap();
....

然后它崩溃了。我真的不知道什么可能导致这个问题,但这很烦人。 提前致谢!

P.S.:如果您需要,我可以发布更多代码。

【问题讨论】:

【参考方案1】:

好的,我刚刚发现了问题所在。因为我使用的是 VAO-s,所以我在其中启用了顶点属性,而不必禁用它们。但是我在 void p_renderwater() 和 p_renderterrain() 中的绘图调用之前“重新启用”了它们,所以如果我是对的,它就像是全局启用的一样,不仅在该 VAO 的范围内,而且在水中 VAO 我只使用了 1 个属性,而不是两个。如果我将地形渲染放在水之后就可以了,但如果地形方法是第一个,水会尝试接受第二个属性,因为我在全局启用了该属性。

如果我错了或误解了什么,请纠正我,但现在效果很好。

【讨论】:

以上是关于OpenGL - 重新排序渲染方法后崩溃的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 在渲染帧之前崩溃 - VBO

opengl vbo建议[关闭]

Bresenham 线抽屉在渲染任何东西之前在某个循环后崩溃? [关闭]

OpenGL glBindTexture() 崩溃

CSharpGL(36)通用的非托管数组排序方法

OpenGL 与 OpenCV 相结合的计算机视觉教程 [关闭]