5

编辑+更好的解决方案:

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

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 工具)的屏幕截图:

OGL Profiler 的屏幕截图

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

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

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

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

4

3 回答 3

8

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

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

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);

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

于 2013-06-21T13:09:57.850 回答
5

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

在绘制粒子时,使用glBlendFuncSeparate在此处描述)为 Alpha 通道使用不同的混合因子:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);

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

于 2013-06-21T08:32:31.370 回答
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);

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

于 2013-06-21T12:08:05.687 回答