【问题标题】:OpenGLES blending bug, alpha is accumulatingOpenGLES 混合错误,alpha 正在累积
【发布时间】:2014-12-07 22:16:48
【问题描述】:

我正在为 android 制作动态壁纸,我将解释它是如何工作的,因为我相信它与问题有关,很抱歉这个问题很长,但我需要解释一切,因为问题很难描述。

我正在使用 OpenGLES 2.0,我有一个 GLSurfaceView 和一个壁纸服务实现,我将它传递给我的渲染器以调用绘图方法,就像大多数 OpenGL 动态壁纸一样。

我实现渲染器的方式是:在墙纸服务中,我有一个独立的线程,它将每 X 秒调用一次绘制方法,GLSurfaceView 设置为 RENDERMODE_WHEN_DIRTY,因此这个更新线程决定了何时进行绘制。

此外,服务中还有一个暂停和恢复方法,当可见性发生变化时。因此,即使我退出壁纸,该服务也会运行,并保留所有内容的状态,直到它恢复为止。

现在解决这个问题,正如您在此处所见:

但是当我失去焦点并重新回到壁纸时,我会按下 android 壁纸选择器上的后退按钮,或者更改壁纸然后返回。事物的alpha值会上升。

这里有 2 个网格,左侧的初始 alpha 值为 0.1,右侧的初始 alpha 值为 0.5。

现在,当我离开并返回时,将调用 GLSurfaceView onVisibilityChanged 方法,它按预期工作,但正如您所见,alpha 值会由于某种原因而增加,并且在我离开和返回时继续增加:

1次 2次

我设置网格绘制的方式是在我的片段着色器中,我将在绘制网格之前设置制服的值,并且该制服将乘以纹理颜色。

这是片段着色器:

precision mediump float;

uniform vec4 u_color;       
uniform sampler2D u_texture;
varying vec2 v_textcoord;

void main()
{
    gl_FragColor = u_color * texture2D(u_texture, v_textcoord); 
}  

当然在绘制网格之前我设置了混合和混合函数:

GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

GLES20.glUniform4f(DayAndNightRenderer.BaseShader.GetUniform("u_color"), color.r, color.g, color.b, 0.5f);      

texture.Bind();

mesh.Draw(GLES20.GL_TRIANGLE_FAN, DayAndNightRenderer.BaseShader);

GLES20.glDisable(GLES20.GL_BLEND);

还有网格绘制,即使绘制之前设置了颜色统一:

GLES20.glUniformMatrix4fv(shader.GetUniform("u_transmat"), 1, false, Transform.GetProjectedTransformationMatrix().ToFloatBuffer());     

GLES20.glEnableVertexAttribArray(shader.GetAttribute("a_pos"));
GLES20.glEnableVertexAttribArray(shader.GetAttribute("a_textcoord"));

GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, VBO[0]);

GLES20.glVertexAttribPointer(shader.GetAttribute("a_pos"), 3, GLES20.GL_FLOAT, false, Vertex.SIZE, 0);
GLES20.glVertexAttribPointer(shader.GetAttribute("a_textcoord"), 3, GLES20.GL_FLOAT, false, Vertex.SIZE, Vertex.POS_SIZE);

GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, IBO[0]);    

GLES20.glDrawElements(primitive, size, GLES20.GL_UNSIGNED_INT, 0);      

GLES20.glDisableVertexAttribArray(shader.GetAttribute("a_textcoord"));
GLES20.glDisableVertexAttribArray(shader.GetAttribute("a_pos"));

到目前为止我尝试过的事情:

  • 更改混合函数似乎不会影响添加到 alpha 值的错误
  • 在焦点丢失之间重新加载着色器
  • 清除帧缓冲区,我设置了 GLES20.glClearColor(0f, 0f, 0f, 0f);开始并调用 GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);每一帧

上述方法均无效,而且它不是我用来设置累积 alpha 的变量,事物的 alpha 设置为常数,正如您在我设置颜色统一的代码中看到的那样。

我不知道是什么原因造成的,它真的只是在失去壁纸的焦点并回到它时才会发生,在第一次运行时没有返回,它完美地绘制了所有内容。

顺便说一下onVisibilityChanged方法:

@Override
public void onVisibilityChanged(boolean visible) 
{
    super.onVisibilityChanged(visible);

    if (hassetrenderer) 
    {
        if (visible) 
        {                       
            OpenGLES2WallpaperService.updatehandler.Start();
            glsurfaceview.onResume();                               
            Log.i("DN", "State: running");

        }
        else
        {
            OpenGLES2WallpaperService.updatehandler.Stop();
            glsurfaceview.onPause();
            Log.i("DN", "State: not running");
        }
    }
}       

【问题讨论】:

    标签: java android opengl-es live-wallpaper blending


    【解决方案1】:

    好吧,我通过在 GLSurfaceView 被破坏时终止壁纸进程来修复它(android.os.Process.killProcess(android.os.Process.myPid()))。

    效果很好,但我不是很满意,它不是着色器,因为即使在片段着色器中将 gl_FragColor.a 设置为 0.5 后它也会发生,所以我仍然不知道是什么原因造成的.

    我永远不会把终止进程作为解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多