OpenGL 中的混合通常被称为在对象内实现透明度的技术。
当将植被添加到场景中时,我们不想看到草的方形图像,而只想显示实际的草并看穿图像的其余部分。
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D texture1;
void main()
{
vec4 texColor = texture(texture1, TexCoords);
//颜色中的透明度小于0.1直接丢弃这个fragment
if(texColor.a < 0.1)
discard;
FragColor = texColor;
}
为了防止上面边缘的透明部分,因为repeat显示底下的部分,对最底下进行插值,变成半透明了,需要加上这一行:
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
开启混合:
glEnable(GL_BLEND);
C-source:源颜色向量,这是fragment本应显示的片段
C-destination:目的颜色,这是当前的color buffer中存储的颜色
F-source: 源 factor value(因子),源透明度值
F-destination: color buffer中存储的透明度值
总结:本身颜色*透明度 + 缓存中的颜色*透明度
假设:自身透明度0.6,而buffer中的颜色透明度为1:
glBlendFunc(GLenum sfactor, GLenum dfactor) 混合函数
两个参数来设置源和目标因子的选项。
glBlendFunc()设置alpha,取源透明度a,并取1-a为目标透明度
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
其他参数设置:
也可以分开配置RGB和alpha(glBlendFunc函数是直接一起配置了):
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
glBlendEquation(GLenum mode) OpenGL 允许我们在等式的源和目标部分之间使用其他运算符,加减乘除最大值之类的。
必须按顺序渲染,不然会出现这种情况,前面的正方形先渲染(边角也没做discard丢弃处理)
结果渲染后面的fragment的时候,depth检测到被覆盖,直接不渲染了。
遵守顺序:
透明物体-排序算法: 对物品(窗户)距离camera进行排序
// transparent window locations
// --------------------------------
vector windows
{
glm::vec3(-1.5f, 0.0f, -0.48f),
glm::vec3( 1.5f, 0.0f, 0.51f),
glm::vec3( 0.0f, 0.0f, 0.7f),
glm::vec3(-0.3f, 0.0f, -2.3f),
glm::vec3( 0.5f, 0.0f, -0.6f)
};
// sort the transparent windows before rendering
// ---------------------------------------------
std::map sorted;
for (unsigned int i = 0; i < windows.size(); i++)
{
float distance = glm::length(camera.Position - windows[i]);
sorted[distance] = windows[i];
}
对排好序的窗户进行遍历:存在了一个map中,用STL的方法进行遍历
for (std::map::reverse_iterator it = sorted.rbegin(); it != sorted.rend(); ++it)
{
model = glm::mat4(1.0f);
model = glm::translate(model, it->second);
shader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
对场景中的对象进行排序是一项艰巨的任务,这在很大程度上取决于您拥有的场景类型。