【问题标题】:OpenGL Alpha Blending Issue, Blending ignored (maybe)?OpenGL Alpha 混合问题,混合被忽略(也许)?
【发布时间】:2013-06-17 23:21:31
【问题描述】:

编辑 + 更好的解决方案:

如果有人碰巧遇到我遇到的问题,有两种解决方案。一种是接受的解决方案,但这仅适用于您按照我的方式做事。让我解释一下我在做什么:

1.) 将星星背景渲染到屏幕

2.) 渲染飞船,然后将粒子渲染到 FBO

3.) 将 FBO 渲染到屏幕

这个问题,以及解决这个问题的方法,首先是因为我将 FBO 与星星背景混合在一起。

真正的解决方案,据说也稍微快一点,是简单地将星形背景渲染到 FBO,然后在禁用混合的情况下将 FBO 渲染到屏幕。使用这种方法,我就不用搞glBlendFuncSeparate了……

1.) 渲染星星,然后是飞船,然后是粒子到 FBO

2.) 将 FBO 渲染到屏幕禁用混合

---------原始问题:---------

根据我对这个问题的理解,混合正在以某种方式被忽略。具有 alpha 透明度的粒子纹理完全覆盖下面的像素。

我正在创建一个自上而下的游戏。相机略微倾斜,以便有一些深度感。我正在渲染我的飞船,然后渲染它们上方的粒子……

在开始 OpenGL 上下文之后

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glCullFace(GL_BACK);

在渲染循环中,我这样做:

glBindFramebuffer(GL_FRAMEBUFFER,ook->fbo);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);

entitymgr_render(ook); //Render entities. Always 1.0 alpha textures.

glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);

//glBlendFunc(GL_SRC_ALPHA,GL_ONE); //This would enable additive blending for non-premult
particlemgr_render(ook); //Render particles. Likely always <1.0 alpha textures
//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

glBindFramebuffer(GL_FRAMEBUFFER,0);

如果我使用上面的代码运行,我会得到这样的结果...

粒子纹理:

OGL Profiler(Mac 工具)的屏幕截图:

没有渲染任何粒子的 FBO 屏幕截图:

顶部渲染一些粒子的 FBO 屏幕截图:

如您所见,尽管粒子具有 alpha 透明度,但它不会与下面渲染的船混合。相反,它只是完全覆盖了像素。

最后说明,在着色器中正确设置像素透明度混合 - 船出现在下方。这是我的着色器:

#version 150
uniform sampler2D s_tex1;
uniform float v4_color;
in vec4 vertex;
in vec3 normal;
in vec2 texcoord;

out vec4 frag_color;

void main()
{
    frag_color=texture(s_tex1,texcoord)*v4_color;
    if(frag_color.a==0.0) discard;
}

如果有什么我可以提供的,请告诉我。

【问题讨论】:

    标签: opengl glsl opengl-3


    【解决方案1】:

    在我看来,它会将 Alpha 通道也渲染到帧缓冲区中,因此当您编写粒子时,src Alpha 通道会与目标 Alpha 通道混合,这不是您想要的。

    这正是创建 glblendfuncseparate() 函数的原因。试试这个...

    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
    

    因此,粒子的 Alpha 通道将用于确定最终像素的颜色,但源和目标的 Alpha 通道将被添加在一起。

    【讨论】:

      【解决方案2】:

      我的猜测是 FBO 的 rgb 通道被正确渲染,但因为它也有一个 alpha 通道,并且它是在启用混合的情况下绘制的,所以最终结果在粒子与飞船重叠的地方透明度不正确。

      在绘制粒子时,使用glBlendFuncSeparate (described here) 为 Alpha 通道使用不同的混合因子:

      glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
      

      或者在将 FBO 绘制到屏幕上时完全关闭混合。

      【讨论】:

      • 我接受了另一个答案,该答案在这个答案之后发布,因为他/她更好地描述了问题以及 glBlendFuncSeparate 在这里做什么。这仍然是正确的答案。
      【解决方案3】:

      为了获得纹理透明度,除了:

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

      您还应该保证:

      1. 使用 glTexImage2D 创建粒子 tex 时,使用 格式 GL_RGBA(如果使用灰色阴影纹理,则使用 GL_LUMINANCE_ALPHA)

      2. 绘制粒子纹理时,在glBindTexture命令后调用

        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);

      您可以使用正确的纹理函数来代替 GL_BLEND,如 glTexEnv 参考:http://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml

      【讨论】:

      • 不正确。我专门为我的问题标记了opengl-3。此功能适用于低于 3 的版本。
      • LOL 我正在大量使用 OpenGL SC,所以我很了解这个版本。我的错没有注意到opengl-3标签。
      猜你喜欢
      • 2023-03-20
      • 2011-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-14
      • 2013-11-16
      • 2015-03-30
      相关资源
      最近更新 更多