在 iPhone 上加载 openGL 游戏的屏幕?

Posted

技术标签:

【中文标题】在 iPhone 上加载 openGL 游戏的屏幕?【英文标题】:Loading screen for an openGL game on iphone? 【发布时间】:2009-11-12 18:11:07 【问题描述】:

我正在为 iPhone 开发一个 openGL,虽然一切都很好,但我必须在游戏的某些部分等待大约一秒钟,因为它使用了大量的精灵表。有没有办法为这些部分创建一个加载屏幕?或者有什么方法可以知道某个纹理是否已经用 openGL 完成了加载?

编辑:

我用这个函数加载我的纹理:

-(void)loadTexture:(NSString*)nombre 

CGImageRef textureImage = [UIImage imageNamed:nombre].CGImage;
if (textureImage == nil) 
    NSLog(@"Failed to load texture image");
    return;


textureWidth = NextPowerOfTwo(CGImageGetWidth(textureImage));   
textureHeight = NextPowerOfTwo(CGImageGetHeight(textureImage));

imageSizeX= CGImageGetWidth(textureImage);
imageSizeY= CGImageGetHeight(textureImage);

GLubyte *textureData = (GLubyte *)calloc(1,textureWidth * textureHeight * 4); // Por 4 pues cada pixel necesita 4 bytes, RGBA

CGContextRef textureContext = CGBitmapContextCreate(textureData, textureWidth,textureHeight,8, textureWidth * 4,CGImageGetColorSpace(textureImage),kCGImageAlphaPremultipliedLast );
CGContextDrawImage(textureContext, CGRectMake(0.0, 0.0, (float)textureWidth, (float)textureHeight), textureImage);

CGContextRelease(textureContext);

glGenTextures(1, &textures[0]);

glBindTexture(GL_TEXTURE_2D, textures[0]);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);

free(textureData);


glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);   


我通常会根据游戏的部分加载我需要的纹理,例如,一个或两个 1024x1024 的纹理作为精灵表对大多数关卡来说就足够了,但在某些关卡中,例如boss战,我加载大约 5 或 6 个纹理(boss 很大,并且有大量不同的攻击),游戏一次加载所有这些纹理大约需要 2 或 3 秒。

【问题讨论】:

由于正在加载纹理(通过OpenGL),你应该知道你的代码何时完成。你如何加载纹理?代码示例会很有帮助。 这个问题听起来很像你自己没有实现 GL 的东西。 @Andreas:我在问题中添加了一些代码,希望现在更清楚。谢谢。 @Till: ?. 对不起,如果这听起来很刺耳 - 我不确定您是否可能使用了某个 3rd 方引擎,因此不知道引擎盖下发生了什么。 【参考方案1】:

正如 Till 所解释的,由于您正在同步加载纹理,因此将在“loadTexture”完成后加载。

通过 OpenGL 在另一个线程中渲染到屏幕,同时通过 OpenGL 加载可能会很快变得非常混乱。

A - 经常使用 - hack 是在纹理加载之间更新屏幕:

    渲染 0% 屏幕 加载纹理 渲染 10% 的屏幕 加载纹理 根据需要重复

通过一些额外的工作,很容易生成一个包含有关加载时间信息的小表,因此“x%”接近事实;)

我们通常会自动执行此步骤,并在发布新版本之前执行“加载”运行,我们会在其中记录加载什么资源以及需要多长时间。

【讨论】:

【参考方案2】:

由于您正在同步加载纹理,因此很明显,一旦您的 loadTexture 方法完成,该纹理的加载就完成了。

编辑/添加: 您应该在代码中避免/更改几件事。并不是说这真的能解决你的实际问题,只是一个一般性的建议......

第一个:不要使用 imageNamed 来加载纹理图像——这通常是个坏主意。使用 imageWithContentsOfFile,因为这样不会占用图像缓存中的数据,而这些数据无论如何都不会被重用。

第二个:一旦纹理被加载,Apple 称之为“加热纹理”的术语 - 基本上是短暂地使用该纹理进行快速而肮脏(甚至是屏幕外)的渲染。这样,您可以确保纹理将完全可用,并且在进行第一次“真实”渲染时不会施加额外的惩罚。我们说的是毫秒级的惩罚 - 所以不是很大但很明显。

3rd:尝试将纹理加载转移到应用程序空闲的点 - 例如。在启动屏幕中等待用户输入 - 但不要在 applicationDidFinishLaunching 方法中这样做。

这里有一个问题要问您 - 为什么在渲染/关卡内时加载纹理。为什么不预加载您可能需要的所有内容?您最多可以使用 24mb 的纹理内存而不会造成任何损失(嗯,减去 fbo 内存)。

【讨论】:

谢谢。关于如何使加载不那么烦人的任何想法,也许只是在屏幕上绘制一个小的加载动画并在我的方法完成加载纹理后立即删除它?或任何其他建议? @Til:“为什么你在渲染/关卡时加载纹理。为什么不预加载你可能需要的所有东西?你可以使用多达 24mb 的纹理内存而不会施加任何惩罚(嗯,减去fbo 内存)。”我最初习惯于在开始时预加载所有纹理……但每当我尝试一次加载太多纹理时,该应用程序就把我踢了出去(我总共有大约 10 MB 的 .png 纹理!)。我想一次预加载我所有的纹理,但我不知道如何......【参考方案3】:

或者,您可以在加载纹理时简单地显示 UIImageView 动画。这具有绘制单独威胁的特殊好处......这是一种特殊情况,就像 UIActivityIndi​​catorView (微调器)一样。我不确定 Apple 在技术上是如何实现这一点的,但效果很好。

唯一的问题是您需要将加载动画帧保存在单独的文件中,而不是在精灵表中。

http://developer.apple.com/library/ios/#documentation/uikit/reference/UIImageView_Class/Reference/Reference.html

【讨论】:

以上是关于在 iPhone 上加载 openGL 游戏的屏幕?的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 加载和渲染 png 到屏幕

iPhone 编程游戏

OpenGL 中的离屏帧缓冲区

如何使用openGL在屏幕上显示加载的纹理

在Android应用中正确加载资源(使用openGL)

具有 OpenGL 和 C++ 的 2D 平台游戏相机