pub struct Shader {
pub asset_id: AssetId,
pub vertex: StageSource,
pub fragment: StageSource,
pub vertex_instanced: Option<StageSource>,
pub locator: Option<PayloadLocator>,
}Expand description
Declares a custom shader program: the vertex and fragment stages, plus the optional GPU-instanced vertex stage.
A Shader is entirely optional. The engine ships its own main-pass
program and uses it for every draw a Shader does not claim, so a world that
wants standard lighting declares no Shader at all. Declare one only to
replace that program with your own. The shadow pass is engine-internal (no
Shader stage of its own); enable or size it with shadow_map_size in
GraphicsConfig.
The engine-internal shadow map covers a ±20 m world-space region centred at
the origin with 80 m depth. For larger scenes, increase shadow_map_size in
GraphicsConfig to maintain resolution.
A stage that resolves no source for the running backend falls back to the engine’s own program for that stage, so a Shader may cover only the platforms it has sources for.
§More than one Shader
The first declared Shader is the world’s default: everything renders with it
unless a Material names another one through its shader field.
A world may declare up to 8 Shaders in total.
Three rules come with the second Shader, all enforced at build time:
- Every fragment stage must define
fragment_main_bindless. Multi-Shader worlds render through the GPU-driven bindless path, which is the only path that can switch programs per draw. A single-Shader world has no such requirement and may define justfragment_main. This applies to.metalsources, which carry one program per entry point; an.hlslor GLSL stage compiles a singlemain, so there is no entry point to pick – what it must match instead is the bindless binding layout (see below). - Instanced, skinned, and voxel-chunk draws always use the world default. A Material naming a Shader cannot be used by an InstancedProp, a SkinnedMesh, or a VoxelWorld; give those a Material without one.
- At most 8 Shaders, the world default included.
Planar reflections are the one case with no build-time signal: a surface reflected in a mirror is drawn with the world default Shader regardless of its Material. Reflection probe cubes capture it the same way.
A non-default Shader’s stages must be written against the engine’s bindless binding layout, not the per-draw one: the material, transform, and texture indices come from the per-frame object buffer rather than per-draw constants.
A Shader referenced only by materials belonging to one Scene is owned by that scene: its pipeline is built when the scene loads (behind the loading screen, alongside that scene’s textures and meshes) and released when the scene unloads. A Shader used across scenes, or by the world default, loads at startup.
Custom shader vertex layout: the engine always supplies vertices with 5
attributes at a fixed 56-byte stride. Any custom .metal shader must declare
struct Vertex exactly as shown below: wrong attribute indices cause tangent
data to be read as vertex colour, producing red/green/blue geometry:
struct Vertex {
float3 pos [[attribute(0)]]; // offset 0
float3 normal [[attribute(1)]]; // offset 12
float3 tangent [[attribute(2)]]; // offset 24
float3 color [[attribute(3)]]; // offset 36
float2 uv [[attribute(4)]]; // offset 48
};Buffer and texture bindings that must match:
struct DirectionalLightData {
packed_float3 direction;
float intensity;
packed_float3 color;
float _pad;
};
struct PointLightData {
packed_float3 position;
float range;
packed_float3 color;
float intensity;
};
struct ShadowUniforms {
float4x4 light_vp;
};Fields§
§asset_id: AssetIdAsset identity; injected via inject_name. Not part of args.
vertex: StageSourceThe vertex stage. Required.
fragment: StageSourceThe fragment stage. Required.
vertex_instanced: Option<StageSource>The GPU-instanced vertex stage. Required only for worlds with InstancedProp components.
locator: Option<PayloadLocator>Injected at load time from BlobAssetDef::payload.
Implementations§
Source§impl Shader
impl Shader
Sourcepub fn stage(&self, kind: ShaderKind) -> Option<&StageSource>
pub fn stage(&self, kind: ShaderKind) -> Option<&StageSource>
The declared source for kind, if that stage is present.
Trait Implementations§
Source§impl Component for Shader
impl Component for Shader
Source§fn from_baked(bytes: &[u8]) -> Result<Self, CnResult>
fn from_baked(bytes: &[u8]) -> Result<Self, CnResult>
Source§fn inject_locator(&mut self, locator: PayloadLocator)
fn inject_locator(&mut self, locator: PayloadLocator)
Source§fn inject_name(&mut self, id: AssetId)
fn inject_name(&mut self, id: AssetId)
Source§impl ComponentSlot for Shader
impl ComponentSlot for Shader
Source§const DISCRIMINANT: u8
const DISCRIMINANT: u8
ComponentId.