DreamShaderLang
HLSL / GLSL 背景

关键字速查

DreamShaderLang 语法特殊对待的每一个词 —— 1.x 的块、section、限定符与上下文关键字,.dss 的声明、#pragma 与 /// 标签,保留字 —— 以及供移植代码时对照的 HLSL 与 GLSL 词汇表。

一张查阅用的页面。DreamShaderLang 的几张表是穷尽的:1.x 的块关键字、section 名、限定符、上下文关键字,.dss 的声明形式、 #pragma 和 /// 标签,以及保留字,就是语法认得的全部集合。HLSL 和 GLSL 两张表是给从那两门语言过来的读者做参考的。

块关键字、section 名和类型名不对标识符保留。 property、输出变量、参数或函数都可以叫 Shader、Graph、Layout;它们只在 语法期待的位置才被识别。例外是一小组保留字 since 2.0.0。数学内置和构造器的名字也不能拿来命名函数 —— 那是 DSH6206,报在声明处(1.9.x 及以前会静默遮蔽)。

.dss 的声明形式

since 2.0.0 .dss 是带声明的 HLSL:文件级只有下面这些形式。完整语法见 DreamShaderLang 2.0。

形式含义
uniform <Type> Name = <init>;材质参数。uniform bool 默认是动态标量;/// @static 让它成为静态开关
static const <Type> Name = <init>;编译期常量
<Type> Name(params) { … }文件内 helper,没有链接关键字
export <Type> Name(params) { … }产出一个资产:void (inout material) 是材质,其他是材质函数
extern <Type> Name(params);通过 /// @asset 绑定到一个已有资产的原型,没有函数体
struct Name { … };字段可以带自己的 /// 块和数组维度;没有方法,不能嵌套
#include "path" · import "path";同一回事;路径必须用双引号
#pragma material(Key = Value, …)文件级材质设置;同一个键设两次是 DSH7200
#pragma layout(Node|Comment, Key = Value, …)节点坐标与注释框,反编译器写出
#pragma region Name · #pragma endregion1.x #Region 注释框的 2.0 写法

#pragma 的名字还有 instance(.dsi)和 pipeline(.dsp)。.dss 特有的类型:material(材质属性集,入口参数 inout material m)、void,以及用户 struct。

/// 标签

声明上方的 /// 行是它的文档块:每行 @key value @key value …,键不区分大小写。

标签用在含义
@group、@sort、@descuniform参数面板里的分组、排序和说明
@slider min max标量 uniform滑条范围;放在向量或开关上是 warning DSH7233
@default /Game/…纹理 uniform默认资产
@sampler纹理 uniform采样器类型
@staticuniform bool静态开关
@nameexport 函数、@custom 函数资产名(或对象路径)、节点标题
@assetextern 原型绑定的已有资产
@library、@param导出的材质函数库分类;某个输入的说明
@layer、@layerblend导出函数产出材质图层 / 图层混合函数
@custom函数函数体原样捕获,每次调用一个 Custom 节点

1.x 顶层块关键字

区分大小写,按整词匹配 —— ShaderFunction 是它自己这个词,永远不是 Shader 加点什么。大小写写错的(shader(…))不是块: DSH2240。

关键字头部必填生成
ShaderShader(Name = "…"[, Root = "…"])NameUMaterial
ShaderFunctionShaderFunction(Name = "…"[, Root = "…"])NameUMaterialFunction
ShaderLayer since 1.3.0ShaderLayer(Name = "…"[, Root = "…"])NameUMaterialFunctionMaterialLayer
ShaderLayerBlend since 1.3.0ShaderLayerBlend(Name = "…"[, Root = "…"])NameUMaterialFunctionMaterialLayerBlend
MaterialLayer(1.3.0 起弃用)MaterialLayer(Name = "…"[, Root = "…"])Name同 ShaderLayer
MaterialLayerBlend(1.3.0 起弃用)MaterialLayerBlend(Name = "…"[, Root = "…"])Name同 ShaderLayerBlend
VirtualFunction since 1.2.0VirtualFunction(Name = "…"[, Asset = "…"])Name,外加来自 Asset = 或 Options.Asset 的资产不生成 —— 声明一个已有资产
NamespaceNamespace(Name = "…")Name不生成 —— helper 的作用域
FunctionFunction [SelfContained | Inline] [<ret>] <Name>( … ) { <HLSL> }一个名字,至少一个输出一个 HLSL helper —— 每次调用一个 Custom 节点
GraphFunction since 1.3.1GraphFunction [<ret>] <Name>( … ) { <HLSL> }一个名字,至少一个输出带节点输入的 HLSL helper

Shader 每个文件只能有一个(DSH2250),而 .dsh 头文件里根本不能有资产块(DSH2249),所以 import 加不出第二个。 其余每种块都可以重复。Function 和 GraphFunction 还可以嵌在 Namespace 里,此时它们的名字变成 <Namespace>::<Name>。

已弃用 自 1.3.0 起

请改用 ShaderLayer。

MaterialLayer 和 MaterialLayerBlend 仍然能解析、生成的资产也相同,带 warning DSH2251。之后的诊断和生成的元数据都报现代写法。

