【问题标题】:Optimizing a shader (OSL GLSL2.0)优化着色器 (OSL GLSL2.0)
【发布时间】:2013-09-11 00:01:43
【问题描述】:

我的目标是在 openGl 中重新创建气泡图的实现,以便它变得更快。作为参考,当前的实现使用画布以 8 fps 的速度运行。它在安卓手机的屏幕上绘制了 5200 个圆圈。 它们会实时改变颜色、大小和位置。

我曾尝试对它们进行精灵批处理,但由于某种未知原因,我一次无法批处理超过 15 个。 然后我尝试将它们全部放入带纹理的矩形中,但是构建网格需要很长时间,即使我在两次绘制之间不更改它,它也很慢。

现在,我认为可以优化很多我当前的着色器,但我缺乏太多的知识来做这件事。

一个潜在的优化地方是网格生成,目前是这样的: x, y, z, r, g, b, a, tx, ty, x, y, z, .... 其中 (x, y, z) 是顶点位置,(r, g, b, a) 是颜色, (tx, ty) 是纹理坐标,但是 (z, r, g, b, a) 在同一个正方形的所有顶点。 (tx, ty) 对于顶点 1 始终为 0,0; 1, 0 代表顶点 2 依此类推...

另外,每个正方形有 6 个顶点而不是 4 个,因为同一个网格有不相交的正方形

我的顶点着色器:

uniform mat4 uMVPMatrix;
attribute vec4 aPosition;
attribute vec4 aColor;
attribute vec4 aTexCoordinate;
varying vec2 vTexCoordinate;
varying vec4 vColor;
void main() {
  vColor = aColor;
  vTexCoordinate = aTexCoordinate.xy;
  gl_Position = uMVPMatrix * aPosition;
}

我的片段着色器:

private final String FragmentShaderCode = 
precision mediump float;
uniform sampler2D u_Texture;
varying vec4 vColor;
varying vec2 vTexCoordinate;
void main() {
  gl_FragColor = texture2D(u_Texture, vTexCoordinate) *vColor;
}

我不太明白着色器代码是如何转换为“在此处绘制此颜色”的,所以我真的无法想象我应该如何解决这些冗余问题。

编辑/更新:

profiler screencap

原来有两种(不相关的?)方法导致速度变慢。 EGLImpl.eglSwapBuffers 和 GLES20.glClear。但是,如果我不绘制 5200 个方格,这些方法不会导致减速。根据this post,这是由着色器引起的(如果我不绘制 5200 个三角形,则不会发生这种情况),不幸的是,发布者忘记告诉着色器在做什么导致这些方法变慢。

更新2,绘制代码,但不确定它是否有帮助

public void draw(float[] mvpMatrix) {
    if (!isPacked) {
        pack();
    }
    GLES20.glUseProgram(GlProgram);
    // ////////////////////
    int mTextureUniformHandle = GLES20.glGetUniformLocation(GlProgram, "u_Texture");
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
    GLES20.glUniform1i(mTextureUniformHandle, 0);
    // ///////////////////////
    VertexBuffer.position(0);
    int PositionHandle = GLES20.glGetAttribLocation(GlProgram, "aPosition");
    GLES20.glEnableVertexAttribArray(PositionHandle);
    GLES20.glVertexAttribPointer(PositionHandle, 3, GLES20.GL_FLOAT, false, (3 + 4 + 2) * 4, VertexBuffer);
    // ///////////////
    VertexBuffer.position(3);
    int ColorHandle = GLES20.glGetAttribLocation(GlProgram, "aColor");
    GLES20.glEnableVertexAttribArray(ColorHandle);
    GLES20.glVertexAttribPointer(ColorHandle, 4, GLES20.GL_FLOAT, false, (3 + 4 + 2) * 4, VertexBuffer);
    // /////////////////
    VertexBuffer.position(7);
    int TexCoordinate = GLES20.glGetAttribLocation(GlProgram, "aTexCoordinate");
    GLES20.glEnableVertexAttribArray(TexCoordinate);
    GLES20.glVertexAttribPointer(TexCoordinate, 2, GLES20.GL_FLOAT, false, (3 + 4 + 2) * 4, VertexBuffer);
    // /////////////////
    int MVPMatrixHandle = GLES20.glGetUniformLocation(GlProgram, "uMVPMatrix");
    GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, mvpMatrix, 0);
    // /////////////
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, totalvertz);
    GLES20.glDisableVertexAttribArray(PositionHandle);
    GLES20.glDisableVertexAttribArray(ColorHandle);
    GLES20.glDisableVertexAttribArray(TexCoordinate);
}

【问题讨论】:

  • 在您的片段着色器中,sampler2D 的默认精度为 lowp,您将其乘以 mediump vec4 (vColor)。这需要将采样的纹理转换为mediump,如果您将lowp 用于vColor,您可能会从中获得一些额外的性能。不过可能不会很多。

标签: android optimization opengl-es opengl-es-2.0 shader


【解决方案1】:

绘制 5200 个四边形不是任务,如果实施正确,它应该可以在任何设备上流畅运行。

您的着色器太简单而无法优化,您几乎无能为力。

在继续之前,您是否检查过 OpenGL 错误? (是glGetError() == 0?)这些会导致大量帧率下降。

编辑: 还有一些我能想到的其他事情,但是如果没有看到你的代码就很难:

  • 您是否有效地使用了 FloatBuffers?
  • 您是否确保不要每帧都创建一个新的顶点缓冲区?
  • 所有四边形都应该在一个网格中,这意味着一个绘制调用。是这样吗?

【讨论】:

  • 是的,我每个周期都在检查错误,不幸的是,导致速度变慢的既不是错误也不是检查错误的行为
  • 但也许可以在一个新问题中回答这个问题。这个问题的答案是“不可能优化”
  • 嗯,我遇到的问题之一是没有有效地使用 FloatBuffer(过多的冗余信息),这将需要更改着色器,但实际上标题有点令人困惑。至于其他问题,我仍然没有在绘制调用之间更改缓冲区的内容,但我需要稍后再做,所有三角形都在同一个网格中
  • 您应该使用顶点缓冲区对象。您每帧都将顶点缓冲区复制到图形芯片,并且数据没有交错。阅读此内容:developer.apple.com/library/ios/documentation/3ddrawing/… 在页面的一半左右的使用顶点缓冲区对象管理复制顶点数据。您的代码类似于示例 9-1
猜你喜欢
  • 2021-10-06
  • 2017-07-03
  • 2019-03-04
  • 2019-02-17
  • 1970-01-01
  • 1970-01-01
  • 2011-09-19
  • 1970-01-01
  • 2022-01-27
相关资源
最近更新 更多