Skip to main content

forge-scene-model-loading

Load and render pipeline-processed 3D models (.fscene + .fmesh + .fmat) through forge_scene.h with per-primitive materials, mesh instancing, and scene hierarchy traversal.

Ir a la instalación

Datos de origen

Repositorio
Nebulavenus/forge-gpu
Última actividad en el origen
13 de marzo de 2026 a las 17:34
Idioma detectado de SKILL.md
inglés
Estrellas
38
Forks
7

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
forge-scene-model-loading
description
Load and render pipeline-processed 3D models (.fscene + .fmesh + .fmat) through forge_scene.h with per-primitive materials, mesh instancing, and scene hierarchy traversal.
trigger
Use when someone needs to load glTF-derived models, render multi-material meshes, or asks about ForgeSceneModel.
# forge-scene-model-loading Load pipeline-processed 3D models through `forge_scene.h`. One `forge_scene_load_model()` call handles file loading, GPU buffer upload, and per-material texture loading. The draw functions traverse the scene node hierarchy and bind materials per-submesh. ## Prerequisites Models must be processed through the asset pipeline tools first: ```bash # Process mesh (produces .fmesh + .fmat) ./build/tools/mesh/forge_mesh_tool input.gltf output.fmesh --verbose # Process scene hierarchy (produces .fscene) ./build/tools/scene/forge_scene_tool input.gltf output.fscene --verbose # Copy textures alongside the .fmat file cp source_textures/*.png output_dir/ ``` ## Usage pattern ```c #define SDL_MAIN_USE_CALLBACKS 1 #include <SDL3/SDL.h> #include <SDL3/SDL_main.h> #include "math/forge_math.h" #define FORGE_PIPELINE_IMPLEMENTATION #include "pipeline/forge_pipeline.h" #define FORGE_SCENE_MODEL_SUPPORT #define FORGE_SCENE_IMPLEMENTATION #include "scene/forge_scene.h" typedef struct { ForgeScene scene; ForgeSceneModel model; } app_state; SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) { app_state *state = (app_state *)SDL_calloc(1, sizeof(*state)); if (!state) return SDL_APP_FAILURE; *appstate = state; ForgeSceneConfig cfg = forge_scene_default_config("Model Viewer"); cfg.cam_start_pos = vec3_create(0.0f, 2.0f, 5.0f); cfg.font_path = "assets/fonts/liberation_mono/LiberationMono-Regular.ttf"; if (!forge_scene_init(&state->scene, &cfg, argc, argv)) return SDL_APP_FAILURE; /* Load a pipeline-processed model. * base_dir is where textures are found (same dir as .fmat). */ if (!forge_scene_load_model(&state->scene, &state->model, "assets/MyModel/MyModel.fscene", "assets/MyModel/MyModel.fmesh", "assets/MyModel/MyModel.fmat", "assets/MyModel")) { SDL_Log("Failed to load model"); return SDL_APP_FAILURE; } return SDL_APP_CONTINUE; } SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { app_state *state = (app_state *)appstate; return forge_scene_handle_event(&state->scene, event); } SDL_AppResult SDL_AppIterate(void *appstate) { app_state *state = (app_state *)appstate; ForgeScene *s = &state->scene; if (!forge_scene_begin_frame(s)) return SDL_APP_CONTINUE; mat4 placement = mat4_translate(vec3_create(0.0f, 0.0f, 0.0f)); /* Shadow pass */ forge_scene_begin_shadow_pass(s); forge_scene_draw_model_shadows(s, &state->model, placement); forge_scene_end_shadow_pass(s); /* Main pass */ forge_scene_begin_main_pass(s); forge_scene_draw_model(s, &state->model, placement); forge_scene_draw_grid(s); forge_scene_end_main_pass(s); return forge_scene_end_frame(s); } void SDL_AppQuit(void *appstate, SDL_AppResult result) { (void)result; app_state *state = (app_state *)appstate; if (!state) return; if (forge_scene_device(&state->scene)) { if (!SDL_WaitForGPUIdle(forge_scene_device(&state->scene))) { SDL_Log("SDL_WaitForGPUIdle failed: %s", SDL_GetError()); } forge_scene_free_model(&state->scene, &state->model); } forge_scene_destroy(&state->scene); SDL_free(state); } ``` ## Key defines Both defines must appear before including `forge_scene.h`: | Define | Purpose | |--------|---------| | `FORGE_SCENE_MODEL_SUPPORT` | Enables model types and functions (pulls in `forge_pipeline.h`) | | `FORGE_SCENE_IMPLEMENTATION` | Compiles the implementation (one `.c` file only) | | `FORGE_PIPELINE_IMPLEMENTATION` | Compiles the pipeline library (one `.c` file only) | ## ForgeSceneModelVertex layout The model pipeline uses a 48-byte vertex with tangent data for normal mapping: | Field | Type | Size | Offset | HLSL | |----------|--------|-------|--------|-----------| | position | float3 | 12 B | 0 | TEXCOORD0 | | normal | float3 | 12 B | 12 | TEXCOORD1 | | uv | float2 | 8 B | 24 | TEXCOORD2 | | tangent | float4 | 16 B | 32 | TEXCOORD3 | ## ForgeSceneModel struct After `forge_scene_load_model`, the struct contains: | Field | Type | Description | |-------|------|-------------| | `scene_data` | `ForgePipelineScene` | Node hierarchy with world transforms | | `mesh` | `ForgePipelineMesh` | Vertex/index data, submeshes, LODs | | `materials` | `ForgePipelineMaterialSet` | PBR material descriptions | | `vertex_buffer` | `SDL_GPUBuffer *` | Uploaded 48-byte vertices | | `index_buffer` | `SDL_GPUBuffer *` | Uploaded uint32 indices | | `mat_textures[]` | `ForgeSceneModelTextures` | Per-material GPU textures | | `draw_calls` | `uint32_t` | Updated each `draw_model` call | ## Pipeline variants The renderer selects a pipeline per-submesh based on material properties: | Variant | Condition | Behavior | |---------|-----------|----------| | `model_pipeline` | Default (opaque) | Cull back, depth test + write | | `model_pipeline_blend` | `alpha_mode == BLEND` | Alpha blend, no depth write | | `model_pipeline_double` | `double_sided == true` | Cull none, depth test + write | ## Texture slots and fallbacks Each material binds up to 5 textures. Missing slots use 1x1 fallbacks: | Slot | Texture | Fallback | sRGB | |------|---------|----------|------| | 0 | Base color | White (1,1,1,1) | Yes | | 1 | Normal map | Flat (0.5,0.5,1) | No | | 2 | Metallic-roughness | White (1,1,1,1) | No | | 3 | Occlusion | White (1,1,1,1) | No | | 4 | Emissive | Black (0,0,0,1) | Yes | | 5 | Shadow map | Scene shadow map | No | ## CMakeLists.txt Models require cJSON for `.fmat` parsing: ```cmake add_executable(my-lesson WIN32 main.c ${CMAKE_SOURCE_DIR}/third_party/cJSON/cJSON.c) target_include_directories(my-lesson PRIVATE ${FORGE_COMMON_DIR} ${CMAKE_SOURCE_DIR}/third_party/cJSON) target_link_libraries(my-lesson PRIVATE SDL3::SDL3 $<$<NOT:$<C_COMPILER_ID:MSVC>>:m>) # Copy model assets to build output add_custom_command(TARGET my-lesson POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/assets $<TARGET_FILE_DIR:my-lesson>/assets) ``` ## Common mistakes - **Forgetting `FORGE_SCENE_MODEL_SUPPORT`.** Without this define, the model types and functions are not compiled. You get "unknown type" errors for `ForgeSceneModel`. - **Forgetting `FORGE_PIPELINE_IMPLEMENTATION`.** The pipeline library must be compiled in exactly one `.c` file. Without it, you get linker errors for `forge_pipeline_load_scene`, etc. - **Wrong texture paths.** The `.fmat` stores source-relative texture paths from the original glTF. `forge_scene_load_model` extracts just the filename and looks for it in `base_dir`. Textures must be copied alongside the `.fmat` file. - **Not freeing models before `forge_scene_destroy`.** Call `forge_scene_free_model` for each loaded model before destroying the scene. The model holds GPU resources (buffers, textures) that reference the device. - **Applying redundant scale.** Some glTF models (e.g., Duck) have scale transforms baked into their scene hierarchy. Check the node world transforms before applying additional scaling in the placement matrix. ## Reference - Source: `common/scene/forge_scene.h` (model support section) - Shaders: `common/scene/shaders/scene_model.vert.hlsl`, `scene_model.frag.hlsl` - Lesson: `lessons/gpu/41-scene-model-loading/` - Pipeline types: `common/pipeline/forge_pipeline.h`
Ver en GitHub