参考
韩世麟 把 PS 图层混合模式理解到这个程度,就算是入门了
Wiki Blend_modes
冯乐乐 《Unity Shader入门精要》
Ps混合模式的计算原理,宇宙最穷的进阶笔记

混合

图层混合模式规则

  1. 0 - 255要换算到0 - 1区间
  2. 逐像素,分通道

常见的混合类型

为叙述方便,定义原图或下层的颜色为底色A,画笔或上层颜色为绘图色B,混合之后的颜色为最终色C

各种模式

正常透明度混合(Normal)

默认状态,最终色与绘图色相同。当上层有透明度时混合方式如下:

C=A∗(1−B.alpha)+B∗B.alphaC = A *(1 - B.alpha) + B * B.alphaC=A∗(1−B.alpha)+B∗B.alpha

溶解(Dissolve)

从两个图层中随机取得像素,上层图像的不透明度越高所占权重越高

变暗系

变暗(Darken)

选取两个颜色中较暗的颜色作为最终色

C=min(A,B)C = min(A, B)C=min(A,B)

正片叠底(Multiply)

将两种颜色相乘

C=ABC = A BC=AB

  • 去白留黑
  • 满足交换律,上下不影响结果
  • 可使用黑白线稿与原图相乘来获得描边
  • 模拟暗房中两张正片(所见即所得的底片)重叠的效果

颜色加深(Color Burn)

将底层反相后除以顶层,再反相

C=A−(1−A)(1−B)/B=1−(1−A)/BC = A - (1 - A) (1 - B) / B=1-(1-A)/BC=A−(1−A)(1−B)/B=1−(1−A)/B

  • 将纯黑图层至于上方时,图像不会变成全黑,会出现失真现象(分母不能出现0,ps中的输入值最大为251,因此底图的过曝部分不会受到影响)

线性加深

将两个图层相加后减去1,等价于两个图层取反相加再取反(线性减淡各项取反)

C=A+B−1=1−((1−A)+(1−B))C = A + B - 1=1-((1-A)+(1-B))C=A+B−1=1−((1−A)+(1−B))

变亮系

变亮(Lighten)

选取两个颜色中较亮的作为最终色

C=max(A,B)C = max(A, B)C=max(A,B)

滤色(Screen)

将两种颜色取反之后相乘,再取反
C=1−(1−A)(1−B)C = 1 - (1 - A) (1 - B)C=1−(1−A)(1−B)

  • 去黑留白

  • 滤色之后的图像会提亮且绝对不会过曝(结果必小于1),能够保留更多细节

  • A的反相与B的反相相乘等于C的反相,可看作是正片叠底的逆运算(各项均取反)(1−C)=(1−A)(1−B)(1-C)=(1-A)(1-B)(1−C)=(1−A)(1−B)

  • 两张相同的图片进行滤色约等于将中间亮度提高到75%的曲线

  • 模拟在暗房中将两张负片重叠后进行曝光的效果

颜色减淡(Color Dodge)

底层除以反相后的顶层

C=A+(A∗B)/(1−B)=A/(1−B)C = A + (A * B) / (1 - B)=A/(1-B)C=A+(A∗B)/(1−B)=A/(1−B)

  • 将纯白图层至于顶层后不会变成全白,会出现失真

线性减淡(Linear Dodge / Additive)

两图层相加

C=A+BC = A + BC=A+B

饱和度系

叠加(overlay)

根据底色是否大于50%中灰来决定使用正片叠底滤色,使暗的变暗、亮的变亮,提高对比度

