无法将混合应用于位于半透明纹理表面后面的立方体

Cannot apply blending to cube located behind half-transparent textured surface

遵循 learnopengl.com 中关于使用混合渲染半透明 windows 眼镜的教程,我尝试将该原理应用于我的简单场景(我们可以使用鼠标在场景中导航)包含:

我面临的问题是,当谈到时,我可以通过Window[=55=看到它] 但不是 Cube!

我的代码结构如下(我故意将 window 的渲染留到最后):

// enable depth test & blending
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA);

while (true):
  glClearColor(background.r, background.g, background.b, background.a);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  cube.draw();
  grass.draw();
  window.draw();

编辑:我将在下面分享用于绘制两个纹理表面(草和window)的顶点和片段着色器:

#version 130

in vec2 position;
in vec2 texture_coord;
// opengl tranformation matrices
uniform mat4 model;      // object coord -> world coord
uniform mat4 view;       // world coord  -> camera coord
uniform mat4 projection; // camera coord -> ndc coord
out vec2 texture_coord_vert;

void main() {
  gl_Position = projection * view * model * vec4(position, 0.0, 1.0);
  texture_coord_vert = texture_coord;
}

#version 130
in vec2 texture_coord_vert;
uniform sampler2D texture2d;
out vec4 color_out;

void main() {
  vec4 color = texture(texture2d, texture_coord_vert);
  // manage transparency
  if (color.a == 0.0)
    discard;
  color_out = color;
}

以及用于渲染彩色立方体的那些:

#version 130

in vec3 position;
in vec3 color;
// opengl tranformation matrices
uniform mat4 model;      // object coord -> world coord
uniform mat4 view;       // world coord  -> camera coord
uniform mat4 projection; // camera coord -> ndc coord
out vec3 color_vert;

void main() {
  gl_Position = projection * view * model * vec4(position, 1.0);
  color_vert = color;
}
#version 130

in vec3 color_vert;
out vec4 color_out;

void main() {
  color_out = vec4(color_vert, 1.0);
}

P.S: 我的着色器程序使用 GLSL v1.30,因为我的内部 GPU 似乎不支持更高版本。

关于执行实际绘图的代码,我基本上为每种类型的几何体设置了一个 Renderer class 实例(一个由两个纹理表面共享,一个用于立方体)。此 class 管理 VAO 的 creation/binding/deletion 和 VBO 的 binding/deletion(在 class 之外创建 VBO,因此我可以共享具有相似形状的顶点)。它的构造函数将着色器程序和顶点属性作为参数。我将尝试在下面显示相关代码

Renderer::Renderer(Program program, vector attributes) {
  vao.bind();
  vbo.bind();

  define_attributes(attributes);

  vao.unbind();
  vbo.unbind();
}

Renderer::draw(Uniforms uniforms) {
  vao.bind();
  program.use();

  set_uniforms(unfiorms);
  glDrawArrays(GL_TRIANGLES, 0, n_vertexes);

  vao.unbind();
  program.unuse();
}

您的混合函数取决于目标的 alpha 通道 (GL_ONE_MINUS_DST_ALPHA):

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA);
dest = src * src_alpha + dest * (1-dest_alpha) 

如果立方体的alpha通道为0.0,则立方体的颜色不会与window的颜色混合。

传统的alpha混合函数只依赖于源alpha通道:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
dest = src * src_alpha + dest * (1-src_alpha) 

另见 glBlendFunc and Blending