API Design

/* A material pass maps directly to one PVR2 polygon header configuration. */
typedef struct {
    uint32_t    list_type;      /* PVR_LIST_OP_POLY, PVR_LIST_TR_POLY, PVR_LIST_PT_POLY */

    /* Texturing */
    sh_texture_t *texture;       /* NULL = untextured */
    uint32_t    tex_filter;      /* PVR_FILTER_NONE, PVR_FILTER_BILINEAR, PVR_FILTER_TRILINEAR */
    uint32_t    tex_env;         /* PVR_TXRENV_REPLACE, PVR_TXRENV_MODULATE, etc. */
    uint32_t    uv_clamp;        /* PVR_UVCLAMP_NONE, PVR_UVCLAMP_U, PVR_UVCLAMP_V, PVR_UVCLAMP_UV */

    /* Blending */
    uint32_t    blend_src;       /* PVR_BLEND_ONE, PVR_BLEND_SRCALPHA, etc. */
    uint32_t    blend_dst;       /* PVR_BLEND_ZERO, PVR_BLEND_INVSRCALPHA, etc. */

    /* Depth */
    uint32_t    depth_compare;   /* PVR_DEPTHCMP_GEQUAL, PVR_DEPTHCMP_GREATER, etc. */
    int         depth_write;     /* 1 = write, 0 = no write */

    /* Culling */
    uint32_t    cull_mode;       /* PVR_CULLING_NONE, PVR_CULLING_CW, PVR_CULLING_CCW */

    /* Color */
    uint32_t    base_color;      /* Default vertex base color (ARGB) */
    uint32_t    offset_color;    /* For bump mapping: K1/K2/K3/Q packed into oargb */

    /* Shading */
    uint32_t    shade_mode;      /* PVR_SHADE_FLAT or PVR_SHADE_GOURAUD */

    /* Fog */
    uint32_t    fog_mode;        /* PVR_FOG_TABLE, PVR_FOG_VERTEX, PVR_FOG_DISABLE */

} sh_material_pass_t;

/* A material is 1-4 passes over the same geometry. */
typedef struct {
    int                 pass_count;     /* 1-4 */
    sh_material_pass_t  passes[4];      /* Max 4 passes (base + lightmap + bump + env) */
    char                name[32];       /* Debug name */
} sh_material_t;


/* --- Predefined Materials (common patterns) --- */

/* Opaque textured (one pass, PVR_LIST_OP_POLY). */
void sh_material_opaque(sh_material_t *mat, sh_texture_t *tex);

/* Transparent textured (one pass, PVR_LIST_TR_POLY, src alpha blend). */
void sh_material_transparent(sh_material_t *mat, sh_texture_t *tex);

/* Punch-through (one pass, PVR_LIST_PT_POLY, alpha test). */
void sh_material_punchthrough(sh_material_t *mat, sh_texture_t *tex);

/* Lightmapped (two passes: opaque base + translucent multiply lightmap).
   From SPECTRE Q-003: depth compare GEQUAL on pass 2, no depth bias needed
   on PVR2 if geometry is identical. */
void sh_material_lightmapped(sh_material_t *mat, sh_texture_t *diffuse, sh_texture_t *lightmap);

/* Bump mapped (from SPECTRE Q-004/Q-005: offset color K1/K2/K3/Q,
   FLAT shading required, bump texture is S/T angle pairs 16-bit twiddled). */
void sh_material_bumpmapped(sh_material_t *mat, sh_texture_t *diffuse, sh_texture_t *bumpmap);

/* Environment mapped (second pass with env texture, additive blend). */
void sh_material_envmapped(sh_material_t *mat, sh_texture_t *diffuse, sh_texture_t *envmap);


/* --- Submission --- */

/* Compile a material pass into a PVR polygon header. Call once, reuse. */
void sh_material_compile(const sh_material_pass_t *pass, pvr_poly_hdr_t *hdr);

/* Compile all passes. headers must have room for mat->pass_count entries. */
void sh_material_compile_all(const sh_material_t *mat, pvr_poly_hdr_t *headers);