S&box Wiki

Anatomy of Shader Files

What is a shader File?

The .shader file is a container for your shader program. Its main purpose is to eliminate the need for multiple shader files for each shader stage. The .shader file is a plain text file and it can be opened in any code/text editor and the underlying shader format is HLSL. The .shader is split into multiple different sections separated by a header and curly brackets. An example of the SHADER format can be seen below:

//========================================================================================================================= // Optional //========================================================================================================================= HEADER { Description = "Template Shader for S&box"; } //========================================================================================================================= // Optional //========================================================================================================================= FEATURES { #include "common/features.hlsl" } //========================================================================================================================= COMMON { #include "common/shared.hlsl" } //========================================================================================================================= struct VertexInput { #include "common/vertexinput.hlsl" }; //========================================================================================================================= struct PixelInput { #include "common/pixelinput.hlsl" }; //========================================================================================================================= VS { #include "common/vertex.hlsl" // // Main // PixelInput MainVs( VertexInput i ) { PixelInput o = ProcessVertex( i ); // Add your vertex manipulation functions here return FinalizeVertex( o ); } } //========================================================================================================================= PS { #include "common/pixel.hlsl" // // Main // float4 MainPs( PixelInput i ) : SV_Target0 { Material m = Material::From( i ); /* m.Metalness = 1.0f; // Forces the object to be metalic */ return ShadingModelStandard::Shade( i, m ); } }

HEADER

The shader HEADER section gives information about the header and sets the compile targets. The following options can be set:

Key Value Type Example Explanation
Version Number Version = 1; Sets a version number for your shader, this is shown in the Material Editor
DevShader Boolean DevShader = true; If your shader is marked as a dev shader, you can reload your shader in the Material Editor
Description String Description = "My shaders description"; A description of your shader which is shown to the user in the material editor
DebugInfo Boolean DebugInfo = true; Ships debug information with your shader, this is only useful for developing shaders. Shipping shaders with this will drastically increase the file size
HEADER { Description = "My shaders description!"; }

FEATURES

Features allow you to add customization to your shaders in the form of using the shader preprocessor(note that this is different from the HLSL preprocessor). Features allow you to specify conditions on attributes, sampler settings, or render states. Features MUST be defined within the FEATURES section and feature names MUST start with F_!

Features have multiple different configurations and settings, you have regular checkboxes, radio buttons and rulesets to only allow one feature or the other. Features are defined as follows: Feature(F_FEATURE_NAME, RANGE_MIN..RANGE_MAX, "Feature Category");

Checkbox

Feature(F_MY_FEATURE_NAME, 0..1, "This is a category"); Feature(F_MY_FEATURE_NAME2, 0..1, "This is a category"); Feature(F_MY_FEATURE_NAME_3, 0..1, "This is a category");

MY_FEATURE_NAME is transformed into My Feature Name. All underscores are converted into spaces within the material editor. The range 0..1 indicates that this is a checkbox. These checkboxes will also share the same category.

2021-10-03_36-02-06f903ab-202e-4441-b29d-934b69d84180-v9q57xG2.png

Categories

You can create another category by providing a different category name.

Feature(F_DO_SOMETHING, 0..1, "This is another category");
2021-10-03_36-59-f61684e9-5754-437b-a0e9-28aa881a5ec0-KDNvT2rL.png

Radio buttons

Features also allow you to have radio buttons. A group of buttons that only allow one choice. This is done by specifying a range that is greater than 0..1 within the feature and providing the names of each radio button. It can be done as so:

Feature(F_RADIO_FEATURES, 0..3(0="Checkbox 1", 1="Checkbox 2", 2="Checkbox 3", 3="Checkbox 4"), "This is another category");

Feature rules

Feature rules allow you to limit the section of options. It works similarly to radio buttons however it's a bit more fine control. Feature rules are defined as follows: FeatureRule(RULE(F_FEATURE1, F_FEATURE2, ...), "A useful tooltip");

Below is a list of feature rules:

Rule Arguments Example Info
AllowN F_FEATURE_0, F_FEATURE_N FeatureRule(Allow1(F_FEATURE1, F_FEATURE2, F_FEATURE3), "You can only pick one!"); N is any number

Using features

As features are only run through the shader preprocessor, you can only use them in such things as within render states. An example of their usage can be used as below:

FEATURES { Feature(F_ENABLE_DEPTH, 0..1, "Settings!"); } PS { RenderState( DepthEnable, F_ENABLE_DEPTH ? true : false ); }

