一键导入
forge-pipeline-morph-animations
Add morph target (blend shape) animations with pipeline assets to an SDL GPU project using ForgeSceneMorphModel.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Add morph target (blend shape) animations with pipeline assets to an SDL GPU project using ForgeSceneMorphModel.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Add PBR texture loading with separate roughness/metallic support to an SDL GPU project using forge_scene.h
Add Cook-Torrance PBR shading with GGX, Schlick-GGX, and Schlick Fresnel to an SDL GPU project alongside forge_scene.h
Add instanced grass rendering with segmented blades, wind animation, LOD density rings, and terrain LOD with geomorphing to an SDL GPU project
Add procedural noise texture generation to the asset pipeline — C tool, Python plugin, web UI with live preview
Add an asset pipeline lesson — hybrid Python + C track for asset processing, procedural geometry, and web frontend
Add an audio lesson — sound playback, mixing, spatial audio, DSP effects, with SDL GPU scenes and forge UI
| name | forge-pipeline-morph-animations |
| description | Add morph target (blend shape) animations with pipeline assets to an SDL GPU project using ForgeSceneMorphModel. |
Add morph target animation support to an SDL GPU project that already uses
forge_scene.h. This skill covers loading .fmesh files with morph data,
evaluating morph weight animation from .fanim channels, CPU-blending
per-vertex deltas, and uploading to GPU storage buffers for vertex shader
displacement.
forge_scene.h with FORGE_SCENE_MODEL_SUPPORT enabledforge_pipeline.h for .fmesh and .fanim loadingFLAG_MORPHS set in .fmeshscene_morph.vert.hlsl, scene_morph_shadow.vert.hlsl)Process glTF models with morph targets using the pipeline tools:
forge_mesh_tool model.gltf model.fmesh --verbose
forge_scene_tool model.gltf model.fscene --verbose
forge_anim_tool model.gltf model.fanim --verbose
The mesh tool detects morph targets and sets FLAG_MORPHS in the .fmesh
header. It also disables vertex deduplication (morph deltas reference original
vertex indices). The anim tool preserves MORPH_WEIGHTS channels
(target_path = 3) with variable component counts.
#define FORGE_SCENE_MODEL_SUPPORT
#define FORGE_SCENE_IMPLEMENTATION
#include "scene/forge_scene.h"
ForgeSceneMorphModel morph_model;
/* fmat_path may be NULL if no materials; fanim_path may be NULL for manual weights */
if (!forge_scene_load_morph_model(&scene, &morph_model,
fscene_path, fmesh_path, fmat_path, fanim_path, base_dir)) {
SDL_Log("Failed to load morph model");
return SDL_APP_FAILURE;
}
/* After forge_scene_begin_frame(): */
morph_model.anim_speed = speed_slider_value;
/* Toggle manual_weights to override animation with direct control */
if (morph_model.manual_weights) {
morph_model.morph_weights[0] = slider_w0;
morph_model.morph_weights[1] = slider_w1;
}
forge_scene_update_morph_animation(&scene, &morph_model, dt);
forge_scene_update_morph_animation does three things:
.fanim (unless manual_weights is set)blended[v] += weight * delta[v]mat4 placement = mat4_multiply(
mat4_translate(vec3_create(x, y, z)),
mat4_scale_uniform(scale));
/* Shadow pass */
forge_scene_begin_shadow_pass(&scene);
forge_scene_draw_morph_model_shadows(&scene, &morph_model, placement);
forge_scene_end_shadow_pass(&scene);
/* Main pass */
forge_scene_begin_main_pass(&scene);
forge_scene_draw_grid(&scene);
forge_scene_draw_morph_model(&scene, &morph_model, placement);
forge_scene_end_main_pass(&scene);
forge_scene_free_morph_model(&scene, &morph_model);
The morph vertex shader uses the standard 48-byte vertex layout (same as
scene_model.vert.hlsl) plus two StructuredBuffer<float4> for position
and normal deltas, indexed by SV_VertexID. The float4 type ensures a
consistent 16-byte stride across SPIRV and DXIL backends:
StructuredBuffer<float4> morph_pos_deltas : register(t0, space0);
StructuredBuffer<float4> morph_nrm_deltas : register(t1, space0);
float3 morphed_pos = input.position + morph_pos_deltas[input.vertex_id].xyz;
float3 morphed_nrm = normalize(input.normal + morph_nrm_deltas[input.vertex_id].xyz);
The shadow variant uses only position deltas (1 storage buffer).