编辑+更好的解决方案:
如果有人碰到我遇到的问题,有两个解决方案。一个是被接受的解决方案,但只适用于你像我一样做事情的时候。让我解释一下我在做什么:
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);
如果我使用上面的代码运行,会得到如下结果...
粒子纹理:
![Particle tex](https://istack.dev59.com/PVRy5.webp)
![Screenshot from OGL Profiler](https://istack.dev59.com/DqI0n.webp)
![Screenshot of the FBO without any particle rendered](https://istack.dev59.com/YAEL5.webp)
![Screenshot of the FBO with some particles rendered on top](https://istack.dev59.com/SCviE.webp)
最后注意,设置着色器中的像素透明度可以正确混合——船体出现在下方。这是我的着色器:
#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;
}
如果有什么我可以提供的,请告诉我。