学习教程来自:【技术美术百人计划】图形 3.2 混合模式及剔除
笔记
1. 什么是混合模式?
将当前已有颜色和即将绘制的颜色混合在一起的方式或算法。
语法:
|代码|说明|
|:——:|:——:|
|Blend Off|关闭混合(默认)|
|Blend SrcFactor DstFactor|color = shader输出颜色 * SrcFactor op GBuffer中的颜色 * DstFactor|
|Blend SrcFactor DstFactor, SrcFactorA DstFactorA|同上,额外指定了Alpha通道的混合参数|
|BlendOp Value|指定混合方式,默认ADD|
|BlendOp OpColor, OpAlpha|同上,额外指定了Alpha|
|AlphaToMaskOn|常用在开启MSAA的地表植被的渲染|
2. 混合模式有哪些类型?
一些常见的混合,详见官方文档
Blend SrcAlpha OneMinusSrcAlpha // Traditional transparency alpha混合
Blend One OneMinusSrcAlpha // Premultiplied transparency 预乘透明度
Blend One One // Additive 相加混合
Blend OneMinusDstColor One // Soft Additive 柔和相加混合
Blend DstColor Zero // Multiplicative 相乘混合 正片叠底
Blend DstColor SrcColor // 2x Multiplicative 2倍相乘混合
使用代码
Blend N SrcFactor DstFactor
Blend N SrcFactor DstFactor, SrcFactorA DstFactorA
BlendOp N Op
BlendOp N OpColor, OpAlpha
3. 混合模式的实现方式
src当前颜色,dst缓冲区已有颜色,一些效果暂时调不出来(BlendOp为空的部分)
混合模式 | PS代码 | BlendOp | SrcBlend | DstBlend | 备注 |
---|---|---|---|---|---|
Alphablend | Src.a Src + (1.0 - Src.a) Dst | ADD | SrcAlpha | OneMinusSrcAlpha | 透明混合 |
Darken | min(Src, Dst) | Min | - | - | 变暗 |
Multiply | Src * Dst | Multiply | - | - | 正片叠底 |
ColorBurn | 1.0 - (1.0 - Dst) / Src | ColorBurn | - | - | 颜色加深 |
LinearBurn | Src + Dst - 1.0 | - | - | - | 线性加深 |
DarkerColor | (Src.x + Src.y + Src.z < Dst.x + Dst.y + Dst.z) ? Src : Dst | Min | - | - | 深色 |
Lighten | max(Src, Dst) | Max | - | - | 变亮 |
Screen | Src (1 - Dst) + Dst 1 | ADD | OneMinusDstColor | One | 滤色 |
ColorDodge | Dst / (1.0 - Src) | ColorDodge | - | - | 颜色减淡 |
LinearDodge | Src + Dst | ADD | One | One | 线性减淡 |
LighterColor | (Src.x + Src.y + Src.z > Dst.x + Dst.y + Dst.z) ? Src : Dst | Lighten | - | - | 浅色 |
Overlay | (Dst < 0.5) ? 2.0 Src Dst : 1.0 - 2.0 (1.0 - Src) (1.0 - Dst) | Overlay | - | - | 叠加 |
SoftLight | (Src < 0.5) ? Dst - (1.0 - 2.0 Src) Dst (1.0 - Dst) : (Dst < 0.25) ? Dst 000000+ (2.0 Src - 1.0) Dst ((16.0 Dst - 12.0) Dst + 3.0) : Dst + (2.0 Src - 1.0) (sqrt(Dst) - Dst) |
SoftLight | - | - | 柔光 |
HardLight | (Src < 0.5) ? 2.0 Src Dst : 1.0 - 2.0 (1.0 - Src) (1.0 - Dst) | HardLight | - | - | 强光 |
VividLight | (Src < 0.5) ? 1.0 - (1.0 - Dst) / (2.0 Src) : Dst / (2.0 (1.0 - Src)) | - | - | - | 亮光 |
LinearLight | 2.0 * Src + Dst - 1.0 | - | - | - | 线性光 |
PinLight | (2.0 Src - 1.0 > Dst) ? 2.0 Src - 1.0 : (Src < 0.5 Dst) ? 2.0 Src : Dst | - | - | - | 点光 |
HardMix | floor(Src + Dst) | - | - | - | 实色混合 |
Difference | abs(Dst - Src) | Difference | - | - | 差值 |
Exclusion | Src + Dst - 2.0 Src Dst | Exclusion | - | - | 排除 |
Subtract | Src - Dst | ReverseSubstrat | One | One | 减去 |
Divide | Src / Dst | - | - | - | 划分 |
Hue | Dst = RGB2HSV(Dst);Dst.x = RGB2HSV(Src).x; return HSV2RGB(Dst); | HSLHue | - | - | 色相 |
Saturation | Dst = RGB2HSV(Dst); Dst.y = RGB2HSV(Src).y; return HSV2RGB(Dst); | - | - | - | 饱和度 |
Color | Src = RGB2HSV(Src);Src.z = RGB2HSV(Dst).z; return HSV2RGB(Src); | - | - | - | 颜色 |
Luminosity | float dLum = dot(Dst, float3(0.3, 0.59, 0.11)); float sLum = dot(Src, float3(0.3, 0.59, 0.11)); float lum = sLum - dLum; float3 C = Dst + lum; float minC = min(min(C.x, C.y), C.z); float maxC = max(max(C.x, C.y), C.z); if (minC < 0.0) return sLum + ((C - sLum) sLum) / (sLum - minC); else if (maxC > 1.0) return sLum + ((C - sLum) (1.0 - sLum)) / (maxC - sLum); else return C; |
HSLLuminoslingity | - | - | 明度 |
ColorBurn只支持OpenGL,DX不支持
遇到的问题:源码中的部分混合效果需要颠倒src和dst的位置。OpenGL下部分效果可以调出,但自带的枚举下SrcBlend和DstBlend失效
4. 剔除的实现方式
- 法线剔除:根据法线朝向进行剔除,Cull Off/Front/Back
- 面裁切:在片元阶段直接丢弃满足某些条件的像素,Clip(),在某些PowerVR机型上效率很低,最好在AlphaTest队列中使用
作业
实现常用的混合模式,并设计使用界面
基于3中的表格,增加了混合的配置界面,对于src和dst可调的开放了参数设置,并增加了预设值。对于失效的则不显示参数选择。正确性未知的不予显示。