OpenGL中的动态图块显示优化

| 我正在研究具有动态生成地形的基于图块的自上而下的2D游戏,并开始(重新)编写OpenGL中的图形引擎。该游戏使用LWJGL用Java编写,我希望它保持相对独立于平台的状态,并且可以在较旧的计算机上玩。 目前,我正在使用即时模式进行绘制,但是对于最简单的场景,这显然太慢了。 绘制的对象有两种基本类型:“图块”(即世界)和“雪碧”(几乎所有其他东西)(实体,项目,效果等)。 这些图块的大小为20 * 20像素,并以大块形式存储(40 * 40个图块)。像Minecraft一样,地形生成是完全完成的。 我现在使用的方法是遍历播放器附近的9个块,然后遍历内部的每个图块,为图块纹理绘制一个四边形,并根据材料选择附加的四边形。 结束时速度很慢,但是简单的视线检查可以将FPS提升5-10倍。 为了优化这一点,我研究了使用VBO和四方带,但是当地形变化时我遇到了一个问题。这并非在每一帧都发生,但也不是非常罕见的事件。 一种简单的方法是在每次更改时删除并重建块的VBO。不过,这似乎并不是最好的方法。我读到VBO可以是“动态的”,可以更改其内容。如何做到这一点,以及可以在其中有效地更改哪些数据?还有其他有效绘制世界的方法吗? 目前,另一种类型的精灵是使用四边形绘制的,该四边形具有从精灵表映射的纹理。因此,通过更改纹理坐标,我什至可以为它们设置动画。这是做ania杀的正确方法吗? 目前,即使是非常大量的精灵也不会降低游戏速度,而且通过了解VBO,我可以进一步提高它们的速度,但是我还没有看到任何可靠的教程有效的方法。有人知道吗? 谢谢您的帮助!     
已邀请:
目前,我正在使用即时模式进行绘制,但是对于最简单的场景,这显然太慢了。 我不同意。除非您要绘制很多图块(每帧数以万计),否则即时模式对您来说就很好了。 无论如何,关键是您必须要做的就是获得良好的性能:纹理图集。您所有的图块都应存储在单个纹理中。渲染时,可以使用纹理坐标将不同的图块从该纹理中拉出。因此,如果这是您的渲染循环现在的样子:
for(tile in tileList) //Pseudocode. Not actual C++
{
    glBindTexture(GL_TEXTURE_2D, tile.texture);
    glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 0.0f);
        glVertex2fv(tile.lowerLeft);
        glTexCoord2f(0.0f, 1.0f);
        glVertex2fv(tile.upperLeft);
        glTexCoord2f(1.0f, 1.0f);
        glVertex2fv(tile.upperRight);
        glTexCoord2f(1.0f, 0.0f);
        glVertex2fv(tile.lowerRight);
    glEnd();
}
您可以将其转换为:
glBindTexture(GL_TEXTURE_2D, allTilesTexture);
glBegin(GL_QUADS);
for(tile in tileList) //Still pseudocode.
{
    glTexCoord2f(tile.texCoord.lowerLeft);
    glVertex2fv(tile.lowerLeft);
    glTexCoord2f(tile.texCoord.upperLeft);
    glVertex2fv(tile.upperLeft);
    glTexCoord2f(tile.texCoord.upperRight);
    glVertex2fv(tile.upperRight);
    glTexCoord2f(tile.texCoord.lowerRight);
    glVertex2fv(tile.lowerRight);
}
glEnd();
如果您已经在使用纹理图集,但仍无法获得令人满意的性能,则可以继续缓冲对象等。但是,如果不先执行此操作,则缓冲对象将无法获得更好的性能。 如果您的所有图块都无法适合单个纹理,则您需要执行以下两项操作之一:使用多个纹理(在一个glBegin / glEnd对中为每个纹理渲染尽可能多的图块),或使用纹理数组。纹理数组仅在OpenGL 3.0级别的硬件中可用。这意味着任何Radeon HDxxxx或GeForce 8xxxx或更高版本。 您提到您有时会在图块的顶部渲染“功能”。这些功能可能会使用混合和不同于常规图块的glTexEnv模式。在这种情况下,您需要找到将相似功能组合到单个glBegin / glEnd对中的方法。 正如您可能从中收集到的那样,性能的关键是使调用glBindTexture和glBegin / glEnd的次数最小化。在每个glBegin / glEnd中做尽可能多的工作。 如果您希望继续使用基于缓冲区的方法(并且仅当纹理图集方法不能使您的性能达到标准时就应该打扰),这非常简单。将所有图块“块”放入单个缓冲区对象中。不要为每个缓冲区创建缓冲区;没有真正的理由这样做,而且40x40瓦片的顶点数据值只有12,800字节。您可以在单个1MB缓冲区中放入81个这样的块。这样,您只需为地形调用glBindBuffer。同样,这可以节省您的性能。 我将需要更多地了解您有时用来建议优化它们的“功能”。但是对于动态缓冲区,我不会担心。只需使用glBufferSubData更新有问题的缓冲区的一部分即可。如果事实证明这很慢,则可以使用多种方法来加快速度。但是除非您知道这是必要的,否则您不应该打扰,因为它们很复杂。 Sprite可能从缓冲区对象方法中受益最少。在即时模式下,它实际上没有任何收获。即使您要渲染数百个,每个对象也将具有自己的转换矩阵。这意味着每个人都必须是一个单独的抽奖电话。因此也可能是glBegin / glEnd。     

要回复问题请先登录注册