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

问题描述

按照 learnopengl.com 中关于使用混合渲染半透明窗户玻璃的教程,我尝试将该原理应用于我的简单场景(我们可以在其中使用鼠标导航场景),其中包含:

  • 立方体:6 个面,每个面有 2 个三角形,使用在其关联的顶点着色器中定义的两个属性(位置和颜色)构造并传递给其片段着色器。
  • :使用 sampler2D 统一(png 图像的背景是透明的)应用 png 纹理的 2D 表面(两个三角形)。
  • 窗口:一个半透明的 2D 表面,基于与上面的草相同的着色器(顶点和片段)。两种纹理均从 learnopengl.com 下载

我面临的问题是,当谈到时,我可以通过窗口看到它,但不能通过立方体看到它!

screenshot

我的代码结构如下(我故意把窗口的渲染留到最后):

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

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

#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 类的实例(一个由两个纹理表面共享,一个用于立方体)。这个类管理 VAO 的创建/绑定/删除和 VBO 的绑定/删除(在类之外创建 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,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,则立方体的颜色不会与窗口的颜色混合。

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

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

另见glBlendFuncBlending