SDSL Shaders for vvvv gamma / Stride
What Is SDSL
SDSL (Stride Shading Language) is Stride's shader language — a superset of HLSL with four key additions: shader classes with inheritance, multiple inheritance (mixins), the streams system for automatic inter-stage data flow, and override for clean method replacement. Shaders are defined in .sdsl files.
Streams System
Streams replace manual VSINPUT/VSOUTPUT structs. Declare once, access everywhere:
CODEBLOCK0
Key built-in streams:
- -
streams.ShadingPosition (SVPosition) — clip-space position - INLINECODE5 (SVTarget0) — pixel shader output
- INLINECODE6 (float4) — object-space position
- INLINECODE7 (TEXCOORD0) — texture coordinates
- INLINECODE8 — world-space normal
Base Shader Hierarchy
Stride Core (available in both Stride and vvvv)
| Shader | Provides |
|---|
| INLINECODE9 | VSMain/PSMain entry points |
| INLINECODE10 |
Texture0-9, Sampler, PointSampler, LinearSampler, TexCoord |
|
Transformation | World, View, Projection, WorldViewProjection matrices |
|
PositionStream4 | Position, PositionWS, DepthVS |
|
NormalStream | meshNormal, normalWS, tangentToWorld |
|
ComputeShaderBase | CSMain entry, Compute() hook, thread groups |
|
ComputeColor | Interface returning float4 via Compute() |
|
ComputeVoid | Interface returning void via Compute() |
|
Global | Time, TimeStep (cbuffer PerFrame) |
vvvv-Only (NOT available in plain Stride)
| Shader | Inherits | Use For |
|---|
| INLINECODE18 | ShaderBase, PositionStream4, NormalStream, Transformation | DrawFX base |
| INLINECODE19 |
TextureFX | Pixel-processing texture effects |
|
MixerBase | TextureFX | Blending textures |
|
TextureFX | ImageEffectShader, Camera, ShaderUtils | Texture effect base |
Important: VS_PS_Base already includes Transformation, NormalStream, and PositionStream4. Do NOT re-inherit them.
File Naming → Auto Node Generation
vvvv automatically creates nodes from shaders based on filename suffix:
| Suffix | Node Type | Description |
|---|
| INLINECODE23 | TextureFX | Image processing effects |
| INLINECODE24 |
DrawFX | Drawing/rendering shaders |
|
_ComputeFX.sdsl | ComputeFX | Compute shaders |
|
_ShaderFX.sdsl | ShaderFX | General shader effects |
Example: MyBlur_TextureFX.sdsl automatically creates a "MyBlur" TextureFX node.
Basic TextureFX Structure
CODEBLOCK1
Note the semicolon after the closing brace — this is required.
Syntax Rules
For critical SDSL syntax rules (static const scope, semicolons, override, variable initialization, common mistakes, branch divergence), see syntax-rules.md.
Keywords
| Keyword | Purpose |
|---|
| INLINECODE30 | Defines a shader class |
| INLINECODE31 |
Required when overriding parent methods |
|
base | Access parent implementation |
|
stage | Ensures member defined once across compositions |
|
stream | Member accessible at every shader stage |
|
static | Static methods callable without inheritance |
|
compose | Declare a composition slot for shader mixins |
|
clone | Force separate instance of a composed shader |
|
abstract | Method without body (child must implement) |
Inheritance & Mixins
CODEBLOCK2
Enum Binding — C# Enum in Shaders
In the shader (.sdsl):
CODEBLOCK3
In C# (.cs):
CODEBLOCK4
Requirements:
- - The enum DLL must be pre-compiled (not from dynamic csproj)
- Assembly name is the project name
- vvvv must be restarted after enum DLL changes
GPU Best Practices
Protect Against Math Errors
CODEBLOCK5
Texture Sampling
CODEBLOCK6
ShaderFX / ComputeColor Pattern
Composable shader nodes using compose keyword:
CODEBLOCK7
In vvvv patching, connect a ShaderFX node to a TextureFX's compose input to chain processing.
Mixin Composition — Virtual Method Dispatch
Base shader with a virtual method, overridden by dynamically composed mixins:
CODEBLOCK8
Template / Generic Shaders
CODEBLOCK9
Supported template parameter types: float, int, float2, float3, float4, Texture2D, SamplerState.
Composition Arrays
Multiple composed shaders of the same type:
CODEBLOCK10
Shared Struct Types Across Shaders
Define once, use in emit/simulate/draw pipeline:
CODEBLOCK11
For detailed SDSL syntax rules, see syntax-rules.md.
SDSL Shaders for vvvv gamma / Stride
什么是SDSL
SDSL(Stride着色语言)是Stride的着色器语言——它是HLSL的超集,增加了四个关键特性:支持继承的shader类、多重继承(混入)、用于自动阶段间数据流的streams系统,以及用于干净方法替换的override。着色器定义在.sdsl文件中。
Streams系统
Streams取代了手动定义的VSINPUT/VSOUTPUT结构体。只需声明一次,即可随处访问:
hlsl
stream float4 MyData : TEXCOORD5; // 声明自定义流变量
// 在顶点着色器中:
streams.MyData = float4(1, 0, 0, 1); // 写入
// 在像素着色器中:
float4 d = streams.MyData; // 读取(自动插值)
关键内置流:
- - streams.ShadingPosition(SVPosition)——裁剪空间位置
- streams.ColorTarget(SVTarget0)——像素着色器输出
- streams.Position(float4)——对象空间位置
- streams.TexCoord(TEXCOORD0)——纹理坐标
- streams.normalWS——世界空间法线
基础着色器层级
Stride核心(Stride和vvvv中均可用)
| 着色器 | 提供内容 |
|---|
| ShaderBase | VSMain/PSMain入口点 |
| Texturing |
Texture0-9、Sampler、PointSampler、LinearSampler、TexCoord |
| Transformation | World、View、Projection、WorldViewProjection矩阵 |
| PositionStream4 | Position、PositionWS、DepthVS |
| NormalStream | meshNormal、normalWS、tangentToWorld |
| ComputeShaderBase | CSMain入口、Compute()钩子、线程组 |
| ComputeColor | 通过Compute()返回float4的接口 |
| ComputeVoid | 通过Compute()返回void的接口 |
| Global | Time、TimeStep(cbuffer PerFrame) |
仅vvvv可用(纯Stride中不可用)
| 着色器 | 继承自 | 用途 |
|---|
| VSPSBase | ShaderBase、PositionStream4、NormalStream、Transformation | DrawFX基础 |
| FilterBase |
TextureFX | 像素处理纹理效果 |
| MixerBase | TextureFX | 混合纹理 |
| TextureFX | ImageEffectShader、Camera、ShaderUtils | 纹理效果基础 |
重要:VSPSBase已包含Transformation、NormalStream和PositionStream4。请勿重复继承它们。
文件命名 → 自动节点生成
vvvv根据文件名后缀自动从着色器创建节点:
| 后缀 | 节点类型 | 描述 |
|---|
| TextureFX.sdsl | TextureFX | 图像处理效果 |
| DrawFX.sdsl |
DrawFX | 绘制/渲染着色器 |
| _ComputeFX.sdsl | ComputeFX | 计算着色器 |
| _ShaderFX.sdsl | ShaderFX | 通用着色器效果 |
示例:MyBlur_TextureFX.sdsl会自动创建一个MyBlur TextureFX节点。
基础TextureFX结构
hlsl
shader MyEffect_TextureFX : FilterBase
{
float Intensity = 1.0;
float4 Filter(float4 tex0col)
{
return tex0col * Intensity;
}
};
注意右大括号后的分号——这是必需的。
语法规则
关于关键的SDSL语法规则(static const作用域、分号、override、变量初始化、常见错误、分支发散),请参见syntax-rules.md。
关键字
| 关键字 | 用途 |
|---|
| shader | 定义着色器类 |
| override |
重写父类方法时必须使用 |
| base | 访问父类实现 |
| stage | 确保成员在组合中只定义一次 |
| stream | 可在每个着色器阶段访问的成员 |
| streams | 访问当前阶段的流数据 |
| static | 无需继承即可调用的静态方法 |
| compose | 声明着色器混入的组合槽 |
| clone | 强制创建组合着色器的独立实例 |
| abstract | 无方法体的方法(子类必须实现) |
继承与混入
hlsl
// 单继承
shader Child : Parent
{
override float4 Filter(float4 tex0col)
{
return base.Filter(tex0col) * 0.5;
}
};
// 多重继承(混入)
shader MyShader : FilterBase, ColorUtils, MathUtils
{
float4 Filter(float4 tex0col)
{
float3 linear = ColorUtils.GammaToLinear(tex0col.rgb);
return float4(linear, tex0col.a);
}
};
// 静态函数调用(无需继承)
float3 result = ColorUtils.LinearToGamma(col.rgb);
枚举绑定 — 着色器中的C#枚举
在着色器(.sdsl)中:
hlsl
[EnumType(MyNamespace.BlendMode, MyAssembly)]
int Mode = 0;
在C#(.cs)中:
csharp
namespace MyNamespace;
public enum BlendMode
{
Normal = 0,
Add = 1,
Multiply = 2,
Screen = 3
}
要求:
- - 枚举DLL必须预编译(不能来自动态csproj)
- 程序集名称即项目名称
- 枚举DLL更改后必须重启vvvv
GPU最佳实践
防止数学错误
hlsl
float3 safeLog = log2(max(x, 1e-10)); // 避免log2(0)
float3 safe = x / max(y, 0.0001); // 避免除以零
float3 safePow = pow(max(x, 0.0), gamma); // 避免pow(负数)
纹理采样
hlsl
// 在TextureFX中,tex0col已从Texture0采样
float4 Filter(float4 tex0col)
{
// 采样额外纹理:
float4 tex1 = Texture1.Sample(Texturex1Sampler, streams.TexCoord);
return lerp(tex0col, tex1, 0.5);
}
ShaderFX / ComputeColor模式
使用compose关键字的可组合着色器节点:
hlsl
shader MyTonemap_ShaderFX : ComputeColor, TonemapOperators
{
compose ComputeColor ColorIn;
[EnumType(MyNamespace.TonemapOp, MyAssembly)]
int Operator = 1;
float Exposure = 0.0;
override float4 Compute()
{
float4 color = ColorIn.Compute();
color.rgb *= exp2(Exposure);
color.rgb = ApplyTonemap(color.rgb, Operator);
return color;
}
};
在vvvv连线中,将ShaderFX节点连接到TextureFX的compose输入以链式处理。
混入组合 — 虚方法分发
带有虚方法的基础着色器,由动态组合的混入重写:
hlsl
// 基础着色器声明虚方法
shader ColorProcessorBase
{
float4 ProcessColor(float4 inPixel) { return inPixel; }
};
// 宿主着色器使用组合
shader ColorTransform_TextureFX : TextureFX
{
stage compose ColorProcessorBase Processor;
stage override float4 Shading()
{
float4 col = Texture0.SampleLevel(PointSampler, streams.TexCoord, 0);
return Processor.ProcessColor(col);
}
};
模板/泛型着色器
hlsl
// 带类型参数的声明
shader ComputeColorWave : ComputeColor, Texturing
{
override float4 Compute()
{
return float4(sin(streams.TexCoord.x * Frequency), 0, 0, 1);
}
};
// 通过继承实例化
shader MyEffect : ComputeColorWave<2.0f> { };
支持的模板参数类型:float、int、float2、float3、float4、Texture2D、SamplerState。
组合数组
多个相同类型的组合着色器:
hlsl
compose ComputeColor lights[];
override float4 Compute()
{
float4 total = 0;
foreach (var light in lights)
total += light.Compute();
return total;
}
跨着色器共享结构体类型
定义一次,在发射/模拟/绘制管线中使用:
hlsl