我正在开发一款iOS游戏,一次需要渲染500-800个粒子。我了解到,在OpenGL ES中批量渲染多个精灵是一个好主意,而不是在游戏中的每个精灵上调用glDrawArrays(..)
,以便能够在帧速率大幅降低的情况下渲染更多的精灵。
我的问题是:如何批处理渲染500多个粒子,这些粒子都具有不同的字母、旋转和比例,但共享相同的纹理图谱?这个问题的重点是每个粒子的不同字母、旋转和尺度。
我意识到这个问题与如何在iPhone OpenGL ES粒子系统中绘制1000多个粒子(具有唯一的旋转、缩放和alpha)而不减慢游戏速度非常相似?,然而,这个问题并没有涉及到批处理渲染。在利用顶点缓冲区对象之前,我想了解OpenGL ES中的批处理渲染,它具有唯一的字母、旋转和缩放(但具有相同的纹理)。因此,虽然我计划最终使用VBO,但我想首先采用这种方法。
代码示例将不胜感激,如果您像某些示例那样使用索引数组,请解释索引数组的结构和用途。
编辑我使用的是OpenGL ES 1.1。
EDIT下面是如何渲染场景中每个粒子的代码示例。假设它们共享相同的纹理,并且在执行此代码之前,该纹理已经绑定在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();
}
如果能提供此方法的代码替代方案,我们将不胜感激!
一种可能性是将这些值包含在顶点属性数组中——我认为这是最好的选择。如果您使用的是OpenGL ES 1.1而不是2.0,那么您将无法使用此方法。顶点属性数组允许您在每个顶点存储值。在这种情况下,您可以将每个字母和旋转存储在各自的属性数组中,并将它们传递给具有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, ...);
该解决方案的一个好的优化是共享每个渲染的缓冲区,这样就不必在每帧重新分配它们。