Szo*_*omi 1 opengl tiles sprite
我正在开发一个基于平铺的,自上而下的2D游戏,其中包含动态生成的地形,并开始(重新)在OpenGL中编写图形引擎.游戏是用Java编写的,使用LWJGL,我更喜欢它保持相对平台无关,并且也可以在旧计算机上播放.
目前我正在使用立即模式进行绘图,但显然这对于除最简单场景之外的任何事情来说都太慢了.
绘制的对象有两种基本类型:Tiles,它是世界,Sprites,几乎所有其他东西(实体,项目,效果等).
瓷砖为20*20像素,并以块(40*40个瓷砖)存储.地形生成以完整的块完成,就像在Minecraft中一样.
我现在使用的方法是迭代播放器附近的9个块,然后在内部的每个瓦片上迭代,为瓦片纹理绘制一个四边形,并根据材料绘制特征的可选额外四边形.这最终会很慢,但是简单的视线外检查可以提供5-10倍的FPS提升.
为了优化这一点,我研究了使用VBO和quad strip,但是当地形发生变化时我遇到了问题.这不会发生在每一帧,但也不是非常罕见的事件.一个简单的方法是在每次更改时丢弃并重建块的VBO.这似乎不是最好的方式.我读到VBO可以是"动态的",允许更改其内容.如何做到这一点,以及哪些数据可以有效地在其中进行更改?有没有其他方法可以有效地吸引世界?
另一种类型的精灵,目前使用四边形绘制,其中纹理从精灵表映射.因此,通过更改纹理坐标,我甚至可以在以后设置它们的动画.这是做正义的正确方法吗?
目前即使是非常多的精灵也不会减慢游戏速度,通过了解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();
}
Run Code Online (Sandbox Code Playgroud)
你可以把它转换成这个:
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();
Run Code Online (Sandbox Code Playgroud)
如果您已经在使用纹理图集并且仍然没有获得可接受的性能,那么您可以继续缓冲对象等.但是,如果您不首先执行此操作,则无法从缓冲区对象获得更好的性能.
如果你的所有图块都不能适合单个纹理,那么你需要做两件事之一:使用多个纹理(尽可能在一个glBegin/glEnd对中渲染尽可能多的纹理),或者使用纹理数组.纹理数组仅在OpenGL 3.0级硬件中可用.这意味着任何Radeon HDxxxx或GeForce 8xxxx或更高版本.
你提到过你有时会在瓷砖上面渲染"特征".这些功能可能使用混合和常规磁贴的不同glTexEnv模式.在这种情况下,您需要找到将类似功能分组为单个glBegin/glEnd对的方法.
正如您可能从中收集的那样,性能的关键是最小化调用glBindTexture和glBegin/glEnd的次数.在每个glBegin/glEnd中尽可能多地工作.
如果您希望继续使用基于缓冲区的方法(如果纹理图集方法没有让您的性能达到标准,那么您应该只会烦恼),这非常简单.将所有tile"chunk"放入单个缓冲区对象中.不要为每一个做缓冲; 没有真正的理由这样做,40x40瓦片的顶点数据只有12,800字节.你可以将81个这样的块放在一个1MB的缓冲区中.这样,您只需为您的地形调用glBindBuffer.这再次为您节省了成绩.
我需要了解更多关于这些"功能"的信息,这些功能有时会用来建议一种优化它们的方法.但至于动态缓冲区,我不担心.只需使用glBufferSubData来更新有问题的缓冲区部分.如果结果很慢,有几种选择可以让你加快速度.但你不应该打扰,除非你知道它是必要的,因为它们很复杂.
精灵可能是从缓冲对象方法中获益最少的东西.它在立即模式下真的没什么好处的.即使你渲染了数百个,每个人都有自己的变换矩阵.这意味着每个人都必须是一个单独的平局调用.所以它也可能是glBegin/glEnd.