【问题标题】:Cannot apply blending to cube located behind half-transparent textured surface无法对位于半透明纹理表面后面的立方体应用混合
【发布时间】:2021-04-26 13:14:04
【问题描述】:

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

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

我面临的问题是,当涉及到 Grass 时,我可以通过 Window 而不是 Cube 看到它!

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

// 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, 0, n_vertexes);

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

【问题讨论】:

  • 不,透过窗户可以看到草,透过窗户看不到的是立方体。请看看我的编辑,我添加了我的着色器程序和更多关于如何完成渲染的细节@Rabbid76

标签: c++ opengl shader textures blending


【解决方案1】:

您的混合函数功能取决于目标的 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

【讨论】:

  • 非常感谢,我不够小心。它实际上解释了为什么我在grass 表面的中间有一个与window 具有相同颜色的区域,因为这些像素在目的地的纹理图像中是完全不透明的。
猜你喜欢
  • 1970-01-01
  • 2011-11-08
  • 1970-01-01
  • 1970-01-01
  • 2013-10-10
  • 2012-08-17
  • 2013-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多