我正在尝试使用 OpenGL 在 C++ 中开发一个粒子系统,但我对混合的工作原理感到困惑。我正在尝试使用加法混合,据我了解,使用以下参数调用 glBlendFunc 函数:
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
当您尝试渲染某些东西时会导致以下情况:它将采用片段着色器计算的 R、G、B 颜色(源颜色),乘以片段着色器计算的 alpha 值(源 alpha),然后添加到帧缓冲区中已经存在的 R、G、B 颜色(目标颜色)。但如果这是真的,那么由片段着色器计算的黑色,其中 (R,G,B,A) = (0,0,0,1) 应该保持现有帧缓冲区颜色(目标颜色)不变,因为它是将 0 的源颜色值乘以 1 的源 alpha 值,这显然应该总是产生 0,然后将该 0 添加到现有的帧缓冲区颜色(目标颜色)中,这应该保持不变......对吗?
但是,当我这样做时,它并没有保持颜色不变,而是使它变亮,如下所示:
在这张图中,环境和剑是用法线混合渲染的,然后用 glBlendFunc(GL_SRC_ALPHA, GL_ONE) 渲染剑周围的方形粒子;使用总是输出 (R,G,B,A) = (0,0,0,1) 的片段着色器。渲染了很多粒子,你可以看到随着更多的粒子重叠,它变得更亮。当我将着色器的 alpha 输出从 1 切换到 0(源 alpha)时,粒子就会消失,这是有道理的。但是为什么当源颜色=1 和源 alpha=0 时它们仍然可见?
这是我调用来渲染粒子的确切函数:
void ParticleController::Render()
{
GraphicsController* gc = m_game->GetGraphicsController();
ShaderController* sc = gc->GetShaderController();
gc->BindAttributeBuffer(m_glBuffer);
ShaderProgram* activeShaderProgram = sc->UseProgram(SHADER_PARTICLE);
glDepthMask(false);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
gc->GetTextureController()->BindGLTexture(TEX_PARTICLES);
activeShaderProgram->SetUniform(SU_PROJ_VIEW_MAT, gc->GetProjectionMatrix() * gc->GetViewMatrix() * gc->GetWorldScaleMatrix());
activeShaderProgram->SetUniform(SU_LIGHT_AMBIENT, m_game->GetWorld()->GetAmbientLight());
activeShaderProgram->SetUniform(SU_TIME, m_game->GetWorld()->GetWorldTime());
CheckForOpenGLError();
m_pa.GLDraw();
CheckForOpenGLError();
gc->BindAttributeBuffer_Default();
CheckForOpenGLError();
glDepthMask(true);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
这些是我的片段着色器的最后 4 行,确保粒子颜色输出 (R,G,B,A) 始终 = (0,0,0,1):
fColor.r = 0.0;
fColor.g = 0.0;
fColor.b = 0.0;
fColor.a = 1.0;
有什么我想念的吗?