我想在iPhone上制作2D平铺背景系统。获取tilemap和tileset图像并将其转换为屏幕上的完整地图的东西。
只是做一些搞乱,我的第一个方法是为每个瓷砖创建一个多边形。这工作正常,直到我开始测试400多边形左右,然后它开始运行非常缓慢。我只是想知道 - 几种多边形的这种方法是不是要走的路?或者我做错了什么?如果需要,我会稍后发布代码,但我的主要问题是“400个小多边形在iPhone上运行缓慢还是我做错了什么?”
我还考虑了另一种方法,即在初始化期间,通过tilemap / tilesets之外的代码创建地图纹理,然后将其粘贴在一个大的多边形上。所以,是啊...关于我应该怎样做这样的事情的任何反馈?
我知道有人会提到这一点 - 我考虑过尝试cocos2d,但我有理由不去那条路。
答案 0 :(得分:1)
你的问题几乎可以肯定你是400次绑定纹理,而不是其他任何东西。你应该将所有的瓷砖放在一个大的纹理图集/精灵表中,而不是重新绑定你的纹理,你应该只绑定你的图集一次,然后绘制它的一小部分。如果你这样做,你应该能够绘制数千个没有真正减速的图块。
你可以像这样画出你的精灵:
//Push the matrix so we can keep it as it was previously.
glPushMatrix();
//Store the coordinates/dimensions from a rectangle.
float x = CGRectGetMinX(rect);
float y = CGRectGetMinY(rect);
float w = CGRectGetWidth(rect);
float h = CGRectGetHeight(rect);
float xOffset = x;
float yOffset = y;
if (rotation != 0.0f)
{
//Translate the OpenGL context to the center of the sprite for rotation.
glTranslatef(x+w/2, y+h/2, 0.0f);
//Apply the rotation over the Z axis.
glRotatef(rotation, 0.0f, 0.0f, 1.0f);
//Have an offset for the top left corner.
xOffset = -w/2;
yOffset = -h/2;
}
// Set up an array of values to use as the sprite vertices.
GLfloat vertices[] =
{
xOffset, yOffset,
xOffset, yOffset+h,
xOffset+w, yOffset+h,
xOffset+w, yOffset,
};
// Set up an array of values for the texture coordinates.
GLfloat texcoords[] =
{
CGRectGetMinX(clippingRect), CGRectGetMinY(clippingRect),
CGRectGetMinX(clippingRect), CGRectGetHeight(clippingRect),
CGRectGetWidth(clippingRect), CGRectGetHeight(clippingRect),
CGRectGetWidth(clippingRect), CGRectGetMinY(clippingRect),
};
//If the image is flipped, flip the texture coordinates.
if (flipped)
{
texcoords[0] = CGRectGetWidth(clippingRect);
texcoords[2] = CGRectGetWidth(clippingRect);
texcoords[4] = CGRectGetMinX(clippingRect);
texcoords[6] = CGRectGetMinX(clippingRect);
}
//Render the vertices by pointing to the arrays.
glVertexPointer(2, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
// Set the texture parameters to use a linear filter when minifying.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//Allow transparency and blending.
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//Enable 2D textures.
glEnable(GL_TEXTURE_2D);
//Bind this texture.
if ([Globals getLastTextureBound] != texture)
{
glBindTexture(GL_TEXTURE_2D, texture);
}
//Finally draw the arrays.
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
//Restore the model view matrix to prevent contamination.
glPopMatrix();
我使用的两个CGRect只是为了放心。您可以指定绘制图像的X,Y,宽度和高度,还可以使用clippingRect指定要在图像中绘制的位置。使用裁剪矩形,(0,0,1,1)是整个图像,而(0,0,0.25,0.25)只绘制左上角。通过更改剪切矩形,您可以将各种不同的图块放在同一纹理中,然后您只需要绑定一次。方式更便宜。
答案 1 :(得分:0)
也可能使用glDrawTex
扩展名。
答案 2 :(得分:0)
斯坦福大学iTune大学有一个关于优化iPhone的OpenGL的播客。
但基本的想法是这些:
批量几何,将各种顶点数组合成一个大的顶点数组。这应该将x个gl 指针调用的数量减少为单个gl 指针调用。
纹理地图集,对所有不同的图块使用单个纹理,差异是每个图块使用的区域。只需将纹理绑定到所有图块的纹理即可。
Interleaved Arrays,将点的各个部分(例如顶点,纹理坐标,颜色)组合成一个数组。这应该将gl *指针调用减少到一次调用。
索引三角形,允许您重复使用几何信息
如果可能的话,使用Short而不是Float来获取几何信息,因为它更小。
这只是一般的opengl优化指南。至于瓷砖引擎,嗯..
我认为这是我到目前为止所能想到的。
答案 3 :(得分:0)
Scott,TexParameter设置只需要每个纹理完成一次。但是,这不是您放缓的原因。
建立一个索引列表,并为整个tile集调用glDrawArrays一次会好得多。顶点数组的目标是允许您在一个步骤中尽可能多地绘制。
应该避免使用glDrawTex,因为它会迫使你进入非常低效的一次性思维模式。答案 4 :(得分:0)
我做了什么来加快我的应用程序。在我加载我的水平之后。我在地图上用瓷砖创建了一个图册。然后我检查每一帧,看相机是否移动。如果它确实那么我只是传递glTranslatef并立即移动整个地图。如果只有动态对象在地图上移动,那么我只是在顶点数组图集中更新该对象。这个系统非常有效,因为我可以绘制大量没有帧率下降的瓷砖。
答案 5 :(得分:0)
只应在初始化时启用客户端状态,并且在创建纹理对象时也应调用glTexParameteri函数。 所有glEnable函数都不会被缓存,这意味着它将设置状态,即使它已经设置为该值。 所有这些小事都会加起来,让你慢下来。
BR