objective-c - 如何在 iPhone OpenGL ES 粒子系统中绘制 1000 多个粒子(具有独特的旋转、缩放和 Alpha)而不减慢游戏速度?

标签 objective-c ios opengl-es particle-system

我正在使用 OpenGL ES 1.1 开发一款 iPhone 游戏。在这个游戏中,我有角色被射击时会发出的血液粒子,因此屏幕上可以同时出现 1000+ 血液粒子。问题是,当我要渲染的粒子超过 500 个时,游戏的帧速率会大幅下降。

目前,每个粒子都使用 glDrawArrays(..) 渲染自身,我知道这是速度减慢的原因。所有粒子共享相同的纹理图集。

那么减少绘制大量粒子造成的速度减慢的最佳选择是什么?以下是我找到的选项:

  1. 将所有血液粒子分组在一起,并使用单个 glDrawArrays(..) 调用来渲染它们 --如果我使用此方法,是否有办法为每个粒子有自己的旋转和阿尔法?或者使用此方法时所有这些都必须具有相同的旋转?如果我无法渲染具有独特旋转的粒子,那么我就无法使用此选项。
  2. 在 OpenGL ES 2.0 中使用点 Sprite 。我尚未使用 OpenGL ES 2.0,因为我需要在规定的期限内在 App Store 上发布我的游戏。要使用 OpenGL ES 需要进行初步研究,不幸的是我没有时间进行。我将在以后的版本中升级到 OpenGL ES 2.0,但对于第一个版本,我只想使用 1.1。

这是每个粒子本身的渲染。这是我最初的粒子渲染方法,导致游戏在渲染 500 多个粒子后帧率显着下降。

// original method: each particle renders itself.
// slow when many particles must be rendered

[[AtlasLibrary sharedAtlasLibrary] ensureContainingTextureAtlasIsBoundInOpenGLES:self.containingAtlasKey];

glPushMatrix();

// translate
glTranslatef(translation.x, translation.y, translation.z);

// rotate
glRotatef(rotation.x, 1, 0, 0);
glRotatef(rotation.y, 0, 1, 0);
glRotatef(rotation.z, 0, 0, 1);

// scale
glScalef(scale.x, scale.y, scale.z);

// alpha
glColor4f(1.0, 1.0, 1.0, alpha);

// load vertices
glVertexPointer(2, GL_FLOAT, 0, texturedQuad.vertices);
glEnableClientState(GL_VERTEX_ARRAY);

// load uv coordinates for texture
glTexCoordPointer(2, GL_FLOAT, 0, texturedQuad.textureCoords);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

// render
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glPopMatrix();

然后我使用了方法 1,但使用此方法(据我所知),粒子不能具有唯一的旋转、缩放或 alpha。

    // this is method 1: group all particles and call glDrawArrays(..) once

    // declare vertex and uv-coordinate arrays
    int numParticles = 2000;
    CGFloat *vertices = (CGFloat *) malloc(2 * 6 * numParticles * sizeof(CGFloat));
    CGFloat *uvCoordinates = (CGFloat *) malloc (2 * 6 * numParticles * sizeof(CGFloat));

    ...build vertex arrays based on particle vertices and uv-coordinates.
    ...this part works fine.


    // get ready to render the particles
    glPushMatrix();
    glLoadIdentity();

    // if the particles' texture atlas is not already bound in OpenGL ES, then bind it
    [[AtlasLibrary sharedAtlasLibrary] ensureContainingTextureAtlasIsBoundInOpenGLES:((Particle *)[particles objectAtIndex:0]).containingAtlasKey];

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);

    glVertexPointer(2, GL_FLOAT, 0, vertices);
    glTexCoordPointer(2, GL_FLOAT, 0, uvCoordinates);

    // render
    glDrawArrays(GL_TRIANGLES, 0, vertexIndex);

    glPopMatrix();

我会重申我的问题:
如何渲染 1000 多个粒子而不会使帧速率大幅下降,并且每个粒子仍然可以具有独特的旋转、Alpha 和缩放?

任何建设性的建议都会很有帮助,我们将不胜感激!

谢谢!

最佳答案

使用大约 1-10 个纹理,每个纹理由透明背景上的 200 个红血点组成,然后每个纹理绘制大约 3-10 次。然后你就有了数千个点。您以球形图案等方式绘制所有图像 - 分层爆炸。

游戏时你不可能总是与现实做到一一对应。仔细观察一些在旧 Xbox 或 iPad 等上运行的游戏 - 您需要执行一些快捷方式 - 并且完成后它们通常看起来很棒。

关于objective-c - 如何在 iPhone OpenGL ES 粒子系统中绘制 1000 多个粒子(具有独特的旋转、缩放和 Alpha)而不减慢游戏速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7435123/

相关文章:

ios - 自定义 UITableViewCell 的 UI 问题

ios - iOS Metal 中的透视正确纹理映射

ios - GPUImage Lookup Filter - 创建大于 512² 颜色的颜色深度

android - SKMaps eglChooseConfig IllegalArgumentException

objective-c - Xcode:如何正确构建静态库项目?

ios - 设计核心数据数据库

objective-c - 函数的可变大小参数

iphone - 更改 UIImage 按钮的颜色

ios - NSManagedObjectContext 扩展中的通用函数中的奇怪 Swift 行为

android - 每次从构建类中 flutter 停止底部导航栏