s&box
RustCounter-Strike 2s&boxDeadlock
Wiki
Get s&box on Steam
Browse
OverviewGetting StartedCreating GamesEngine & ToolsDocumentationCommunity GamesResources
s&boxDocumentationRenderingShadersShading Model
SOURCE 2 · C#
Build and play games with s&box.

Facepunch's game engine and creation platform — make games in C#, or jump straight into community games.

Get s&box on Steam

s&box Wiki

  • Overview
  • Getting Started
  • Creating Games
  • Engine & Tools
  • Documentation
  • Community Games
  • Resources

Tools & Community

  • Getting Started
  • Creating Games
  • Engine & Tools
  • Resources

Platforms

  • RustBattle
  • CSBattle
  • Rust Game Wiki
  • CS2 Skins Wiki
  • Deadlock Wiki

About

  • Official Site
  • Developer Wiki
  • GitHub
  • Get on Steam
NOT AFFILIATED WITH FACEPUNCH STUDIOS · © 2026 s&box Wiki (community)
Docs/Rendering
Rendering

Shading Model

Shading Models are what process how a model is lit, this is typically the final step and output of your shader.

Consumes your Material and shades the output with lighting, atmospheric, and deals with everything needed to show specific stages of rendering if Debug Views are enabled.

The traditional flow of a lit shader is Input Interpolants > Material Definition > Output Shading Model

ShadingModelStandard

The default Source 2 Lighting.

float4 MainPs(PixelInput i)  : SV_Target0
{
   Material m = Material::Init( i );
   return ShadingModelStandard::Shade( m );
}

float4 ShadingModelStandard::Shade( Material m )

  • Consumes the material set from m and does the standard lighting from it.

    Returns the final output of the shader in a float4

Custom Shading Model Example

The default Shading Model should have everything you need, but if your game has a custom art style you can try to implement your own Shading Model with ease.

When implementing your own Shading Model, the best practice is to segment it by Direct/Indirect and each of these again in Specular/Diffuse lighting.

This is an example of a simple toon shader:

class ShadingModelToon
{
    static float4 Shade( Material m )
    {
        float4 color = 0;
        
        // Direct Lighting
        for( uint i = 0; i < Light::Count( m.ScreenPosition ); i++ )
        {
            Light l = Light::From( m.WorldPosition, m.ScreenPosition, i );
            ...
            
            float3 diffuse = /* */
            float3 specular = /* */
            
            color += diffuse + specular;
        }
        
        // Indirect Lighting
        {
            float3 diffuse = 0;
            {
                diffuse = /* ambient light */
                diffuse *= min( m.AmbientOcclusion, ScreenSpaceAmbientOcclusion::Sample( m.ScreenPosition ) );
            }
            
            float3 specular = 0;
            {
                specular = /* envmap */
                specular += /* toon fresnel */
            }
            
            color += diffuse + specular;
        }
        
        if( DepthNormals::WantsDepthNormals() )
            return DepthNormals::Output( m.Normal, m.Roughness, color.a );

        if( ToolsVis::WantsToolsVis() )
        {
            // See below - build a ToolsVis from your lighting terms and let it
            // draw whichever debug view the editor has selected.
        }

        // Composite atmospherics after lighting
        color.rgb = Fog::Apply( m.WorldPosition, m.ScreenPosition.xy, color.rgb );
        
        return color;
    }
}

Supporting Debug Views

ToolsVis::WantsToolsVis() tells you the editor is asking for a debug view rather than the normal image. To support them, initialize a ToolsVis with your lighting terms and call the Handle* methods for the ones you care about:

ToolsVis vis = ToolsVis::Init( color, diffuse, specular, indirectDiffuse, indirectSpecular, transmissive );

vis.HandleAlbedo( color, m.Albedo );
vis.HandleNormalWs( color, m.Normal );
vis.HandleRoughness( color, float2( m.Roughness, m.Roughness ) );
// ...and so on for the views you want to support

return color;

ShadingModelStandard wires up every one of these in its own DoToolsVis, so shadingmodel.hlsl is the reference to copy from. Note DoToolsVis itself is private to ShadingModelStandard - you can't call it from your own shading model.

Source: Facepunch/sbox-docs (CC-BY-4.0) · updated 2026-08-03. Read it rendered on the official docs.

More in Rendering

AmbientLight
Animated Effects
Attributes and Variables
BeamEffect
Beams
Bindless API
C# Shader Nodes
Classes
← All documentation

Community wiki — not affiliated with Facepunch Studios. For the latest and most authoritative information, see the official developer wiki.