SafiMaterial

#include <safi/render/material.h>

The engine ships a single material type: unlit textured. It owns a SDL_GPUGraphicsPipeline, a SDL_GPUSampler, and (optionally) a base-color SDL_GPUTexture.

Multi-material models

For glTF files with multiple materials, use SafiModel instead of managing SafiMaterial instances directly. SafiModel handles material deduplication, per-primitive texture binding, and fallback textures automatically.

WIP — Material system

Only the unlit textured material exists. The following are not yet implemented:

  • PBR / lit materials — no metallic-roughness or normal-map pipeline
  • Alpha modes — no opaque/mask/blend handling (enable_blend = false)
  • Material parameters — no generalized uniform/parameter block; only base-color texture
  • Double-sided flag — culling is globally disabled rather than per-material
  • Texture abstraction — textures are raw SDL_GPUTexture* inside the material, not standalone assets

See Lighting and Asset System.

Types

typedef struct SafiMaterial {
    SDL_GPUGraphicsPipeline *pipeline;
    SDL_GPUTexture          *base_color;
    SDL_GPUSampler          *sampler;
} SafiMaterial;

Functions

safi_material_create_unlit

bool safi_material_create_unlit(SafiRenderer *r,
                                SafiMaterial *out,
                                const char   *shader_dir);

Loads the compiled unlit shader artifacts from shader_dir via safi_shader_load (both vs_main and fs_main stages) and builds a graphics pipeline that:

  • reads SafiVertex from vertex buffer slot 0
  • draws triangle lists with back-face culling and counter-clockwise front faces
  • writes depth using LESS comparison
  • blends one color attachment in swapchain format

Also creates a trilinear REPEAT sampler.

safi_material_set_base_color_rgba8

bool safi_material_set_base_color_rgba8(SafiRenderer  *r,
                                        SafiMaterial  *m,
                                        const uint8_t *pixels,
                                        uint32_t width, uint32_t height);

Uploads an RGBA8 texture and binds it as the base color. Replaces any previously bound texture. safi_gltf_load and safi_model_load call this automatically when the glTF has a base-color texture.

safi_material_destroy

void safi_material_destroy(SafiRenderer *r, SafiMaterial *m);

Shader inputs

The default HLSL uses these bindings — if you write your own shader, match them or override the pipeline:

BindingPurpose
cbuffer b0, space1 (vertex stage)float4x4 mvp uniform, pushed via SDL_PushGPUVertexUniformData
Texture2D t0, space2 (fragment)base color texture
SamplerState s0, space2sampler

Example

SafiMaterial mat;
safi_material_create_unlit(&app.renderer, &mat, SAFI_DEMO_SHADER_DIR);

uint8_t white[] = {255, 255, 255, 255};
safi_material_set_base_color_rgba8(&app.renderer, &mat, white, 1, 1);

See also