Skip to content

Basic ShaderWriter usage

Sylvain Doremus edited this page Oct 23, 2023 · 12 revisions

sdw::ShaderWriter allows to write a shader by defining functions needed to declare the following:

  • Control statements.
  • Constants declarations.
  • Specialization constants declarations.
  • Combined images declarations.
  • Sampled images declarations.
  • Storage images declarations.
  • Shader input variables declarations.
  • Shader output variables declarations.
  • Local variables declarations.
  • Structure type declarations.
  • Uniform buffer declarations.
  • Storage buffer declarations.
  • Push constant buffer declarations.

Additionally, sdw::ShaderWriter is derived in shader stage specific classes:

  • sdw::VertexWriter
  • sdw::TessellationControlWriter
  • sdw::TessellationEvaluationWriter
  • sdw::GeometryWriter
  • sdw::FragmentWriter
  • sdw::ComputeWriter
  • sdw::TaskShader
  • sdw::MeshShader
  • sdw::CallableShader
  • sdw::RayAnyHitShader
  • sdw::RayClosestHitShader
  • sdw::RayGenerationShader
  • sdw::RayMissShader

Each one of them exposes the access to its built-in inputs and outputs (all listed in their respective header file).

sdw:: types, in their constructor, need an sdw::ShaderWriter, an expression (ast::Expr) and an enabled status.
You will never use them directly, since the sdw::ShaderWriter base class exposes all necessary functions to declare all types of variables.

When you want to declare a local variable with a type, say for the following glsl : vec3 a;, you will use:

auto a = writer.declLocale< sdw::Vec3 >( "a" );

If you want to set the value of a with something, like in the following glsl : a = vec3( 0.0, 1.0, 0.0 );, you will use the matching composite ctor helper, this way:

a = vec3( 0.0_f, 1.0_f, 0.0_f );

Note the use of the custom literal suffix _f which builds an sdw::Float from the given literal.
You have literal suffixes for bool int, uint, and double, respectively _b, _i, _u and _d.

You can declare a local variable with an initialisation value, which allows you to not specify the template parameter :

auto a = writer.declLocale( "a", vec3( 0.0_f, 1.0_f, 0.0_f ) );

And then a will be deduced as an sdw::Vec3.

Example:

sdw::FragmentWriter writer;

// Shader inputs
auto mapHdr = writer.declCombinedImg< FImg2DRgba32 >( "mapHdr"
    , 0u    //binding
    , 0u ); // set
auto uv = writer.declInput< Vec2 >( "uv"
    , 0u ); // location
auto hdrConfig = writer.declUniformBuffer<>( "HdrConfig"
    , 1u    // binding
    , 0u ); // set
auto uboExposure = hdrConfig.declMember< Float >( "uboExposure" );
auto uboGamma = hdrConfig.declMember< Float >( "uboGamma" );
hdrConfig.end();

// Shader outputs
auto fragOutput = writer.declOutput< Vec4 >( "fragOutput"
    , 0 ); // location

// Helper functions
auto applyGamma = writer.implementFunction< Vec3 >( "applyGamma"
    , [&]( Float const & gamma, Vec3 const & hdr )
    {
        writer.returnStmt( pow( max( hdr, vec3( 0.0_f ) ), vec3( 1.0_f / gamma ) ) );
    }
    , InFloat{ writer, "gamma" }
    , InVec3{ writer, "hdr" } );

// Main
writer.implementMainT< VoidT, VoidT >( [&]( FragmentIn in
    , FragmentOut out )
    {
        auto hdrColor = writer.declLocale( "hdrColor"
            , mapHdr.sample( uv ).rgb() );
        hdrColor *= vec3( uboExposure );
        fragOutput = vec4( applyGamma( uboGamma, hdrColor ), 1.0_f );
    } );
Clone this wiki locally