{C=2AB,ifA<0.5C=1−2(1−A)(1−B),otherwise\begin{cases} C=2AB, & ifA<0.5\\ C=1-2(1-A)(1-B),&otherwise\\ \end{cases}{C=2AB,C=1−2(1−A)(1−B),​ifA<0.5otherwise​

  • 抠中灰,留黑白
  • 对应函数曲线如下图,可以看出当图片叠加它自己时等效于如下图的曲线,亮部变亮、暗部变暗以提高对比度

强光(Hard Light)

公式与叠加模式相同,但是叠加是根据底色来判断,强光则是根据绘图色与50%中灰的关系来判断使用正片叠底还是滤色

{C=2AB,ifB<0.5C=1−2(1−A)(1−B),otherwise\begin{cases} C=2AB, & ifB<0.5\\ C=1-2(1-A)(1-B),&otherwise\\ \end{cases}{C=2AB,C=1−2(1−A)(1−B),​ifB<0.5otherwise​

柔光(Soft Light)

根据绘图色的明暗来决定提亮还是变暗,原理与强光相同,曲线相比于强光更加柔和

{C=2AB+A2(1−2B),ifB<0.5C=2A(1−B)+A(2B−1),otherwise\begin{cases} C=2AB+A^2(1-2B), & ifB<0.5\\ C=2A(1-B)+\sqrt{A}(2B-1),&otherwise\\ \end{cases}{C=2AB+A2(1−2B),C=2A(1−B)+A​(2B−1),​ifB<0.5otherwise​

  • 柔光与叠加的曲线对比

叠加的上下图层*

ps中对混合模式常用的操作是在原图上方增加一个图层作为控制图层,从直觉上来判断是对上方图层的操作影响了下方图层。

在这种方式下,使用黑色笔刷在控制图层上进行涂抹时,混合之后的图像并不会变成纯黑色,与公式中两倍的正片叠底/两倍的滤色不匹配。

分析公式可以得知,叠加的控制层应该在下方,即下方颜色与中灰的关系决定最终图像是变亮还是变暗。

将控制图层至于下方时,可以看到最终效果符合公式定义。

因此许多人对图层混合的理解其实是错误的。使用传统的操作方法可能会出现灰度突变的问题。

下图中使用上方图层作为控制层,用黑色笔刷进行加深之后,能看到中间有一道明显的分界线。因为实际上的控制层在下方,因此下图中接近中灰的位置会进行判断,左侧使用的正片叠底而右侧使用了滤色。
而上方的图层是被改变的图层,左侧的纯黑经过正片叠底运算之后依旧是纯黑,并不会受影响。但是右边的纯黑会受到滤色的影响而迅速变亮。这就形成了中灰位置的分界线。
但是反过来,这种特性也能够起到保留边界的作用。

下图中左侧的墙壁亮度小于50%,右侧亮度大于50%,因此中间的分界线得到了非常清晰的保留。

将调整图层至于上方的传统做法虽然与实际原理不符,但是不代表一定是错误的用法。毕竟根据只要它看起来是对的那么它就是对的的原则,能够得到想要的效果的方法就是最好的方法。实际应用中应当根据实际的需求来决定,切忌教条化。

Unity中的颜色混合

混合操作发生于光栅化阶段最后的逐片元操作中,透明度测试之后

渲染顺序

在开启深度写入的情况下,物体背后的其他物体会在深度测试中被剔除,导致无法通过半透明表面看到后边的物体,因此半透明物体的渲染需要关闭深度写入。
因为半透明物体的渲染需要关闭深度写入,所以半透明物体的渲染顺序非常重要。

渲染引擎一般都会先对物体进行排序,再渲染。常用的方法为:

  1. 先渲染所有不透明物体,并开启它们的深度测试与深度写入。
  2. 把半透明物体按它们距离摄像机的远近进行排序,然后按照从后往前的顺序渲染这些半透明物体,并开启它们的深度测试,关闭深度写入。

但是以上面的方法进行渲染还是会出现一些问题。由于深度缓冲区中的值是像素级别的,排序时却是对物体进行排序,这就会导致有些物体之间出现穿插产生了循环重叠的现象时无法得到正确的渲染结果。

上图中三个循环重叠的物体无法得到正确的渲染结果。这种情况需要通过分割网格的方法来解决。

Unity中解决渲染顺序问题提供的方案是渲染队列(render queue)。使用SubShader的Queue标签来决定模型归属于哪个队列。Unity内部使用一系列整数索引来表示每个渲染队列,且索引号越小表示越早被渲染。

名称 队列索引号 描述
Background 1000 这个渲染队列会在任何其他队列之前被渲染,通常使用该队列来渲染那些需要绘制在背景上的物体
Geometry 2000 默认的渲染队列,大多数物体包括不透明物体使用这个队列。
AlphaTest 2450 需要透明度测试的物体使用这个队列。在Unity 5中它从Geometry队列中被单独分离出来,这是因为在所有不透明物体渲染之后再渲染它们会更加高效
Transparent 3000 这个队列中的物体会在所有 Geometry 和 AlphaTest 物体渲染后再按从后往前的顺序进行渲染。任何使用了透明度混合的物体都应该使用该队列
Overlay 4000 该队列用于实现一些叠加效果。任何需要在最后渲染的物体都应使用该队列

ShaderLab的混合命令

当片元着色器产生一个颜色时,可以选择与颜色缓冲中的颜色进行混合。混合与两个参数有关:源颜色(source color)目标颜色(destination color)。源颜色用S表示,指的是片元着色器生成的颜色值;目标颜色用D表示,指的是颜色缓冲中读取到的颜色值。将它们混合之后得到的输出颜色O会重新写入颜色缓冲区。

混合是一个逐片元的操作,不可编程但是高度可配置。将源颜色S和目标颜色D通过混合等式(blend equation) 进行混合后得到输出颜色O。进行混合时需要使用两个混合等式:一个用于混合RGB通道,一个用于混合A通道。

设置混合状态状态实际上设置的是混合等式中的操作因子。默认状态下的操作为加操作,因此通常需要设置的是混合因子。设置2个因子,RGB和A将以相同的方式进行混合;设置4种因子,RGB和A将以各自的方式进行混合。

命令 描述
Blend SrcFactor DstFactor 开启混合,设置混合因子,源颜色乘以SrcFactor,目标颜色乘以DstFactor,之后将两者相加再存入颜色缓冲中
Blend SrcFactor DstFactor,
SrcFactorA DstFactorA
除使用不同的因子来混合透明通道外其余与上边相同

混合公式:

Orgb=SrcFactor×Srgb+DstFactor×DrgbOa=SrcFactorA×Sa+DstFactorA×DaO_{rgb}=SrcFactor\times S_{rgb}+DstFactor\times D_{rgb} \\ O_{a}=SrcFactorA\times S_{a}+DstFactorA\times D_{a} Orgb​=SrcFactor×Srgb​+DstFactor×Drgb​Oa​=SrcFactorA×Sa​+DstFactorA×Da​

ShaderLab 中的混合因子

参数 描述
One 因子为1
Zero 因子为0
SrcColor 因子为源颜色值。当用于混合RGB的混合等式时,使用SrcColor的RGB分量作为混合因子;当用于混合A的混合等式时,使用SrcColor的A分量作为混合因子
SrcAlpha 因子为源颜色的透明度值(A通道)
DstColor 因子为目标颜色值。当用于混合RGB的混合等式时,使用DstColor的RGB分量作为混合因子;当用于混合A的混合等式时,使用DstColor的A分量作为混合因子
DstAlpha 因子为目标颜色的透明度值(A通道)
OneMinusSrcColor 因子为(1-源颜色)。当用于混合RGB的混合等式时,使用结果的RGB分量作为混合因子;当用于混合A的混合等式时,使用结果的A分量作为混合因子
OneMinusSrcAlpha 因子为(1-源颜色的透明度值)
OneMinusDstColor 因子为(1-目标颜色)。当用于混合RGB的混合等式时,使用结果的RGB分量作为混合因子;当用于混合A的混合等式时,使用结果的A分量作为混合因子
OneMinusDstAlpha 因子为(1-目标颜色的透明度值)

使用上边的指令进行设置时,RGB通道的混合因子和A通道的混合因子都是一样的。有时我们希望可以使用不同的参数混合A通道,这时就可以利用Blend SrcFactor DstFactor,SrcFactorA DstFactorA 指令。例如,如果我们想要在混合后输出颜色的透明度就是源颜色的透明度,可以使用下面的命令:

Blend SrcAlpha OneMinusSrcAlpha, One Zero

混合操作

上面涉及的混合等式都是将源颜色和目标颜色与对应的混合因子相乘后的结果相加作为输出颜色。使用ShaderLab的BlendOp BlendOperation命令可以设置其他的混合操作。

操作 描述
Add 将混合后的源颜色与目标颜色相加。默认的混合操作。等式为:
Orgb=SrcFactor×Srgb+DstFactor×DrgbO_{rgb}=SrcFactor\times S_{rgb}+DstFactor\times D_{rgb}Orgb​=SrcFactor×Srgb​+DstFactor×Drgb​
Oa=SrcFactorA×Sa+DstFactorA×DaO_{a}=SrcFactorA\times S_{a}+DstFactorA\times D_{a}Oa​=SrcFactorA×Sa​+DstFactorA×Da​
Sub 用混合后的源颜色减去混合后的目标颜色。等式为:
Orgb=SrcFactor×Srgb−DstFactor×DrgbO_{rgb}=SrcFactor\times S_{rgb}-DstFactor\times D_{rgb}Orgb​=SrcFactor×Srgb​−DstFactor×Drgb​
Oa=SrcFactorA×Sa−DstFactorA×DaO_{a}=SrcFactorA\times S_{a}-DstFactorA\times D_{a}Oa​=SrcFactorA×Sa​−DstFactorA×Da​
RevSub 用混合后的目标颜色减去混合后的源颜色。等式为:
Orgb=DstFactor×Srgb−SrcFactor×DrgbO_{rgb}=DstFactor\times S_{rgb}-SrcFactor\times D_{rgb}Orgb​=DstFactor×Srgb​−SrcFactor×Drgb​
Oa=DstFactorA×Sa−SrcFactorA×DaO_{a}=DstFactorA\times S_{a}-SrcFactorA\times D_{a}Oa​=DstFactorA×Sa​−SrcFactorA×Da​
Min 使用源颜色和目标颜色中较小的值作为最终结果,逐分量比较。等式为:
Orgba=(min(Sr,Dr),min(Sg,Dg),min(Sb,Db),min(Sa,Da))O_{rgba}=(min(S_r, D_r),min(S_g, D_g),min(S_b, D_b),min(S_a, D_a))Orgba​=(min(Sr​,Dr​),min(Sg​,Dg​),min(Sb​,Db​),min(Sa​,Da​))
Max 使用源颜色和目标颜色中较大的值作为最终结果,逐分量比较。等式为:
Orgba=(max(Sr,Dr),max(Sg,Dg),max(Sb,Db),max(Sa,Da))O_{rgba}=(max(S_r, D_r),max(S_g, D_g),max(S_b, D_b),max(S_a, D_a))Orgba​=(max(Sr​,Dr​),max(Sg​,Dg​),max(Sb​,Db​),max(Sa​,Da​))
其他逻辑操作 仅支持D3D11.1,详见官方文档

常见的混合类型

通过混合操作和混合类型的组合,可以得到一些类似Photoshop混合模式中的混合效果

//正常(Normal),即透明度混合
Blend SrcAlpha OneMinusSrcAlpha//柔和相加(Soft Additive)
Blend OneMinusDstColor One//正片叠底(Multiply)
Blend DstColor Zero//变暗(Darken)
BlendOp Min
Blend One One//变亮(Lighten)
BlendOp Max
Blend One One//滤色(Screen)         C = 1-(1-A)(1-B) = A+B-AB = A+B(1-A) = A(1-B)+B
Blend OneMinusDstColor One
//等同于
Blend One OneMinusSrcColor //线性减淡
Blend One One

Blend 混合模式相关推荐

  1. shader Blend混合模式讲解

    内容说明: 1.混合(blend)说明 2.在OpenGL中的使用 3. Unity中的使用 1. 什么是混合 混合是什么呢?混合就是把两种颜色混在一起.具体一点,就是把某一像素位置原来的颜色和将要画 ...

  2. Android OpenGL射线拾取手势旋转(二)

    上回分解-_-!,Android OpenGL射线拾取&手势旋转(一). 3)Renderer:RayPickRenderer.java OpenGL渲染器,比较多的东西都在这里面了. pub ...

  3. Unity 之 ShaderGraph Input节点解析汇总

    Unity 之 ShaderGraph Input节点解析汇总 一,Input Basic 基础输入节点 1.1 Vector 1, 2, 3, 4 1.2 Boolean 1.3 Color 1.4 ...

  4. 前端必看的8个HTML+CSS技巧

    点赞是动力 ??,关注是支持 ??! 建议.疑问.话题欢迎在评论区留言哦! CSS是一个很独特的语言.看起来非常简单,但是某种特殊效果看似简单,实现起来就颇有难度.这篇文章主要是给在学习前端的童鞋分享 ...

  5. OpenGL ES 2.0 总体概述

    文章目录 OpenGL ES 2.0 总体概述 1. OpenGL ES 的两个小伙伴 1.1 EGL 1.2 GLSL 2. 屏幕图片的本质和产生过程 3. OpenGL ES pipeline 3 ...

  6. Unity着色器常用关键字及属性

    看了好多次shader,不过还是感觉无从下手的去写shader,然后看shader的效果 个人认为还是因为shader基础打得不够扎实,顾特意再重温shader相关书籍的时候,看见有些常用关键字时,把 ...

  7. 2020,Laya最新中高级面试灵魂32问,你都知道吗?

    ##前言 上个月陆续给大家更新了cocos和unity的面试题,相信读者朋友们看了之后多多少少也有了一些收获,在之前的分享中,有部分读者粉丝一直私信阿博,让我分享一些金九银十服务器和Laya的面试题, ...

  8. unity物体设置透明度_透明度混合(Alpha blending)

    文章目录 前言 一.混合模式 1.说明 2.常用公式 二.问题 总结 参考 前言 本文介绍unity渲染中的透明度混合,和透明度混合相关问题. 一.混合公式 1.说明 unity上,Blend Src ...

  9. OpenGL ES: (5) OpenGL的基本概念、OpenGL ES 在屏幕产生图片的过程、OpenGL管线(pipeline)...

    一. OpenGL的基本概念 OpenGL 的结构可以从逻辑上划分为下面 3 个部分: 图元(Primitives) 缓冲区(Buffers) 光栅化(Rasterize) 图元(Primitives ...

  10. OPENGL ES 2.0 知识串讲(1)――OPENGL ES 2.0 概括

    更多图形知识请关注我的公众号: 前言 电脑是做什么用的? 电脑又被称为计算机,那么最重要的工作就是计算.看过三体的同学都知道, 电脑中有无数纳米级别的计算单元,通过 0 和 1 的转换,完成加减乘除的 ...

最新文章

  1. matlab求微分方程的系数,如何利用matlab求解矩阵系数的二阶微分方程
  2. ajax请求必须打断点才能成功,Jquery等待ajax执行完毕继续执行(断点调试正常,运行异常)...
  3. C语言的逗号!_只愿与一人十指紧扣_新浪博客
  4. 系统架构师秘籍(二)软件架构- 续
  5. linux位置变量的应用,llinux中变量的运用
  6. 专题_数字货币历史行情获取[博]
  7. 在IntelliJ IDEA中clone项目代码
  8. c#简单注册登录利用缓存存储账号密码_“密码代填”实现单点登录,安全吗?...
  9. 【转】Nero v9.4.26.0 多语(简体中文)版+完美破解(世界上最多人使用的烧录软体)...
  10. 用什么 软件测试无线频段,Wirelessmon无线频段与信号强度扫描工具软件使用技巧...
  11. NLP思维一书读书笔记
  12. flume笔记(四) Channal
  13. python线程isalive_如何在线程类上使用.isAlive()
  14. 微信支付商户号的调研
  15. matlab 变分不等式,求解变分不等式的matlab程序
  16. HGAME2020第一周杂项题——克苏鲁神话
  17. idog copy from,
  18. 全栈Python自动化测试学习资料【付费资源、看到即赚到,】
  19. wordpress仿站实战教程:wordpress调用函数记录
  20. Excel用排序做工资条

热门文章

  1. 【 开源计划 - Flutter组件 】 星星也可以如此闪耀 flutter_star
  2. OCCT学习遇到的问题记录
  3. c语言中的整型常量和实型常量
  4. adb命令连接设备出现Offline
  5. 280. 陪审团 poj1015(背包DP)
  6. 自动驾驶两大路线对决,渐进式玩家为何更容易得人心?
  7. 复旦大学数学学院 17 级本科生对每周一题的评价
  8. mysql瀑布流布局插件_瀑布流JS插件
  9. 研发质量管理工作经验总结(五)----关于流程建设的思考
  10. 电脑的wifi天线原理_详解无线路由器天线的原理