之前有把《OpenGL ES 应用开发指南 Android 卷》书中示例代码移植到 Windows 上的 MinGW 平台。在移植 Heightmap 示例时一开始在公司电脑上是可以运行的。回到家自己的笔记本电脑运行确神奇的崩溃了。后面初步定为是生成地形时顶点数太多导致的。我的笔记本显卡是 Geforce 820M 。生成的地形顶点有 30w+ ,按理说不会这么脆弱吧,连几十万个顶点都绘制不了。因为书中采用的生成地形并绘制的方式超级的简单,并没有做优化,这样的好处有利于初学者理解概念,如果能用 Instance Draw 绘制方式可以优化很多。
我一开始想法就是这样的,认为是程序问题,要靠优化解决问题。所以挂起了一个 issue 等之后再处理。最近碰巧有空了就想用个简单的办法来处理。于是用 GL_TRIANGLE_STRIP
来代替 GL_TRIANGLES
绘制,这样地形顶点可以减少到 13w+ ,开心而期待的编译然后运行发现还是崩了。这时真的到我郁闷了。我之所以不想尝试 Instance Draw 因为不想太过修改书中的逻辑,想尽量让示例程序简单。
后面就想用 Vertex Array Object 会不会有效果,然后就是改代码尝试。最后偶尔的机会发现下面的绘制代码中,只要 draw_heightmap
和 draw_particle
不同时进行,程序就不会崩溃。draw_particle
绘制粒子时都没有用 Buffer Object 。
static void
cb_display() {
// logv("cb_display");
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw_heightmap();
draw_skybox();
draw_particle();
glutSwapBuffers(); // or we can simply call glFlush
}
于是幡然醒悟。可能问题并不在于优化方面,而是绘制粒子系统时出了问题。然后就开始采用 Buffer Object 传递数据,想试试会不会出现奇迹。果然奇迹出现了。程序正常运行了。
这其实就是一个很普通不过的小问题。之所以还特地写篇博客是因为标记一下并不是出了问题,一定要往底层优化上面考虑。日常开发中出现了 bug ,当未能直观解决时,总会就下定论是底层问题,最后偶然机会找到原因时发现还是自己的逻辑有问题。所以当出现问题时,能静下心来认真分析写过的代码,给出客观的分析。