OpenGL Alpha混合问题,混合忽略(也许)?

时间:2013-06-20 22:24:41

标签: opengl glsl opengl-3

编辑+更好的解决方案:

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

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);

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

粒子tex:

Particle tex

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

Screenshot from OGL Profiler

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

Screenshot of the FBO without any particle rendered

FBO的屏幕截图,其中一些粒子呈现在顶部:

Screenshot of the FBO with some particles rendered on top

正如您所看到的,尽管具有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;
}

如果我能提供任何内容,请告诉我。

3 个答案:

答案 0 :(得分:6)

在我看来,它正在将alpha通道渲染到帧缓冲区中,所以当你编写粒子时,src alpha通道会与目标alpha通道混合,这不是你想要的。

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

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);

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

答案 1 :(得分:4)

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

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

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);

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

答案 2 :(得分:0)

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

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);

  3. 而不是GL_BLEND,您可以使用正确的纹理函数,如中所述 glTexEnv参考:http://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml