问题描述
按照 learnopengl.com 中关于使用混合渲染半透明窗户玻璃的教程,我尝试将该原理应用于我的简单场景(我们可以在其中使用鼠标导航场景),其中包含:
- 立方体:6 个面,每个面有 2 个三角形,使用在其关联的顶点着色器中定义的两个属性(位置和颜色)构造并传递给其片段着色器。
-
草:使用
sampler2D
统一(png 图像的背景是透明的)应用 png 纹理的 2D 表面(两个三角形)。 - 窗口:一个半透明的 2D 表面,基于与上面的草相同的着色器(顶点和片段)。两种纹理均从 learnopengl.com 下载
我面临的问题是,当谈到草时,我可以通过窗口看到它,但不能通过立方体看到它!
我的代码结构如下(我故意把窗口的渲染留到最后):
// 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)