forge-pbr-textures
A specialized tool for loading and rendering PBR materials in SDL graphics pipelines.
Install
mkdir -p .claude/skills/forge-pbr-textures && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/14606" && unzip -o skill.zip -d .claude/skills/forge-pbr-textures && rm skill.zipInstalls to .claude/skills/forge-pbr-textures
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Add PBR texture loading with separate roughness/metallic support to an SDL GPU project using forge_scene.hKey capabilities
- →Load PBR material texture sets including albedo, normal, roughness, metallic, AO, and emissive.
- →Support both packed metallic-roughness (glTF convention) and separate single-channel textures (ambientCG convention).
- →Render textured PBR materials using a Cook-Torrance BRDF shader.
- →Handle sRGB and linear color spaces correctly for different texture types.
- →Repurpose the `shininess` field to indicate the use of separate metallic-roughness textures.
How it works
The skill parses material files, loads various texture types (albedo, normal, roughness, metallic, etc.) into appropriate color spaces, and configures a shader to use these textures for PBR rendering.
Inputs & outputs
When to use forge-pbr-textures
- →Adding PBR support to models
- →Configuring texture loading pipelines
- →Material rendering setup
About this skill
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
.fmatsidecar 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
/* 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:
ForgeSceneModelFragUniforms fu;
forge_scene__fill_model_frag_uniforms(scene, mat, &fu);
fu.shininess = (tex.roughness || tex.metallic) ? 1.0f : 0.0f;
In the shader:
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_texturebefore loading separate — if both packed and separate exist, prefer packed
Reference
See Lesson 52 — PBR Textures for the full implementation.
When not to use it
- →When PBR materials are not being used.
- →When only basic texture loading without PBR properties is required.
- →When the project does not use `forge_scene.h` or SDL GPU.
Limitations
- →The skill is designed for SDL GPU projects using `forge_scene.h`.
- →The skill relies on specific texture naming conventions and formats.
- →The skill repurposes an existing uniform field for a new flag, which might conflict with other uses.
How it compares
This workflow provides specific mechanisms for handling PBR texture loading and shader configuration, including support for different metallic-roughness conventions, which is more specialized than general texture loading.
Compared to similar skills
forge-pbr-textures side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| forge-pbr-textures (this skill) | 0 | 4mo | No flags | Advanced |
| forge-shader-grid | 0 | 5mo | No flags | Advanced |
| unity-developer | 142 | 4mo | No flags | Advanced |
| unity-mcp-orchestrator | 17 | 4mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by Nebulavenus
View all by Nebulavenus →You might also like
forge-shader-grid
Nebulavenus
>
unity-developer
sickn33
Build Unity games with optimized C# scripts, efficient rendering, and proper asset management. Masters Unity 6 LTS, URP/HDRP pipelines, and cross-platform deployment. Handles gameplay systems, UI implementation, and platform optimization. Use PROACTIVELY for Unity performance issues, game mechanics, or cross-platform builds.
unity-mcp-orchestrator
CoplayDev
Orchestrate Unity Editor via MCP (Model Context Protocol) tools and resources. Use when working with Unity projects through MCP for Unity - creating/modifying GameObjects, editing scripts, managing scenes, running tests, or any Unity Editor automation. Provides best practices, tool schemas, and workflow patterns for effective Unity-MCP integration.
arm-cortex-expert
sickn33
Senior embedded software engineer specializing in firmware and driver development for ARM Cortex-M microcontrollers (Teensy, STM32, nRF52, SAMD). Decades of experience writing reliable, optimized, and maintainable embedded code with deep expertise in memory barriers, DMA/cache coherency, interrupt-driven I/O, and peripheral drivers.
implementing-jsc-classes-cpp
oven-sh
Implements JavaScript classes in C++ using JavaScriptCore. Use when creating new JS classes with C++ bindings, prototypes, or constructors.
rsyslog-module
rsyslog
Encodes technical requirements for rsyslog modules, including concurrency, metadata, and initialization.