Skip to main content

forge-procedural-geometry

Generate procedural 3D geometry using forge_shapes.h — parametric surfaces (sphere, icosphere, cylinder, cone, torus, plane, cube, capsule) with struct-of-arrays layout for GPU upload

الانتقال إلى التثبيت

معلومات المصدر

المستودع
Nebulavenus/forge-gpu
آخر نشاط في المصدر
٨ مارس ٢٠٢٦ في ١١:٥٢
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٣٨
التفرعات
٧

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
forge-procedural-geometry
description
Generate procedural 3D geometry using forge_shapes.h — parametric surfaces (sphere, icosphere, cylinder, cone, torus, plane, cube, capsule) with struct-of-arrays layout for GPU upload
Generate and render procedural geometry using the `forge_shapes.h` header-only library. Shapes are unit-scale, centred at origin, Y-up, CCW winding. ## Include pattern One `.c` file defines the implementation; all others get declarations only: ```c /* In exactly ONE .c file: */ #define FORGE_SHAPES_IMPLEMENTATION #include "shapes/forge_shapes.h" /* In all other files: */ #include "shapes/forge_shapes.h" ``` ## Generate and upload a shape ```c /* Generate a 32-slice, 16-stack UV sphere */ ForgeShape sphere = forge_shapes_sphere(32, 16); /* Create GPU buffers for struct-of-arrays layout */ SDL_GPUBuffer *pos_buf = upload_gpu_buffer(device, sphere.positions, sphere.vertex_count * sizeof(vec3)); SDL_GPUBuffer *nor_buf = upload_gpu_buffer(device, sphere.normals, sphere.vertex_count * sizeof(vec3)); SDL_GPUBuffer *idx_buf = upload_gpu_buffer_index(device, sphere.indices, sphere.index_count * sizeof(uint32_t)); /* Free CPU-side data after upload */ int index_count = sphere.index_count; forge_shapes_free(&sphere); ``` ## Bind and draw (struct-of-arrays) ```c /* Bind position buffer at vertex slot 0 */ SDL_GPUBufferBinding pos_bind = { .buffer = pos_buf, .offset = 0 }; SDL_BindGPUVertexBuffers(rpass, 0, &pos_bind, 1); /* Bind normal buffer at vertex slot 1 */ SDL_GPUBufferBinding nor_bind = { .buffer = nor_buf, .offset = 0 }; SDL_BindGPUVertexBuffers(rpass, 1, &nor_bind, 1); /* Bind index buffer */ SDL_GPUBufferBinding idx_bind = { .buffer = idx_buf, .offset = 0 }; SDL_BindGPUIndexBuffer(rpass, &idx_bind, SDL_GPU_INDEXELEMENTSIZE_32BIT); /* Draw */ SDL_DrawGPUIndexedPrimitives(rpass, index_count, 1, 0, 0, 0); ``` ## Pipeline vertex attributes Configure two vertex buffer slots matching the struct-of-arrays layout: ```c SDL_GPUVertexBufferDescription vbufs[] = { { .slot = 0, .pitch = sizeof(vec3), .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX }, { .slot = 1, .pitch = sizeof(vec3), .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX }, }; SDL_GPUVertexAttribute attrs[] = { { .location = 0, .buffer_slot = 0, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, .offset = 0 }, { .location = 1, .buffer_slot = 1, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, .offset = 0 }, }; ``` ## Multiple shapes in one scene ```c /* Generate all shapes */ ForgeShape shapes[] = { forge_shapes_sphere(32, 16), forge_shapes_torus(24, 12, 1.0f, 0.4f), forge_shapes_plane(4, 4), }; int shape_count = sizeof(shapes) / sizeof(shapes[0]); /* Upload each to GPU, store buffers and counts */ for (int i = 0; i < shape_count; i++) { upload_shape_to_gpu(device, &shapes[i], &gpu_shapes[i]); forge_shapes_free(&shapes[i]); } /* In render loop: draw each with its own model matrix */ for (int i = 0; i < shape_count; i++) { set_push_uniforms(rpass, model_matrices[i]); bind_and_draw(rpass, &gpu_shapes[i]); } ``` ## Available generators | Function | Description | Default params | |---|---|---| | `forge_shapes_sphere(slices, stacks)` | UV sphere, radius 1 | 32, 16 | | `forge_shapes_icosphere(subdivisions)` | Even triangle distribution | 2 | | `forge_shapes_cylinder(slices, stacks)` | No caps, height 2 | 32, 1 | | `forge_shapes_cone(slices, stacks)` | Apex at Y=+1, no base | 32, 1 | | `forge_shapes_torus(slices, stacks, major, tube)` | Donut in XZ plane | 32, 16, 1.0, 0.4 | | `forge_shapes_plane(slices, stacks)` | XZ plane, Y=0 | 4, 4 | | `forge_shapes_cube(slices, stacks)` | 6 faces, per-face normals | 1, 1 | | `forge_shapes_capsule(slices, stacks, cap_stacks, half_h)` | Cylinder + hemisphere caps | 32, 4, 4, 1.0 | ## Common mistakes 1. **Forgetting to free** — always call `forge_shapes_free()` after GPU upload 2. **Wrong vertex slot** — positions go to slot 0, normals to slot 1; swapping them produces garbled lighting 3. **Using interleaved vertex layout** — `ForgeShape` uses struct-of-arrays; bind separate buffers per attribute, not one interleaved buffer 4. **Missing seam at U=0/U=1** — the sphere has `(slices+1)` columns to handle the texture seam; this is intentional, not a bug ## References - Library: [`common/shapes/forge_shapes.h`](../../../common/shapes/forge_shapes.h) - API docs: [`common/shapes/README.md`](../../../common/shapes/README.md) - Lesson: [`lessons/assets/04-procedural-geometry/`](../../../lessons/assets/04-procedural-geometry/) - Tests: [`tests/shapes/test_shapes.c`](../../../tests/shapes/test_shapes.c)
عرض على GitHub