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.

Zur Installation springen

Quellinformationen

Repository
Nebulavenus/forge-gpu
Letzte Quellaktivität
13. März 2026 um 17:34
Erkannte Sprache von SKILL.md
Englisch
Sterne
38
Forks
7

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
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`
Auf GitHub ansehen