LEARN BY MAKING

What is a Shader?

An introduction to shaders and their role in graphics rendering.

A shader is a small GPU program that changes how something is drawn. In Kraken, custom shaders are used as fragment effects; they receive the color, texture coordinates, textures, samplers, and uniform data for a draw call, then return the final pixel color.

That makes them a good fit for effects like:

  • tinting or recoloring sprites
  • screen-space distortion
  • palette swaps
  • water, heat haze, grass wind, or light pulses
  • combining a base texture with one or more mask/noise textures

Kraken currently exposes custom fragment shaders only. You do not write a custom vertex pipeline or compute shader for this feature yet, so most shader work in Kraken answers one question:

Given this pixel and the data I bound, what color should it become?

The Pieces

A fragment shader usually reads from three kinds of inputs:

  • Texture samplers: Textures paired with samplers, such as a sprite texture plus nearest or linear filtering.
  • Uniform buffers: Small pieces of CPU-side data that stay constant for a draw call or frame, such as time, color, strength, or resolution.
  • Interpolated inputs: Values Kraken’s renderer passes into the fragment shader, such as vertex color and UV coordinates.

Here is a tiny HLSL fragment shader that samples one texture and returns it:

Texture2D spriteTex : register(t0, space2);
SamplerState spriteSamp : register(s0, space2);

struct PSInput {
    float4 v_color : COLOR0;
    float2 v_uv    : TEXCOORD0;
};

struct PSOutput {
    float4 o_color : SV_Target;
};

PSOutput main(PSInput input) {
    PSOutput output;
    output.o_color = spriteTex.Sample(spriteSamp, input.v_uv) * input.v_color;
    return output;
}

The texture and sampler are binding 0. The v_color and v_uv fields are values supplied by Kraken’s default draw path. The output is a single color for the pixel being rendered.

Shader Languages

Kraken’s shader baker, kraken bake, accepts HLSL input and produces the platform shader files Kraken needs. This is the recommended path.

kraken bake shaders/simple.frag.hlsl -o assets/shaders

You can still write GLSL, but Kraken does not bake GLSL for you. If you choose GLSL, compile it yourself into the format your target platform needs, then load the resulting shader by its base path with kn.shaders.Shader.

Binding Rules Matter

Shader resource bindings must be authored in a specific order. If the shader compiles but samples the wrong texture, reads empty uniform data, or behaves differently on another backend, this is the first thing to check.

Kraken’s current custom shader API binds fragment resources only, so these are the rules you will use most often:

HLSL DXIL Fragment Shaders

  • Sampled textures use register(t0, space2), register(t1, space2), and so on.
  • Samplers use matching indices: register(s0, space2), register(s1, space2), and so on.
  • Uniform buffers use register(b0, space3), register(b1, space3), and so on.
Texture2D baseTex  : register(t0, space2);
Texture2D noiseTex : register(t1, space2);

SamplerState baseSamp  : register(s0, space2);
SamplerState noiseSamp : register(s1, space2);

cbuffer WindUniform : register(b0, space3) {
    float4 wind;
};

GLSL SPIR-V Fragment Shaders

  • Sampled textures are in resource set 2.
  • Uniform buffers are in resource set 3.
  • Within each set, bindings start at 0 and increase from there.
layout(set = 2, binding = 0) uniform sampler2D baseTex;
layout(set = 2, binding = 1) uniform sampler2D noiseTex;

layout(set = 3, binding = 0) uniform WindUniform {
    vec4 wind;
};

MSL Fragment Shaders

  • [[texture]] entries are sampled textures.
  • [[sampler]] entries use indices matching the sampled textures.
  • [[buffer]] entries list uniform buffers.

If you are using HLSL with Kraken’s baker, you normally do not write these MSL bindings by hand.

HLSL Input Semantics

For HLSL source, the fragment input should accept one vertex color and one vertex texture coordinate as such:

struct PSInput {
    float4 v_color : COLOR0;
    float2 v_uv    : TEXCOORD0;
};

Keeping this convention in your shader source makes the generated platform shaders line up consistently.

KEEP EXPLORING Using Shaders

Find your next step

Start typing to search the manual.