赞
踩
目录:Unity Shader - 知识点目录(先占位,后续持续更新)
原文:ShaderLab: Blending
版本:2019.1
混合
(如果大家看完还是看不懂可以再去查看我之前写过的一篇译文:Vulkan - Color Blending)
混合用于透明对象
当所有Shader都执行了,并且所有纹理都被应用了,对象的像素写入到了屏幕,那么图形被渲染出来了。如何将它们与已经存在的内容组合在一起是由Blend命令控制的。
语法
Blend Off:关闭混合(这是默认的)
Blend SrcFactor DstFactor:配置开启的混合方式。片段生成的颜色将乘以 SrcFactor。已经在屏幕了的颜色(准确说应该是已经存在framebuffer中的颜色,可查看我之前写的译文:Vulkan - Color Blending)乘以 DstFactor,然后将他们的积相加,组合为新的颜色。
(这里吐槽一下,翻译这么多篇Unity文档了,觉得Unity描述、说明得相当烂,还是OpenGL,或是Direct或是Vulkan说的最清楚,反正后面我会不定期吐槽,但是要用Unity开发啊,所以还是了解清楚好一些)
Blend SrcFactor DstFactor, SrcFactorA DstFactorA:和上面一样,但使用了不一样的alpha通道混合因子。
BlendOp Op:就如上面说的ColorBlend的积后,再相加的操作,也可以设置不一样的操作。
BlendOp OpColor, OpAlpha:和上面一样,但使用了不一样的颜色(RGB)和透明(A)通道的混合。
(
注意上面官方没有说明一些Blend分类:
混合可简写成:
finalColor.rgb = SrcColor.rgb * SrcFactor <ColorOp> DstColor.rgb * DstFactor;
finalColor.a = SrcAlpha * SrcFactorA <AlphaOp> DstAlpha * DstFactorA;
属于ColorBlend的是:SrcFactor,DstFactor
属于AlphaBlend的是:SrcFactorA,DstFactorA
属于OpBlend的是:ColorOp,AlphaOp
可查看我之前写的译文:Vulkan - Color Blending
)
另外,你还可以给指定渲染目标时设置混合模式。当你使用multiple render target(MRT:多渲染目标)渲染时,可以给每个渲染目标像上面一样设置混合模式。下面的语法可以给每个单独的渲染目标设置混合模式,N 就是渲染目标的索引(0到7)。这个功能工作于现代应将(APIs/GPUs(DX11/12, GLCore, Meta, PS4)):
AlphaToMask On:开启alpha-to-coverage覆盖。当使用MSAA(Multi-Sample Anti-Aliasing多重采样抗锯齿),alpha-to-coverage修改多重采样的覆盖掩码按比例地控制像素着色器的alpha值结果。这通常用于alpha测试后锯齿比较少的轮廓的情况;用在植被或是其他的alpha测试的shader上比较有用。
混合操作
下面是用于混合操作的枚举:
枚举 | 描述 |
---|---|
Add | 将source与destination相加。 |
Sub | Source - Destination |
RevSub | Destination-Source |
Min | Min(Source, Destination |
Max | Max(Source, Destination |
LogicalClear | 逻辑操作:Clear(0) 仅DX11.1 |
LogicalSet | 逻辑操作:Set(1) 仅DX11.1 |
LogicalCopy | 逻辑操作:Copy(s) 仅DX11.1 |
LogicalCopyInverted | 逻辑操作:Copy反向值(!s) 仅DX11.1 |
LogicalNoop | 逻辑操作:Noop(d) 仅DX11.1 (空操作) |
LogicalInvert | 逻辑操作:Invert(!d) 仅DX11.1 |
LogicalAnd | 逻辑操作:And(s&d) 仅DX11.1 |
LogicalOr | Or(s | d) 仅DX11.1 |
LogicalNor | Nor !(s | d) 仅DX11.1 |
LogicalXor | Xor (s ^ d) 仅DX11.1 |
LogcialEquiv | Equivalence !(s^d) 仅DX11.1 |
LogicAndReverse | Reverse And (s & !d) 仅DX11.1 |
LogicalAndInverted | Inverted And (!s & d) 仅DX11.1 |
LogicalOrReverse | Reverse Or (s | !d) 仅DX11.1 |
LogicalOrInverted | Inverted Or (!s | d) 仅DX11.1 |
混合因子
下面的枚举都是混合命令中两个因子 SrcFactor 和 DstFactor的值。Sourface 是片段计算的颜色, Destination 是存在于屏幕的颜色(准确说是:framebuffer的颜色)。混合因子不会收 BlendOp 的逻辑操作影响,因为BlendOp是再因子应用了Src和Dst后的逻辑处理,对最终颜色计算值会有影响。
枚举 | 描述 |
---|---|
One | (1,1,1)的分享值,可用于Src或Dst |
Zero | (0,0,0) |
SrcColor | (SrcColor.rgb) |
SrcAlpha | (SrcAlpha.aaa) |
DstColor | (DstColor.rgb) |
DstAlpha | (SrcAlpha.aaa) |
OneMinusSrcColor | (1 - SrcColor.rgb) |
OneMinusSrcAlpha | (1 - SrcColor.aaa) |
OneMinusDstColor | (1 - DstColor.rgb) |
OneMinusDstAlpha | (1 - DstColor.aaa) |
下面是常用的混合类型:
Blend SrcAlpha OneMinusSrcAlpha // 传统透明
Blend One OneMinusSrcAlpha // 预乘Alpha的透明
Blend One One // 叠加
Blend OneMinusDstColor One // 软叠加
Blend DstColor Zero // 混合色调
Blend DstColor SrcColor // 双倍的混合色调
alpha混合,alpha测试,alpha覆盖
绘制多数的不透明或全透明对象时,当透明度是使用纹理的alpha通道来决定的(如,叶子,草,锁链,等等),一些常用的用法如下:
alpha混合
一般的alpha混合
通常是意味着对象被认为是"semitransparent"(半透明的),因此不能使用某些渲染功能(例如:延迟渲染,不能接收阴影)。凹面体或是自身重叠了alpha混合的对象通常也有绘制顺序的问题。
通常,alpha混合着色器也会设置 transparent的render queue渲染队列,且会关闭深度写入。就像下面的代码写法一样:
// inside SubShader
Tags { "Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector"="True" }
// inside Pass
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
alpha测试/剔除
在像素着色器中的clip()
在像素着色器中使用 clip() HLSL的指令,那么这个像素将被取消掉绘制(当clip(v)中的v值有小于0的数值时都会被取消绘制该像素,其实v可以是Type[N], N:1~4都分量维度数,如:float, half, fixed1, float3, half4,那么如果所有的分量都小于0,那么就会剔除该像素的绘制)。这意味着,对象仍然还是不透明对象,并且也不会有渲染顺序的问题。然而,这意味着像素只能是要么不透明,要么全透明,那么将导致锯齿的出现(“jaggies”)。
通常,alpha测试的Shader也会设置 cutout(AlphaTest) 的render queue 渲染队列,如下代码:
// inside SubShader
Tags { "Queue"="AlphaTest" "RenderType"="TransparentCutout" "IgnoreProjector"="True" }
// inside CGPROGRAM in the fragment Shader:
clip(textureColor.a - alphaCutoffValue);
alpha覆盖
在4被MSAA(多重采样)开启AlphaToMask
当使用多重采样来抗锯齿(MSAA,查看 QualitySettings),使用GPU的alpha-to-coverage功能,可能会提升alpha测试这种方法的效果。提升了边缘的表现,依赖于MSAA的使用级别。
这个功能在纹理几乎都不透明或是全透明的情况下工作得最大,并且看想来会有部分的半透明似的效果(草,叶子,之类的非常适合)。
通常,alpha-to-coverage Shader 也会是指 render queue 渲染队列。代码如下:
// inside SubShader
Tags { "Queue"="AlphaTest" "RenderType"="TransparentCutout" "IgnoreProjector"="True" }
// inside Pass
AlphaToMask On
这儿有个例子,将纹理叠加到屏幕颜色重:
Shader "Simple Additive" {
Properties {
_MainTex ("Texture to blend", 2D) = "black" {}
}
SubShader {
Tags { "Queue" = "Transparent" }
Pass {
Blend One One
SetTexture [_MainTex] { combine texture }
}
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。