Help home · Beginner · Intermediate · Advanced authoring · Command reference · Samples
This guide describes how to author shader assets and HLSL for Blitz3D. It assumes you already know how to load, parameterise, attach, copy, and deploy a shader. See the intermediate guide if those workflows are new.
The recommended progression is surface mode, then post mode, and finally raw mode only when the generated surface pipeline cannot express the effect.
For format-3/layout-4 light-cookies 1 opt-in and per-light surface/raw/fog
sampling, see Light cookies. Old custom shaders retain
their rendering until explicitly opted in and recompiled.
A source-backed asset consists of a .b3shader descriptor and an
HLSL source file. This minimal material declares two public parameters:
blitz3d_shader 1 layout 3 mode surface name "Orange material" source "orange.hlsl" vertex_entry "VSMain" pixel_entry "PSMain" shadow_entry "ShadowVSMain" shadows classic color "Tint" 255 130 30 255 float "Shine" 0.35
The first line is asset format 1. layout 3 selects the immutable
legacy binding layout. Format 2 and layout 4 add pass graphs and named resources
without changing layout-3 bytecode. mode is surface,
post, or raw. Paths are relative to the descriptor.
A precompiled descriptor uses vertex, pixel, and,
when needed, shadow CSO paths in place of source and
entry-point directives. Normally b3dshaderc produces that compiled
form; do not maintain it by hand.
Value declarations are assigned constant slots in declaration order. Layout 3 has sixteen value slots and eight texture stages. Layout 4 keeps those bindings and adds a sixteen-entry named texture/sampler table for material and post inputs.
| Descriptor | Blitz setter | HLSL access |
|---|---|---|
float "Roughness" .5 | ShaderFloat shader,"Roughness",.8 | B3DUserFloat(0) |
int "Mode" 0 | ShaderInt shader,"Mode",1 | B3DUserInt(1) |
vector "Wind" 1 0 0 0 | ShaderVector shader,"Wind",1,0,.2,0 | B3DUserVector(2) |
color "Tint" 255 255 255 255 | ShaderColor shader,"Tint",80,160,255 | B3DUserVector(3), converted to 0..1 |
texture "NormalMap" 1 | ShaderTexture shader,"NormalMap",map | texture1 and sampler1 |
A float or integer consumes a complete slot, just like a vector or colour. Do not infer slots from parameter names: count only non-texture declarations from zero. Names form the BlitzBasic interface; slots form the HLSL interface.
Surface mode lets the engine generate transforms, GPU skinning, instancing, lighting, fog, vertex-colour handling, shadow receiving, and the standard vertex and pixel entry points. Your HLSL supplies one callback:
#include "blitz3d_surface.hlsli"
B3DSurface B3DShadeSurface(B3DSurfaceInput input)
{
B3DSurface surface = B3DDefaultSurface();
surface.color = B3DUserVector(0).rgb;
surface.alpha = B3DUserVector(0).a;
surface.normal = input.worldNormal;
surface.shininess = saturate(B3DUserFloat(1));
return surface;
}
Start with B3DDefaultSurface() so brush colour, alpha, and
shininess keep their traditional meaning, then replace only the fields your
effect owns.
B3DSurface field | Meaning |
|---|---|
color, alpha | Linear base colour and opacity. |
normal | World-space shading normal; zero uses the interpolated mesh normal. |
shininess | Classic specular amount and exponent control. |
emission | Unlit linear RGB added to the result. |
metallic, roughness, occlusion | PBR material values used when pbr is non-zero. |
alphaCutoff | Threshold used by masked drawing. |
indirect | Additional indirect linear RGB for PBR lighting. |
pbr | Non-zero selects the PBR lighting branch. |
B3DSurfaceInput supplies uv0, uv1,
vertexColor, worldPosition, worldNormal,
worldTangent, and viewPosition. Use
B3DSurfaceTextureUV(input,stage) when sampling so Blitz texture
coordinate selection and transforms are respected:
float4 texel = texture0.Sample(
sampler0, B3DSurfaceTextureUV(input,0));
surface.color *= texel.rgb;
surface.alpha *= texel.a;
For displacement, include the base layout first, write a function accepting
VertexInput, and define B3D_DISPLACE_POSITION before
including the surface wrapper:
#include "blitz3d_shader.hlsli"
float3 WavePosition(VertexInput input)
{
float wave = sin(input.position.x * 3.0f + B3DUserFloat(0));
return input.position + float3(0.0f,wave * B3DUserFloat(1),0.0f);
}
#define B3D_DISPLACE_POSITION(input) WavePosition(input)
#include "blitz3d_surface.hlsli"
The generated visible and shadow entry points then use the same object-space position. The Vertex Waves sample contains the complete callback and descriptor.
| Policy | Use it when... |
|---|---|
shadows classic | The shader does not move vertices and the standard caster shape is correct. |
shadows custom | Displacement or custom geometry must be repeated in the shadow pass. |
shadows disabled | The effect should not cast shadows, as with transparent effects and all post shaders. |
A source-backed surface shader normally uses the wrapper's
ShadowVSMain. Keep the visible and shadow displacement logic shared
to prevent shadows from separating from geometry.
Post mode includes blitz3d_post.hlsli and implements one
function:
#include "blitz3d_post.hlsli"
float4 B3DPostProcess(B3DPostInput input)
{
float grey = dot(input.sceneColor.rgb,
float3(.299f,.587f,.114f));
float amount = saturate(B3DUserFloat(0));
return float4(lerp(input.sceneColor.rgb,grey.xxx,amount),
input.sceneColor.a);
}
B3DPostInput contains sceneColor,
sceneDepth, uv, screenSize, elapsed
time, deltaTime, frameNumber,
cameraPosition, near and far planes, and the camera viewport. Scene
colour is texture stage 0 and depth is stage 1 if direct sampling is needed.
The wrapper supplies the full-screen vertex and pixel entries, confines output
to the viewport, and preserves the input image outside it. Declare
shadows disabled for post assets.
Raw mode uses your VSMain and PSMain directly.
Include blitz3d_shader.hlsli for the exact engine structures,
resources, flags, and helpers. Raw mode is appropriate for a rendering model
which cannot fit B3DSurface; it also means taking responsibility for
transforms, lighting, fog, colour, texture sampling, and output yourself.
VertexInput supplies position, normal, colour, two UV sets,
tangent, instance ID, and vertex ID. Matrices are row-major and positions use
Blitz3D's row-vector convention:
float4 world = mul(float4(input.position,1.0f),worldMatrix); float4 view = mul(world,viewMatrix); output.position = mul(view,projectionMatrix);
B3DTransformPosition is the convenient object-to-clip helper.
Raw shaders currently take the conservative one-instance draw path because
their vertex transforms are entirely user-defined. Surface shaders use the
instance-aware generated wrapper automatically.
| Register | Contents |
|---|---|
b0 | Pixel and draw flags plus classic texture-stage state. |
b1 | World, view, projection, material, fog, draw and instance data, texture transforms, eight lights, and six shadow views. |
b2 | Sixteen uint4 user slots, read with B3DUserFloat, B3DUserInt, and B3DUserVector. |
t0..t7 / s0..s7 | Classic and named textures with matching samplers. |
t8 / s8 | Engine shadow-map array and comparison sampler. |
t9 | Instance world-matrix buffer. |
t10..t12 | Skin vertices, bone palette, and per-instance palette ranges. |
Layout 4 retains the legacy table and adds frame/pass scene inputs, named
textures at t16..t31 / s16..s31, auxiliary MRT output contracts,
previous transforms/bone palettes, and inverse/jitter matrices. Include
blitz3d_surface_v4.hlsli or blitz3d_post_v4.hlsli through
the normal wrapper rather than copying structures. The runtime selects separate
root signatures for layouts 3 and 4; deployed layout-3 assets remain supported.
blitz3d_shader 2 layout 4 mode post stage scene-linear requires scene-color scene-depth scene-normals blue-noise target "ao" scale 0.5 format r8-unorm pass "evaluate" pixel "ao_ps.cso" input "scene-depth" output "ao" clear pass "composite" pixel "composite_ps.cso" input "scene-color" input "ao" output "scene-output" clear
Targets and passes are ordered and acyclic. A pass can read engine inputs,
custom texture:Name bindings, or earlier targets. Supported formats
are bounded colour/depth-friendly RT formats; scale must be positive and no
larger than the documented parser limit. The compiler rejects duplicate names,
forward references, cycles, read/write aliasing, compute passes, incompatible
stages/requirements, excessive parameters/textures/targets/passes, and layout
reflection mismatches before atomically replacing the prior package.
Post scene inputs include colour, resolved depth, normal/roughness, velocity, object mask, deterministic blue noise, history, opaque colour where appropriate, and up to sixteen named textures. Reconstruction helpers use the unjittered inverse projection/view matrices and explicit render/output sizes. Surface manifests may request opaque colour or read-only scene depth and may override blend, depth-write, cull, and shadow policy; removing the shader restores stored entity/brush state.
The IDE compiles literal source-backed shader references during Check and Run. For a direct build, use:
b3dshaderc fx\orange.b3shader b3dshaderc fx\orange.b3shader --force b3dshaderc fx\orange.b3shader --package-dir package\fx
The compiler invokes DirectX Shader Compiler for Shader Model 6, writes a compiled descriptor and CSO stages, and can copy the runtime package to a target directory. It searches the source directory and the bundled Blitz3D include directory for includes.
Do not edit generated .compiled descriptors or CSO files. Keep
source descriptors, HLSL, and project-specific includes under source control;
regenerate the compiled results. Runtime packages need the compiled descriptor,
its referenced bytecode, textures, and other runtime dependencies while
preserving relative paths.
B3DDefaultSurface() and override only the fields the effect owns.B3DSurfaceTextureUV when surface sampling should honour Blitz texture state.The shader sample gallery
contains editable surface tint, displacement, raw rim-light, and post-effect
sources. The builtin_sources folder beside those samples contains
the reviewed source versions of packaged built-ins; loading a
builtin: alias still uses packaged bytecode.
Shader asset formats 1/2 · binding layouts 3/4 · Shader Model 6 · Extended mode