Example

FEATURES { Feature(F_MY_FEATURE_NAME, 0..1, "This is a category"); Feature(F_MY_FEATURE_NAME2, 0..1, "This is a category"); Feature(F_MY_FEATURE_NAME_3, 0..1, "This is a category"); Feature(F_DO_SOMETHING, 0..1, "This is another category"); Feature(F_RADIO_FEATURES, 0..3(0="Checkbox 1", 1="Checkbox 2", 2="Checkbox 3", 3="Checkbox 4"), "This is another category"); // Features MUST begin with F_ Feature(F_ENABLE_DEPTH, 0..1, "Settings!"); Feature(F_A_CHECKBOX_FEATURE, 0..3(0="Radio 1", 1="Radio 2", 2="Radio 3", 3="Radio 4"), "Category name"); Feature(F_ONLY_ALLOW_ONE_1, 0..1, "Feature rules"); Feature(F_ONLY_ALLOW_ONE_2, 0..1, "Feature rules"); Feature(F_ONLY_ALLOW_ONE_3, 0..1, "Feature rules"); FeatureRule(Allow1(F_ONLY_ALLOW_ONE_1, F_ONLY_ALLOW_ONE_2, F_ONLY_ALLOW_ONE_3), "Hover over hint"); }
2021-10-03_27-08-b859b709-0c90-48ed-9a8e-a8b30188ae55-D5UkXcfi.png

Common

The common section is any information that is shared between all shader stages. This can include anything from defines, includes functions, etc. An example can be seen below:

COMMON { #define SOME_GLOBAL_DEF } PS { #define LOCAL_DEF #ifdef SOME_GLOBAL_DEF // This is seen #endif #ifdef LOCAL_DEF // This is seen #endif } VS { #ifdef SOME_GLOBAL_DEF // This is seen #endif #ifdef LOCAL_DEF // This is not seen! #endif }

Shader Inputs/Outputs

As of March 2024, Hull and Domain stages have been removed and won't work. If your shader uses HS/DS programs, it's recommended to remove them from your code. HS/DS stages are still referenced on this page for archival purposes.

The shader inputs and outputs are structs that act like sections. If you noticed in the sample file, they are defined in the same area as headers are. There are multiple different inputs and outputs which you can use:

Input/Output Stage Name Alternate Name Note
Input Vertex VertexInput VS_INPUT
Input Pixel/Fragment PixelInput PS_INPUT
Input Geometry GeometryInput GS_INPUT
Input Geometry HullInput HS_INPUT Deprecated
Input Domain DomainInput DS_INPUT Deprecated
Output Vertex VertexOutput VS_OUTPUT
Output Pixel/Fragment PixelOutput PS_OUTPUT
Output Geometry GeometryOutput GS_OUTPUT
Output Geometry HullOutput HS_OUTPUT Deprecated
Output Domain DomainOutput DS_OUTPUT Deprecated

Example

struct VertexInput { float3 vPositionOs : POSITION < Semantic( PosXyz ); >; float4 vNormalOs : NORMAL < Semantic( OptionallyCompressedTangentFrame ); >; float2 vTexCoord : TEXCOORD0 < Semantic( LowPrecisionUv ); >; } // OR struct VS_INPUT { float3 vPositionOs : POSITION < Semantic( PosXyz ); >; float4 vNormalOs : NORMAL < Semantic( OptionallyCompressedTangentFrame ); >; float2 vTexCoord : TEXCOORD0 < Semantic( LowPrecisionUv ); >; }

Shader Stages

As of March 2024, Hull and Domain stages have been removed and won't work. If your shader uses HS/DS programs, it's recommended to remove them from your code. HS/DS stages are still referenced on this page for archival purposes.

There is a section for each dedicated shader stage, the valid shader stages are as follows:

Stage Name Entry Point Notes
VS Vertex Shader MainVs
PS Pixel/Fragment Shader MainPs
GS Geometry Shader MainGs
HS Hull Shader MainHs Deprecated
DS Domain Shader MainDs Deprecated
CS Compute Shader MainCs

A shader can have as many unique stages as you like. Typically you'll be using PS and VS in most shaders.

Example

VS { #include "common/vertex.hlsl" // // Main // PixelInput MainVs( VertexInput i ) { PixelInput o = ProcessVertex( i ); // Add your vertex manipulation functions here return FinalizeVertex( o ); } }