无法将混合应用于位于半透明纹理表面后面的立方体
Cannot apply blending to cube located behind half-transparent textured surface
遵循 learnopengl.com 中关于使用混合渲染半透明 windows 眼镜的教程,我尝试将该原理应用于我的简单场景(我们可以使用鼠标在场景中导航)包含:
- 立方体:6 个面,每个面有 2 个三角形,使用在其关联的顶点着色器中定义并传递给其片段着色器的两个属性(位置和颜色)构造。
- 草: 使用
sampler2D
制服应用了 png 纹理的 2D 表面(两个三角形)(png 图像的背景是透明的)。
- Window: 基于与上面的草相同的着色器(顶点和片段)的半透明二维表面。两个纹理都是从 learnopengl.com
下载的
我面临的问题是,当谈到草时,我可以通过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
遵循 learnopengl.com 中关于使用混合渲染半透明 windows 眼镜的教程,我尝试将该原理应用于我的简单场景(我们可以使用鼠标在场景中导航)包含:
- 立方体:6 个面,每个面有 2 个三角形,使用在其关联的顶点着色器中定义并传递给其片段着色器的两个属性(位置和颜色)构造。
- 草: 使用
sampler2D
制服应用了 png 纹理的 2D 表面(两个三角形)(png 图像的背景是透明的)。 - Window: 基于与上面的草相同的着色器(顶点和片段)的半透明二维表面。两个纹理都是从 learnopengl.com 下载的
我面临的问题是,当谈到草时,我可以通过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