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

Big*_*uce 3 opengl-es objective-c vertex-array ios opengl-es-1.1

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

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

我意识到这个问题非常类似于如何在iPhone OpenGL ES粒子系统中绘制1000多个粒子(具有独特的旋转,缩放和alpha)而不会减慢游戏速度?但是,该问题不涉及批量渲染.在利用顶点缓冲区对象之前,我想了解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();
}
Run Code Online (Sandbox Code Playgroud)

我们非常感谢这种方法的替代代码!

Jus*_*ers 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, ...);
Run Code Online (Sandbox Code Playgroud)

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