【问题标题】:Android OpenGL 2.0 Sprite OptimizationAndroid OpenGL 2.0 精灵优化
【发布时间】:2013-10-29 07:11:36
【问题描述】:

嘿嘿,

我正在使用 OpenGL ES 2.0 为 Android 创建简单的游戏。 游戏将包含几种不同的精灵,但这些精灵会不止一次出现。

现在假设我有 1 个对象(精灵)。到目前为止,我已经实现了 VBO 和索引缓冲,因此据我所知,整个对象都存储在 GPU 上。

我现在想做的是多次绘制这个对象,只是它的位置不同。 就目前而言,实现如下:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.getBufferId());
for(int i=0; i<1000; i++){
    multiplyMM(MVP, 0, viewMatrix, 0, tempGetRandomMVPMatrix(), 0);
    glUniformMatrix4fv(uMatrixLocation, 1, false, MVP, 0);//TODO


    if(androidVersion > Build.VERSION_CODES.FROYO)
        glDrawElements(GL_TRIANGLES, indexArray.length, GL_UNSIGNED_SHORT, 0);
    else{
        if(repairedGL20 == null){
            repairedGL20 = new AndroidGL20();
        }
        repairedGL20.glDrawElements(GL_TRIANGLES, indexArray.length, GL_UNSIGNED_SHORT, 0);
    }

}

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

如果我理解正确,主要问题是调用 glDrawElements,每次更改 MVP 矩阵时都会调用它。有什么方法可以将所有 MVP 矩阵发送到 GPU 并在那里多次绘制一个元素,而只需调用 1 次 glDrawElements?

关于对象的更多信息。 它有大约 24 个顶点和 64x64 纹理。 目前有 1k 个对象,我有 35FPS,我想获得更高的 fps,因为我将绘制更多的精灵。

这是我的着色器: 顶点:

    uniform mat4 u_Matrix;

attribute vec4 a_Position;
attribute vec2 a_TextureCoordinates;

varying vec2 v_TextureCoordinates;

void main(){
    v_TextureCoordinates = a_TextureCoordinates;
    gl_Position = u_Matrix * a_Position;
}

片段:

precision mediump float;

uniform sampler2D u_TextureUnit;//actual texture data
varying vec2 v_TextureCoordinates;

void main(){
    gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);
}

还有一点我不太了解纹理。如果我创建这样的纹理:

glBindTexture(GL_TEXTURE_2D, textureObjectIds[0]);//binds texture to texture object

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);//minimization filter
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);//send texture data to OpenGL to the CURRENTLY BOUND object

当我将使用此纹理绘制对象时,纹理保存在哪里,是在 CPU 的内存上还是在 GPU 上?此外,在上面的示例中,我正在绘制相同的精灵,每次绘制调用是否都会将纹理发送到 GPU?如果是这样,有什么办法可以优化这个(类似于VBO)?

【问题讨论】:

  • 你想要的是实例化渲染。 GLES 2.0 没有它,但是如果您向顶点数组添加额外的顶点属性,您可以伪造它。添加一个表示顶点 ID 的 GLubyte,然后通过一些巧妙的工作,您可以在编译时选择适当的矩阵统一。它不会像真正的实例化,但您可能无需进行多次绘制调用就可以逃脱。
  • 你能详细解释一下吗?例如,假设我有 1 个带有 2 个顶点的对象,我想用 MVP 将其转换为 2 个位置。如何让“gl_Position”同时在 2 个不同的地方绘制?

标签: android optimization opengl-es-2.0 sprite


【解决方案1】:

例如,假设我有 1 个带有 2 个顶点的对象,我想用 MVP 将其转换到 2 个位置。如何使“gl_Position”同时在 2 个不同的地方绘制?

那是永远做不到的。我在最初的评论中所指的是一个顶点缓冲区,每个精灵都包含 N 个(可能是 4 个)顶点......如果除了顶点缓冲区中的位置之外,您还包括一个额外的字段,您可以转换在着色器中使用不同矩阵的顶点。您将始终必须为每个对象定义 N 个顶点,但您可以使用静态顶点缓冲区来执行此操作,我将在下面解释。

假设你有一个由点定义的精灵(在转换之前):

   Position
   <0.0,0.0>
   <1.0,0.0>
   <1.0,1.0>
   <0.0,1.0>

如果您的模型视图矩阵包含缩放信息,顺便说一下,您可以反复使用同一组点。

现在,如果你想扩展它以在一次调用中绘制 3 个精灵,你可以这样做:

  Position  Idx
  <0.0,0.0> [0]
  <1.0,0.0> [0]
  <1.0,1.0> [0]
  <0.0,1.0> [0]

  <0.0,0.0> [1]
  <1.0,0.0> [1]
  <1.0,1.0> [1]
  <0.0,1.0> [1]

  <0.0,0.0> [2]
  <1.0,0.0> [2]
  <1.0,1.0> [2]
  <0.0,1.0> [2]

基本上我在顶点缓冲区中添加了一个新字段,用于标识每组 4 个点所属的精灵;使用GLubyte 以获得最佳性能。您会注意到同一组点一遍又一遍地重复。以这种方式实现实例化有效地将存储需求增加到O (N*V + 4N),其中 V 是 4 个点的原始顶点数据结构的大小,N 是精灵的数量。

您可以定义一个顶点缓冲区,其中包含足够 16 个精灵的点,然后当您想在一次调用中绘制多个精灵时,您将始终使用相同的顶点缓冲区并使用总数的一个子集点数。要使用此顶点缓冲区绘制 4 个精灵,只需从它包含的总共 64 个点中绘制前 16 个。

现在,这只是过程的一半。您还需要设置您的顶点着色器以获取一组模型视图矩阵制服,这些制服定义了每个精灵的转换。

这是一个可以用来做这个的顶点着色器示例:

#version 100

uniform mat4    proj_mat;
uniform mat4    instanced_mv [16];

attribute vec4  vtx_pos;
attribute vec2  vtx_st;
attribute float vtx_sprite_idx; // This would be a uint in desktop GLSL

varying   vec2  tex_st;

void main (void) {
  gl_Position = proj_mat * instanced_mv [(int)vtx_sprite_idx] * vtx_pos;
  tex_st      = vtx_st;
}

这里有几点需要注意:

  1. GLES 2.0 不支持整数顶点属性,所以索引必须是浮点数

    • 索引统一数组必须使用顶点着色器中的整数表达式来完成,因此需要强制转换。

  2. 模型视图制服的数量实际上是限制您一次可以实例化多少精灵的因素

    • 顶点着色器只需要支持 128 个 4 分量统一变量(mat4 算作 4 个 4 分量统一变量),因此这意味着如果您的顶点着色器只有 modelview 制服,您最多可以支持 32 个 (128/4) 的数组。

  3. 将精灵索引作为GLubyte 存储在顶点缓冲区中,但请确保在设置顶点属性时不要启用浮点规范化。指针。

最后,此着色器尚未经过测试。如果您在此处无法理解任何内容或遇到实施问题,请随时发表评论。

【讨论】:

    猜你喜欢
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    • 2013-08-21
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多