【问题标题】:GLES2.0+ framebuffer fade artifactsGLES2.0+ 帧缓冲淡入淡出伪影
【发布时间】:2015-07-03 21:45:04
【问题描述】:

我正在使用 GLES 2.0 或 3.0 在 android 上编写一个简单的测试程序。 (如果解决方案只适用于另一种,那么我将采用这种方式。)

问题:

  • 基本上我在褪色时遇到奇怪的像素伪影。
  • 可以通过提高截止阈值来“隐藏”该问题,但是淡入淡出仍然具有不完整的一致性,就我而言,这不起作用。

例子:

  • Example Pictures (Sorry, I cant post images directly yet)
  • 已降低帧缓冲区分辨率以使伪影更加明显。
  • 此问题出现在所有经过测试的设备上(Nexus 7 2012 和 2013、Galaxy Tab S 8.4、Galaxy S6 Edge、Galaxy Note 4)
  • 在较新的设备上,问题似乎只是粉红色的均匀小点,在较旧的设备上,问题似乎确实是不完整的,如链接图片所示。
  • 在最终渲染上运行模糊通道也是不可能的,因为这需要节能且对移动设备友好。

布局:

  • 我创建了 2 个帧缓冲区。 (使用 GLES20.GL_UNSIGNED_SHORT_5_6_5 格式。)
  • 我将第一个设置为渲染目标。
  • 我绘制了一个四边形,它是帧缓冲区的缓冲区大小。
  • 四边形片段着色器设置为渲染一个在圆周上移动的黑点。
  • 四边形也可以采用纹理并将其与点混合。
  • 然后我切换回屏幕渲染。
  • 我使用之前设置的渲染目标作为纹理渲染另一个四边形。
  • 然后在每一帧切换纹理时重复此过程。

渲染代码:

int i = 0;
@Override public void onDrawView() {
    setRenderTarget(mRenderTexture[i]);
    mTestShader.setTexture0(mRenderTexture[(i + 1) % 2].getTextureHandle());
    mTestShader.draw(mBlitQuad);
    setRenderTarget(null);
    mBlitShader.setTexture0(mRenderTexture[i].getTextureHandle());
    mBlitShader.draw(mBlitQuad);
    i = ++i % 2;
}

着色器代码:

precision highp float;

uniform float u_GlobalTime;
uniform vec3 u_Resolution;
uniform sampler2D u_Texture0;

varying vec2 v_TexCoord;

void main(void) {
    vec2 uv = v_TexCoord * 2.0 - 1.0;
    uv.x *= u_Resolution.z;
    vec2 pos = vec2(cos(u_GlobalTime), sin(u_GlobalTime)) * 0.5;
    vec4 circle = vec4(1.0 - smoothstep(0.09, 0.11, length(pos - uv)));
    vec4 px = max(texture2D(u_Texture0, v_TexCoord), circle) - 0.025;
    gl_FragColor = step(0.15, px) * px;
}

对这个问题有帮助吗?

编辑:
感谢 Jerem 对抖动进行了一些谷歌搜索后,我找到了 GLES20.glDisable(GLES20.GL_DITHER)。这对解决这个问题有很大帮助,并且在较新的设备上它可以完美运行。在旧设备上,我仍然会遇到伪像,如 HERE 所示。

EDIT2:
经过更多测试,切换到甚至 RGB 颜色的缓冲区格式似乎已经完成了 GLES30.GL_UNSIGNED_SHORT_5_5_5_1 的技巧。我的猜测是它与 GPU 如何压缩帧缓冲区有关,因为绿色更明显。 (了解它不喜欢 5_6_5 格式的具体原因仍然会有所帮助。)
应用两个修复后的最终结果:i.imgur.com/bQsG9YJ.png。

【问题讨论】:

  • 看起来你的图片有某种抖动,你如何淡化白点? (绘制点时使用的纹理是什么?)
  • 纹理@u_Texture0 是一个帧缓冲区,与当前正在渲染的那个相反。白点每帧减去 0.025,低于 0.15 的任何值都设置为 0。修改帧缓冲区配置不能解决此问题。'code' mFormat = GLES20.GL_UNSIGNED_SHORT_5_6_5; mWrapMode = GLES20.GL_CLAMP_TO_EDGE; mFilterMode = GLES20.GL_LINEAR;'代码'
  • 也尝试禁用 alpha 测试,在新的屏幕截图中似乎已启用。
  • 如果您已经解决了,首选的方法是回答您自己的问题,然后接受该答案,而不是在问题中编辑“已解决”一词。
  • 为什么不将该答案粘贴到提供的答案框中(在此评论下方),这样问题就会被记录为有解决方案。不要只是添加另一个评论。 StackOverflow 不是聊天板。

标签: android opengl-es glsl framebuffer


【解决方案1】:

它是一个多部分的解决方案,调用 GLES20.glDisable(GLES20.GL_DITHER),将渲染缓冲区格式设置为 GLES30.GL_UNSIGNED_SHORT_5_5_5_1,正如 Jerem 所说,您也可以在禁用 alpha 的情况下获得更好的结果,尽管实验在我的设备上选择似乎没有效果,可能在其他设备上会。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-29
    • 2012-08-14
    • 1970-01-01
    相关资源
    最近更新 更多