一键导入
forge-grass-rendering
Add instanced grass rendering with segmented blades, wind animation, LOD density rings, and terrain LOD with geomorphing to an SDL GPU project
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Add instanced grass rendering with segmented blades, wind animation, LOD density rings, and terrain LOD with geomorphing to an SDL GPU project
用 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 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
Run a quality review pass on a lesson before publishing, catching recurring issues found across project PR history
| name | forge-grass-rendering |
| description | Add instanced grass rendering with segmented blades, wind animation, LOD density rings, and terrain LOD with geomorphing to an SDL GPU project |
Add grass rendering to an SDL GPU project using forge_scene.h. Implements
instanced segmented grass blades with wind animation, density-based LOD rings,
and tile-based terrain LOD with vertex shader geomorphing.
forge_shapes_plane() — generate tile meshes at different resolutionsforge_scene_upload_buffer_deferred() — per-frame instance buffer uploadforge_scene_create_shader() — create custom shaders alongside forge_sceneSDL_SetGPUViewport() / SDL_SetGPUScissor() — split-screen viewportsSDL_DrawGPUIndexedPrimitives() — instanced draw with per-instance bufferforge_noise_fbm2d() — procedural heightmap generationforge_hash_wang() / forge_hash_to_float() — deterministic placement variationEach blade is a vertical segmented strip with 2*(N+1) vertices and 2*N
triangles. The height_t attribute (0 at base, 1 at tip) controls wind
weighting and tapering.
for (int i = 0; i <= segments; i++) {
float t = (float)i / (float)segments;
float half_w = 0.5f * (1.0f - t * GRASS_BLADE_TIP_TAPER);
verts[2*i+0] = (GrassVertex){ {-half_w, t, 0}, t };
verts[2*i+1] = (GrassVertex){ { half_w, t, 0}, t };
}
typedef struct {
float position[3]; /* world-space base position */
float rotation; /* Y-axis rotation (radians) */
float scale[2]; /* width, height */
float color[3]; /* RGB tint */
float _pad; /* alignment to 40 bytes */
} GrassInstance;
float wind_weight = height_t * height_t; /* quadratic: tip bends most */
float phase = time * wind_speed + world.x * 0.7 + world.z * 0.3;
float wind_offset = sin(phase) * wind_strength * wind_weight;
float2 snapped_uv = round(global_uv / coarse_cell_size) * coarse_cell_size;
float2 morphed_uv = lerp(global_uv, snapped_uv, morph_factor);
float morphed_x = lerp(world_x, snapped_x, morph_factor);
float h = height_tex.SampleLevel(smp, morphed_uv, 0).r;
half_w / height aspectSee Lesson 50 — Grass Rendering for the full implementation.