1.x Section 名

不区分大小写。块前的 = 可省 since 1.5.0,块后的 ; 也可省。section 顺序任意,可以重复:Properties、Inputs 和 Outputs 追加,Settings 按键合并,第二个 Graph 或 Layout 替换第一个并给出 warning DSH2258。块不接受的名字是 DSH2245。

名称可用于含义
PropertiesShader、ShaderFunction、ShaderLayer、ShaderLayerBlend参数、const 和 UE.* 节点声明
PropertiesVirtualFunctionInputs 的别名 —— 是有类型的参数,不是参数节点
InputsShaderFunction、ShaderLayer、ShaderLayerBlend、VirtualFunction有类型的输入参数
OutputsShaderFunction、ShaderLayer、ShaderLayerBlend、VirtualFunction有类型的输出参数
OutputsShader输出声明与绑定 —— 另一套语法
ResultsShaderFunction、ShaderLayer、ShaderLayerBlend、VirtualFunctionOutputs 的别名
SettingsShader材质设置 —— 特殊键加上反射到 UMaterial 的属性
SettingsShaderFunction、ShaderLayer、ShaderLayerBlend材质函数的设置键
SettingsVirtualFunctionOptions 的别名
OptionsVirtualFunction声明的资产及其他存储键
GraphShader、ShaderFunction、ShaderLayer、ShaderLayerBlend节点图主体
Code—到处都被拒绝(DSH2246;VirtualFunction 里 Graph 和 Code 都是 DSH2247);请用 Graph
LayoutShader、ShaderFunction、ShaderLayer、ShaderLayerBlendNode / Comment 摆放

Function 和 GraphFunction 完全没有 section —— 它们的 { … } 是裸 HLSL。

1.x 声明限定符

限定符位置效果
const since 1.2.6Properties 声明中类型之前产出常量节点而不是参数;多数参数节点 token 上被拒绝(DSH3253)
opt since 1.2.3Inputs 声明中类型之前在 Unreal 里把该函数输入标记为可选;后面跟着类型和名字时才被识别
inFunction / GraphFunction 参数类型之前输入参数;参数只有两个词时的默认值
outFunction / GraphFunction 参数类型之前输出参数;除非声明了返回类型,否则至少要有一个,且不能和返回类型并存(DSH6305、DSH6304)
SelfContainedFunction 之后读取后忽略:每个 Function 节点本来就嵌入它函数体调用的函数 since 2.0.0;不接受用在 GraphFunction 上(DSH6307)
InlineFunction 之后SelfContained 的旧拼写,带 warning DSH6306

函数参数上只接受 in 和 out 两个限定符(不区分大小写);其他的,包括 inout,是 DSH6302。

1.x 上下文关键字

只在列出的位置被识别,除非该行另有说明,否则不区分大小写。

关键字位置含义
import顶层,块之间把一个 .dsh 头文件的名字声明进本文件 since 2.0.0(1.x 把文件贴进来);小写 —— 别的大小写也能读,带 warning DSH2253
Group("…") { … } since 1.5.0Properties 内的语句位置把参数组名盖到内部每条声明上;可嵌套,用 | 拼接
Slider(min, max) since 1.5.0[ … ] 元数据块内的条目设置标量参数的 UI 范围
Path( … )纹理或资产型声明的默认值带根写法的资产引用
Base.Outputs 绑定目标的开头绑定到一个材质属性
Expression( … )Outputs 绑定目标的开头绑定到反射节点上的某个 pin;Class="…" 必填
.Pin[<index>]Expression( … ) 目标之后选择要绑定的 pin
Node( … )Layout 内的语句钉住某个变量的节点位置
Comment( … )Layout 内的语句放置一个注释框
#Region / #EndRegionGraph 体内独占一行给图的一段命名;可嵌套
#if / #elif / #else / #endif since 1.9.0独占一行,Function / GraphFunction 的 HLSL 体之外的任何位置在解析前剪掉没走的分支;只认小写
#ifdef / #ifndef since 1.9.0同上#if defined(NAME) 和 #if !defined(NAME) 的糖
#define / #undef since 1.9.0同上定义或删除一个名字,只在本文件有效
defined since 1.9.0#if / #elif 表达式里名字已定义为 1,否则 0
UE.Properties 的类型位置、Graph 的调用位置内置材质节点命名空间;在 Graph 调用里必须恰好写成 UE since 2.0.0
Substrate.Graph 的调用位置Substrate 节点命名空间,since UE 5.4
true / false默认值、Graph 表达式布尔字面量;期待标量的位置会转成 1.0 / 0.0
default since 1.2.3Graph 中的调用实参不连这个输入,让函数自己的默认值生效;只认小写 since 2.0.0

预处理器在 .dss 里同样可用,规则见词法与大小写 ▸ 预处理器。

保留字

since 2.0.0 所有文件由同一个词法器读取,它的关键字在 1.x 文件里也保留(小写):uniform static const extern export in out inout struct if else for while do return break continue discard true false import。它们都不能用来命名 property、输出、输入或 Graph 变量。别的大小写是普通的词:在 1.x 语法期待 const 和 in 的地方, Const 和 IN 照样读作它们,True 读作 true。见词法与大小写 ▸ 保留字。

