opengl学习-混合

不使用混合如何实现透明度

通过在片源着色器中添加if (texColor.a < 0.1) discard;来根据透明度的值判断是否丢弃片段,丢弃的片段不会被进一步处理,不会进入颜色缓冲。效果如下。

image.png

这里有个问题是草的顶部可以看到一个有色边框,这是因为当采样纹理边缘的时候,OpenGL会对边缘的值和纹理下一个重复的值进行插值(因为我们将它的环绕方式设置为了GL_REPEAT。)为了避免这个问题当我们使用alpha纹理的时候,要将纹理的环绕方式设置为GL_CLAMP_TO_EGDGE

使用混合

虽然可以直接丢弃片段,但我们还是不能渲染半透明的图像,只能要么渲染要么丢弃。要想渲染多个透明度级别的图像,需要启用混合。

启用混合

glEnable(GL_BLEND);

混合方程

C_result = C_source ∗ F_source + C_destination ∗ F_destination

  • C_source:源颜色向量。这是源自纹理的颜色向量。
  • C_destination:目标颜色向量。这是当前储存在颜色缓冲中的颜色向- 量。
  • F_source:源因子值。指定了alpha值对源颜色的影响。
  • F_destination:目标因子值。指定了alpha值对目标颜色的影响。

片段着色器运行完成后,并且所有的测试都通过之后,这个混合方程才会应用到片段颜色输出与当前颜色缓冲中的值(当前片段之前储存的之前片段的颜色)上。源颜色和目标颜色将会由OpenGL自动设定,但源因子和目标因子的值可以由我们来决定。

设置源因子和目标因子

glBlendFunc(GLenum sfactor, GLenum dfactor)
glBlendFuncSeparate 可以为RGB和alpha通道分别设置不同的值
glBlendColor 可以设置常数颜色向量C_constant

可选值有

  • GL_ZERO 因子等于0
  • GL_ONE 因子等于1
  • GL_SRC_COLOR 因子等于源颜色向量C_source
  • GL_ONE_MINUS_SRC_COLOR 因子等于1−C_source
  • GL_DST_COLOR 因子等于目标颜色向量C_destination
  • GL_ONE_MINUS_DST_COLOR 因子等于1−C_destination
  • GL_SRC_ALPHA 因子等于C_source的alpha分量
  • GL_ONE_MINUS_SRC_ALPHA 因子等于1− C_source的alpha分量
  • GL_DST_ALPHA 因子等于C¯destination的alpha分量
  • GL_ONE_MINUS_DST_ALPHA 因子等于1− C_destination的alpha分量
  • GL_CONSTANT_COLOR 因子等于常数颜色向量C_constant
  • GL_ONE_MINUS_CONSTANT_COLOR 因子等于1−C_constant
  • GL_CONSTANT_ALPHA 因子等于C_constant的alpha分量
  • GL_ONE_MINUS_CONSTANT_ALPHA 因子等于1− C_constant的alpha分量

改变方程中源和目标部分的运算符

glBlendEquation(GLenum mode)允许我们设置运算符

  • GL_FUNC_ADD:默认选项,将两个分量相加:C=Src+Dst。
  • GL_FUNC_SUBTRACT:将两个分量相减: C=Src−Dst。
  • GL_FUNC_REVERSE_SUBTRACT:将两个分量相减,但顺序相反:C=Dst−Src。

开始使用混合

glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

image.png

可以发现最前面窗户的透明部分遮蔽了背后的窗户,因为写入深度缓冲时,深度缓冲不会检查片段是否是透明的,所以透明的部分会和其它值一样写入到深度缓冲中。结果就是窗户的整个四边形不论透明度都会进行深度测试。即使透明的部分应该显示背后的窗户,深度测试仍然丢弃了它们。
要想保证窗户中能够显示它们背后的窗户,我们需要首先绘制背后的这部分窗户。也就是我们必须先手动将窗户按照最远到最近来排序,再按照顺序渲染。

绘制顺序规则需要如下

  1. 先绘制所有不透明的物体。
  2. 对所有透明的物体排序。
  3. 按顺序绘制所有透明的物体。

排序透明物体的一种方法是,从观察者视角获取物体的距离。这可以通过计算摄像机位置向量和物体的位置向量之间的距离所获得。
添加代码根据举例排序然后按顺序绘制

  std::map<float, glm::vec3> sorted;
        for (unsigned int i = 0; i < vegetation.size(); i++) {
            float distance = glm::length(camera.Position - vegetation[i]);
            sorted[distance] = vegetation[i];
        }
image.png

按照距离排序物体这种方法并没有考虑旋转、缩放或者其它的变换,奇怪形状的物体需要一个不同的计量,而不是仅仅一个位置向量。
在场景中排序物体是一个很困难的技术,更高级的技术有次序无关透明度(Order Independent Transparency, OIT)。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容