OpenGL ES - 如何批量渲染具有不同alpha,旋转和比例的500多个粒子?

时间:2012-08-03 00:30:29

标签: objective-c ios opengl-es opengl-es-1.1 vertex-array

我正在开发一款需要一次渲染500-800颗粒的iOS游戏。我已经了解到,在OpenGL ES中批量渲染许多精灵而不是在游戏中的每个精灵上调用glDrawArrays(..)是一个好主意,以便能够渲染更多的精灵而不会大幅降低帧速率。

我的问题是:我如何批量渲染500多个粒子,这些粒子都具有不同的alphas,旋转和缩放,但共享相同的纹理图集?此问题的重点在于每个粒子的不同的 alphas 旋转 scale

我意识到这个问题与How do I draw 1000+ particles (w/ unique rotation, scale, and alpha) in iPhone OpenGL ES particle system without slowing down the game?非常相似,但是,这个问题并没有解决批量渲染问题。在利用顶点缓冲区对象之前,我想了解OpenGL ES中的批渲染与唯一的alphas,旋转和缩放(但具有相同的纹理)。因此,虽然我计划最终使用VBO,但我想先采用这种方法。

非常感谢代码示例,如果您使用索引数组作为示例,请解释索引数组的结构和用途。

编辑我正在使用OpenGL ES 1.1。

编辑下面是我如何渲染场景中每个粒子的代码示例。假设它们共享相同的纹理,并且在执行此代码之前,该纹理已经在OpenGL ES 1.1中绑定。

- (void) render {

    glPushMatrix();

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

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

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

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

    // glBindTexture(GL_TEXTURE_2D, texture[0]);

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


    glTexCoordPointer(2, GL_FLOAT, 0, texturedQuad.textureCoords);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

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

非常感谢此方法的替代代码!

1 个答案:

答案 0 :(得分:7)

一种可能性是将这些值包含在顶点属性数组中 - 我认为这是最佳选择。如果您使用的是OpenGL ES 1.1而不是2.0,那么您将无法使用此方法。 Vertex attrib数组允许您在每个顶点存储值,在这种情况下,您可以将alphas和rot各自存储在它们自己的attrib数组中,并使用glVertexAttribArray将它们传递给着色器。然后着色器将使用alpha进行旋转变换和颜色处理。

另一种选择是在CPU上进行旋转变换,然后将具有相似alpha值的粒子批量处理为多个绘制调用。这个版本需要更多的工作,它不会是一个单独的绘制调用,但如果着色器不是一个选项,它仍然有助于优化。

注意:您链接的问题也建议使用阵列解决方案

编辑:鉴于您的代码是OpenGL ES 1.0,这是使用glColorPointer的解决方案:

// allocate buffers to store an array of all particle data
verticesBuffer = ... 
texCoordBuffer = ...
colorBuffer = ...

for (particle in allParticles)
{
  // Create matrix from rotation
  rotMatrix = matrix(particle.rotation.x, particle.rotation.y, particle.rotation.z)
  // Transform particle by matrix
  verticesBuffer[i] = particle.vertices * rotMatrix

  // copy other data
  texCoordBuffer[i] = particle.texCoords;
  colorBuffer[i] = color(1.0, 1.0, 1.0, particle.alpha);
}

glVertexPointer(verticesBuffer, ...)
glTexCoordPointer(texCoodBuffer, ...)
glColorPointer(colorBuffer, ...)

glDrawArrays(particleCount * 4, ...);

此解决方案的一个很好的优化是共享每个渲染的缓冲区,因此您不必每帧都重新分配它们。