保留名

名称位置规则
__returnFunction / GraphFunction 参数名任何大小写都保留;这样命名的参数是 DSH6303
return到处一个保留字:不能命名输出变量,也不能作绑定源 since 2.0.0
DS_… since 1.9.0预处理器 define 名整个 DS_ 前缀归 DreamShader:#define 或 #undef 这样的名字是 DSH1039,其他 define 层会丢掉它并给出警告

Function 体里的 return 是 HLSL,since 2.0.0 起保持原样;声明了返回类型的函数里裸写 return; 是 DSH6308。

类型 token

完整集合共 52 个 token。逐上下文的有效性见类型与值。

族Token个数
标量(1 分量)float half double int uint bool,以及各自带 1 后缀的写法(float1…)12
向量(2 / 3 / 4 分量)float2..4 half2..4 double2..4 int2..4 uint2..4 bool2..4 vec2..4 ivec2..4 uvec2..4 bvec2..430
纹理Texture2D TextureCube Texture2DArray Texture3D VolumeTexture5
不透明及其他SamplerState MaterialAttributes Substrate StaticBool StaticBoolParameter5

vec* / ivec* / uvec* / bvec* 只在 1.x 源文件里是类型;.dss 写 HLSL 拼写,并另有 material、void 和用户 struct。 图里没有矩阵值:mat2 / mat3 / mat4 和 float2x2 / float3x3 / float4x4 在 Properties 里是 DSH3252,变成节点或 pin 的位置是 DSH4361。有三个 token 已被移除:

已移除的 token替代
Scalarfloat
Colorfloat4 / vec4
Vectorfloat2 … float4 / vec2 … vec4

1.x 的 Properties 声明还可以使用显式的 *Parameter 节点 token(ScalarParameter、TextureSampleParameter2D、 ChannelMaskParameter……),收录在 Properties 类型。

标识符改写

只在 1.x Function 和 GraphFunction 声明内部、输出 HLSL 之前应用。匹配不区分大小写、按整标识符进行;字符串和注释被跳过, :: 限定名不查这张表 —— 它被拍平成 <Namespace>_<Name>。.dss 的 /// @custom 体不做这层改写。

写的改写为作用于
vec2 vec3 vec4float2 float3 float4参数与返回类型、函数体文本
ivec2 ivec3 ivec4int2 int3 int4参数与返回类型、函数体文本
uvec2 uvec3 uvec4uint2 uint3 uint4参数与返回类型、函数体文本
bvec2 bvec3 bvec4bool2 bool3 bool4参数与返回类型、函数体文本
mat2 mat3 mat4float2x2 float3x3 float4x4参数与返回类型、函数体文本
mixlerp仅函数体文本
fractfrac仅函数体文本
modfmod仅函数体文本

HLSL 关键字

参考 —— HLSL 自己的词汇,在 /// @custom 和 Function 体里有效;.dss 的图代码认其中的大部分,见 HLSL 简介。

分类关键字
类型void、bool、int、uint、half、float、double
控制流if、else、for、while、do、switch、case、default
跳转return、break、continue、discard
参数in、out、inout
修饰const、static、uniform、groupshared
纹理Texture2D、TextureCube、SamplerState、SamplerComparisonState
聚合struct

GLSL 关键字

参考 —— 除 1.x 里的 vec* / ivec* / uvec* / bvec* 类型别名(它们是一等 token)之外,这里的内容都不属于 DreamShaderLang 语法。

分类关键字
类型void、bool、int、uint、float、double、vec2、vec3、vec4、mat2、mat3、mat4
控制流if、else、for、while、do、switch、case、default
跳转return、break、continue、discard
参数in、out、inout
修饰const、uniform、layout、centroid、flat、smooth、attribute、varying
精度lowp、mediump、highp

迁移提醒

原本的习惯在 DreamShaderLang 中
vec3.dss 写 float3;1.x 里 vec3 是真正的 token,读作 float3
mix(a, b, t)、fract(x)、mod(a, b)写 lerp、frac、fmod。1.x Graph 里 GLSL 拼写仍能编译,带 warning DSH5277;.dss 里是错误 DSH4250;1.x Function 体里被改写
length(v)、distance、exp、log都是内置 —— 两种语言拼写相同
main().dss 的入口 export void M(inout material m);1.x 用带 Outputs 绑定的 Shader 块
uniform.dss 里就是 uniform,加 /// 标签;1.x 写成 Properties 声明
sampler2D + texture(s, uv).dss:Tex.Sample(uv);1.x:纹理对象用 SampleTexture2D(tex, uv),TextureSampleParameter* 用 Tex(Coordinates = uv)
HLSL Custom 节点函数体.dss 用 /// @custom 函数;1.x 用 Function,函数体需要 UE.* 值时用 GraphFunction
可视化材质节点用具体的 UE.* 内置,或 UE.Expression(Class = "…")
共享 include 文件.dsh 头文件加 #include(.dss)或 import(1.x)

接下来

本页目录