DreamShaderLang
插件参考Graph

Swizzle

Swizzle

Swizzle

DreamShader » Graph » Swizzle

对数值使用后缀成员访问,用于选择、重排或重复其通道。

声明于.dsm, .dsf — 位于 Graph { … } 体内、Outputs 绑定表达式内,或 Outputs 声明默认值中
类型表达式,后缀
生成对于升序掩码生成一个 UMaterialExpressionComponentMask;当源节点恰好为这些通道提供输出引脚时生成无;对于重排或重复掩码,每个通道生成一个掩码加 UMaterialExpressionAppendVector × (N−1)

概要

<swizzle> := <expression> . <channels>
<channels> := <channel> [ <channel> ] [ <channel> ] [ <channel> ]
<channel>  := { x | y | z | w | r | g | b | a }

一到四个通道字符。. 和通道字母是字面量;[ … ] 和 { a | b } 是元记号。

通道集合

字符通道索引
x, X, r, R0
y, Y, g, G1
z, Z, b, B2
w, W, a, A3
  • 恰好存在两个集合:xyzw 和 rgba。没有 stpq 集合,也没有 uv 集合 — u 和 v 均无法解析,因此 .uv 会失败并产生 DSH4230。
  • 通道字符不区分大小写进行匹配:.RGB, .Rgb, .XyZ 均有效。
  • 在一个 swizzle 中混用两个集合是 DSH4230 (自 2.0.0 起;1.x 将 .xg 视为 .xy)。

长度与边界

规则违规
一到四个通道字符5 个或更多:DSH4230
每个字符必须是通道字母未知字母:DSH4230
每个通道索引必须小于基础值的分量数超出范围:DSH4230
每个 swizzle 一个集合.xg: DSH4230

swizzle 只能缩小或重排;它永远无法读取超出基础宽度的内容。

基础Swizzle结果
float4.rgbfloat3
float3.a错误 — 通道 3 ≥ 3 个分量
float2.xyz错误 — 通道 2 ≥ 2 个分量
float.x, .r基础值
float.xx, .rrr散布为 float2 / float3
float.y, .z, .w, .g, .b, .a错误

[!WARNING] 标量不会通过超出范围的通道进行散布。 对标量参数使用 Roughness.yz 是一个硬错误,而不是两分量广播:DSH4230。要广播标量,请重复通道 0 (Roughness.xx)、使用构造函数(float2(Roughness)),或依赖 赋值时的标量拓宽。

降级

(自 2.0.0 起) swizzle 是一个节点:生成器从不在连接上放置通道掩码。以下四种 情况按此顺序尝试。

#适用条件创建的节点结果
1源节点恰好将所选通道作为输出引脚发布 — 纹理采样的 .rgb 或 .a、向量参数的 .rgb 或 .r无读取该引脚
2通道索引严格递增且无重复一个 ComponentMask所选通道
3基础有 2–4 个分量且掩码被重排或重复每个不同通道一个单通道掩码(或按情况 1 使用其引脚),然后 N−1 个 AppendVector各部分串联
4基础有 1 个分量且每个通道都在范围内N−1 个 AppendVector(对于 1 字符 swizzle 则无)标量复制 N 次

恒等掩码 — 值的每个通道按顺序:.x 作用于 float、.rgb 作用于 float3 — 在 .dss 中不是 节点。在 1.x 源中它保留为 ComponentMask,因为 1.x 无论值声明为哪种宽度 都会对连接进行掩码。

顺序与非顺序掩码

Swizzle通道情况节点成本
.r / .x021 个 ComponentMask
.a321 个 ComponentMask
.rg / .xy0,121 个 ComponentMask
.rgb / .xyz0,1,221 个 ComponentMask
.ga1,32 — 递增,允许有间隔1 个 ComponentMask
.rgba 作用于 float40,1,2,3恒等在 .dss 中无;在 1.x 源中为 1 个 ComponentMask
.gr1,032 个 ComponentMask, 1 个 AppendVector
.bgr2,1,03 (自 1.3.3 起)3 个 ComponentMask, 2 个 AppendVector
.xxx0,0,031 个 ComponentMask, 2 个 AppendVector
.rrgg0,0,1,132 个 ComponentMask, 3 个 AppendVector
.rr 作用于 float0,041 个 AppendVector

凡源节点有引脚之处,情况 1 会将此表中的 ComponentMask 替换为引脚。无论 swizzle 被书写多少次,每个 节点都只计数一次:相等的节点会被合并(参见 节点复用)。

组合 swizzle

对已 swizzle 的值再次 swizzle 会通过现有掩码重新映射,因此通道编号始终 相对于被 swizzle 的值,而不是相对于原始节点。

