Write HLSL shaders for s&box using the .shader file format, dispatch compute shaders from C# with RenderAttributes, and reference ray-tracing programs.
Use this file to discover all available pages before exploring further.
s&box uses a custom HLSL-based shader format (.shader files compiled via the Vulkan shader compiler) that supports vertex, pixel, geometry, compute, and ray-tracing programs in a single file. This page explains the file structure, how the compiler works, how to dispatch compute shaders from C#, and how RenderAttributes bridges C# and HLSL.
When the dispatch dimensions come from a GPU buffer (populated by a previous compute pass):
// Buffer must have UsageFlags.IndirectDrawArguments and element size of 12 bytescompute.DispatchIndirect( indirectBuffer, indirectElementOffset: 0 );// With custom attributescompute.DispatchIndirectWithAttributes( attrs, indirectBuffer, indirectElementOffset: 0 );
DispatchIndirect requires the buffer to have GpuBuffer.UsageFlags.IndirectDrawArguments set and an element size of exactly 12 bytes. The element offset is an element index, not a byte offset.
The thread group size declared with [numthreads(...)] divides into the total thread count you pass to Dispatch(). If you dispatch 1024 threads with a group size of 64, the engine dispatches 16 groups.
The ShaderCompile class (in Sandbox.Engine.Shaders) is available in the editor only — it is not available at game runtime. It is used by asset pipeline tooling to compile .shader files into engine-ready .shader_c resources.
// Editor-only: compile a shader from an absolute pathvar options = new ShaderCompileOptions{ ForceRecompile = false, SingleThreaded = false, ConsoleOutput = true};ShaderCompile.Results results = await ShaderCompile.Compile( absoluteFilePath: "/path/to/my.shader", relativeFilePath: "shaders/my.shader", compileOptions: options, token: CancellationToken.None);if ( results.Success ){ Log.Info( "Shader compiled successfully" );}else{ foreach ( var prog in results.Programs ) { if ( !prog.Success ) Log.Error( string.Join( "\n", prog.Output ) ); }}
From C#, push per-draw overrides with RenderAttributes:
var attrs = new RenderAttributes();attrs.Set( "GlowStrength", pulseValue );// Draw a model with per-draw attribute overridesGraphics.DrawModel( model, transform, attrs );