Skip to main content

forge-pbr-textures

Add PBR texture loading with separate roughness/metallic support to an SDL GPU project using forge_scene.h

Aller à l'installation

Informations de source

Dépôt
Nebulavenus/forge-gpu
Dernière activité de la source
29 mars 2026 à 08:51
Langue détectée de SKILL.md
anglais
Étoiles
38
Forks
7

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
forge-pbr-textures
description
Add PBR texture loading with separate roughness/metallic support to an SDL GPU project using forge_scene.h
Load PBR material texture sets (albedo, normal, roughness, metallic, AO, emissive) from the asset pipeline and render them with a Cook-Torrance BRDF shader. Supports both packed metallic-roughness (glTF convention) and separate single-channel textures (ambientCG convention). ## When to use - Loading PBR materials from `.fmat` sidecar files - Rendering textured PBR materials on scene models - Supporting both packed and separate metallic-roughness workflows - Adding multiple material support to a scene ## Material loading pattern ```c /* Parse .fmat sidecar */ ForgePipelineMaterialSet mat_set; if (!forge_pipeline_load_materials("assets/materials/Rock026/Rock026.fmat", &mat_set) || mat_set.material_count == 0) { SDL_Log("Failed to load Rock026 material"); return false; } const ForgePipelineMaterial *mat = &mat_set.materials[0]; /* Load textures from processed assets. * vram tracks GPU memory usage — must be non-NULL. */ ForgeSceneVramStats vram = {0}; ForgeSceneModelTextures tex = {0}; /* Base color — sRGB (authored color) */ tex.base_color = forge_scene_load_pipeline_texture( scene, &vram, "assets/materials/Rock026/Rock026_Color.png", true, false); /* Normal map — linear, is_normal_map=true for BC5 */ tex.normal = forge_scene_load_pipeline_texture( scene, &vram, "assets/materials/Rock026/Rock026_NormalGL.png", false, true); /* Separate roughness — linear */ tex.roughness = forge_scene_load_pipeline_texture( scene, &vram, "assets/materials/Rock026/Rock026_Roughness.png", false, false); /* AO — linear, R channel */ tex.occlusion = forge_scene_load_pipeline_texture( scene, &vram, "assets/materials/Rock026/Rock026_AmbientOcclusion.png", false, false); ``` ## 8-sampler PBR pipeline The shader uses 8 texture slots to support both packed and separate workflows: | Slot | Texture | Color space | Fallback | |------|---------|-------------|----------| | 0 | Base color | sRGB | White | | 1 | Normal map | Linear | Flat (+Z) | | 2 | Packed metallic-roughness | Linear | White | | 3 | Occlusion (AO) | Linear | White | | 4 | Emissive | sRGB | Black | | 5 | Shadow map | Depth | Scene shadow | | 6 | Separate roughness | Linear | White | | 7 | Separate metallic | Linear | White | ## Separate MR flag The `shininess` field in `ForgeSceneModelFragUniforms` (offset 80, unused by PBR) is repurposed as `use_separate_mr`: ```c ForgeSceneModelFragUniforms fu; forge_scene__fill_model_frag_uniforms(scene, mat, &fu); fu.shininess = (tex.roughness || tex.metallic) ? 1.0f : 0.0f; ``` In the shader: ```hlsl if (use_separate_mr > 0.5) { roughness = roughness_tex.Sample(roughness_smp, input.uv).r * roughness_factor; metallic = metallic_tex.Sample(metallic_smp, input.uv).r * metallic_factor; } else { float2 mr = mr_tex.Sample(mr_smp, input.uv).bg; metallic = mr.x * metallic_factor; roughness = mr.y * roughness_factor; } ``` ## sRGB vs linear | Data type | Color space | Why | |-----------|-------------|-----| | Base color, emissive | sRGB | Authored as visible color — GPU linearizes on sample | | Normal, roughness, metallic, AO | Linear | Physical parameters — gamma would distort values | ## Common mistakes - **Loading roughness as sRGB** — makes 0.5 appear as ~0.22, materials look too shiny - **Loading normal maps with sRGB** — corrupts direction vectors, surface detail is lost - **Forgetting the use_separate_mr flag** — shader reads packed MR texture (white fallback = all 1.0), making everything fully metallic and rough - **Not checking `metallic_roughness_texture` before loading separate** — if both packed and separate exist, prefer packed ## Reference See [Lesson 52 — PBR Textures](../../../lessons/gpu/52-pbr-textures/) for the full implementation.
Voir sur GitHub