书写含义
v.rgb.bv 的通道 2 — .rgb 选择 {0,1,2},然后 .b 选取该列表的条目 2
v.ga.rv 的通道 1 — .ga 选择 {1,3},然后 .r 选取条目 0
v.ga.gv 的通道 3
v.bgr.rv 的通道 2

当结果保持升序时,掩码的掩码会折叠为一个掩码,因此 v.rgb.rg 在 v 上是一个 ComponentMask(或一个引脚)。选择外部列表中不存在的条目是针对 已 swizzle 宽度的 普通边界失败 — v.ga.b 是 DSH4230,因为 .ga 有 2 个分量,无论 v 的宽度如何。

对调用结果进行 swizzle

. 是普通后缀运算符,因此任何调用结果都可以直接 swizzle — 无需临时 变量。

float u  = UE.TexCoord().x;
vec3  c  = SampleTexture2D(Albedo, uv).rgb;
vec2  yx = vec4(1.0, 2.0, 3.0, 4.0).yx;
float m  = MyFunction(A, B).r;

Swizzle 应用于调用的值。对于 Function、GraphFunction、ShaderFunction 或 VirtualFunction 的调用,若成员名是函数某个输出的名称,则改选该输出; 当函数不返回任何内容时,任意成员也如此(旧规则 L3b):在仅有 out 参数的函数上的 .r 会被读取为输出名称,且 DSH5280,除非有个输出名为 r。参见 调用。对于具有多个输出的 UE.* 节点,成员名指定一个输出; 当输出是同一个值的通道视图时(例如纹理采样),允许使用 swizzle。

不可 swizzle 的基础值

对非数值值的成员访问并不是 swizzle。

基础值行为
MaterialAttributes不是 swizzle。成员名会作为材质属性解析并读取。参见 MaterialAttributes
纹理对象DSH4206:纹理的成员是采样方法,必须被调用
SubstrateDSH4207:该值没有这样的成员

说明

  • 无论写多少次,一个 swizzle 只消耗一个节点:Src.rgb 使用十次就是一个 ComponentMask —— 或者当 Src 具有 RGB 引脚时,不消耗节点。
  • 在 1.x 源中的窄化会以相同的 swizzle 取前导通道(r、rg、rgb),因此 隐式裁剪的开销与 swizzle 相同。参见 转换。
  • 常量的 swizzle 会被折叠:vec4(1.0, 2.0, 3.0, 4.0).yx 就是一个 Constant2Vector(2, 1)。
  • 重复和重排序的 swizzle 会像任何其他表达式一样被合并,因此 Src.bgr 写两次 只会产生一条 AppendVector 链。参见 节点复用。
  • . 后跟任何非标识符的内容,在任何 swizzle 逻辑运行之前就是解析错误: DSH2161。

诊断

代码触发条件
DSH4230出现了非通道字母的字符、超过四个字符、通道达到或超出基础值宽度,或两组通道混用。
DSH4206纹理对象的成员。
DSH4207没有成员的值的成员,例如 Substrate 值。
DSH5201多输出 UE.* 节点的成员未指定任何输出,或 swizzle 跨越了位于不同输出上的通道。
DSH5280仅有 out 参数的函数调用的成员未指定任何输出。
DSH2161. 后未跟标识符。
DSH8214、DSH8226发射器无法创建 ComponentMask 或 AppendVector 节点,或收到的掩码不是一到四个升序通道(内部防护)。

示例

Shader(Name="Docs/M_Swizzle")
{
    Properties { vec4 Src = vec4(0.1, 0.2, 0.3, 0.4); }
    Settings   { Domain = "UI"; ShadingModel = "Unlit"; }
    Outputs    { vec3 Color; Base.EmissiveColor = Color; }

    Graph {
        vec3  Forward   = Src.rgb;   // leading channels -> the parameter's RGB pin
        vec3  Reordered = Src.bgr;   // reordered        -> a mask per channel, 2 AppendVector
        float One       = Src.a;     // ascending        -> 1 ComponentMask
        vec2  Repeated  = One.rr;    // scalar base      -> 1 AppendVector
        Color = Forward + Reordered * One + vec3(Repeated, 0.0);
    }
}

生成的节点:

VectorParameter                       -> Src (property node)
(no node)                             -> Src.rgb        [the RGB pin of Src]
ComponentMask B, ComponentMask G,
  AppendVector, AppendVector          -> Src.bgr        [r is the R pin of Src]
ComponentMask A                       -> Src.a
AppendVector                          -> One.rr
Multiply, Add, Constant(0.0),
  AppendVector, Add                   -> Base.EmissiveColor

另请参见

本页目录