Skip to main content

forge-environment-mapping

Add cube map environment mapping with a skybox and reflective surfaces. Use when someone needs a 360-degree background, reflection mapping, or cube map textures in SDL3 GPU.

Aller à l'installation

Informations de source

Dépôt
Nebulavenus/forge-gpu
Dernière activité de la source
1 mars 2026 à 21:31
Langue détectée de SKILL.md
anglais
Étoiles
38
Forks
7

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
forge-environment-mapping
description
Add cube map environment mapping with a skybox and reflective surfaces. Use when someone needs a 360-degree background, reflection mapping, or cube map textures in SDL3 GPU.
# Environment Mapping — SDL3 GPU Skill Add a cube map skybox and environment reflections to a 3D scene. ## When to use this skill - Rendering a 360-degree background (space, sky, indoor environment) - Adding reflections to metallic or glossy surfaces - Working with `SDL_GPU_TEXTURETYPE_CUBE` textures - Combining multiple graphics pipelines in one render pass ## Cube map texture creation ```c /* Create a cube map texture with 6 faces. */ SDL_GPUTextureCreateInfo tex_info; SDL_zero(tex_info); tex_info.type = SDL_GPU_TEXTURETYPE_CUBE; tex_info.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB; tex_info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER; tex_info.width = face_size; tex_info.height = face_size; tex_info.layer_count_or_depth = 6; /* MUST be 6 for cube maps */ tex_info.num_levels = 1; SDL_GPUTexture *cubemap = SDL_CreateGPUTexture(device, &tex_info); /* Upload each face as a separate layer (0=+X, 1=-X, 2=+Y, 3=-Y, 4=+Z, 5=-Z). */ for (int face = 0; face < 6; face++) { /* Load face image, convert to ABGR8888, map transfer buffer... */ SDL_GPUTextureRegion dst; SDL_zero(dst); dst.texture = cubemap; dst.layer = (Uint32)face; /* Face index = layer index */ dst.w = face_size; dst.h = face_size; dst.d = 1; SDL_UploadToGPUTexture(copy_pass, &src, &dst, false); } ``` ## Skybox rendering pattern ### Vertex shader — depth = 1.0 ```hlsl cbuffer VertUniforms : register(b0, space1) { column_major float4x4 vp_no_translation; }; struct VSOutput { float4 clip_pos : SV_Position; float3 direction : TEXCOORD0; }; VSOutput main(VSInput input) { VSOutput output; output.direction = input.position; float4 pos = mul(vp_no_translation, float4(input.position, 1.0)); output.clip_pos = pos.xyww; /* z = w → depth = 1.0 after divide */ return output; } ``` ### Fragment shader — sample cube map ```hlsl TextureCube skybox_tex : register(t0, space2); SamplerState smp : register(s0, space2); float4 main(PSInput input) : SV_Target { return skybox_tex.Sample(smp, input.direction); } ``` ### Pipeline settings ```c /* Cull FRONT faces — we're inside the cube. */ pipe_info.rasterizer_state.cull_mode = SDL_GPU_CULLMODE_FRONT; /* Depth test LESS_OR_EQUAL to pass at depth=1.0. * Depth write DISABLED — skybox should never occlude anything. */ pipe_info.depth_stencil_state.enable_depth_test = true; pipe_info.depth_stencil_state.enable_depth_write = false; pipe_info.depth_stencil_state.compare_op = SDL_GPU_COMPAREOP_LESS_OR_EQUAL; ``` ### Rotation-only view matrix ```c /* Strip translation so the skybox always surrounds the camera. */ mat4 view_rot = view; view_rot.m[12] = 0.0f; view_rot.m[13] = 0.0f; view_rot.m[14] = 0.0f; mat4 vp_sky = mat4_multiply(proj, view_rot); ``` ## Reflection mapping pattern ### Fragment shader with reflections ```hlsl TextureCube env_tex : register(t1, space2); /* Compute reflection direction */ float3 V = normalize(eye_pos.xyz - world_pos); float3 R = reflect(-V, N); float3 env_color = env_tex.Sample(env_smp, R).rgb; /* Blend diffuse with environment reflection */ float3 blended = lerp(surface_color.rgb, env_color, reflectivity); ``` ## Render order 1. Clear depth to 1.0 2. Draw skybox (depth write off, passes at depth=1.0) 3. Draw objects (depth write on, depth < 1.0 always passes) ## Common mistakes 1. **Forgetting `layer_count_or_depth = 6`** — cube maps require exactly 6 layers. Without this, texture creation fails silently or renders black. 2. **Wrong face order** — `SDL_GPUCubeMapFace` enum order is +X, -X, +Y, -Y, +Z, -Z. Mixing up faces produces seams or incorrect reflections. 3. **Depth write enabled on skybox** — the skybox writes depth=1.0 everywhere, occluding all subsequent geometry. Always disable depth write for the skybox. 4. **Using full view matrix for skybox** — includes camera translation, causing visible parallax when moving. Strip translation columns (m[12], m[13], m[14]). 5. **Wrong cull mode for skybox** — the camera is inside the cube, so front faces point inward (toward the camera). Cull front faces, not back faces. 6. **Not negating V in reflect()** — `reflect()` expects the incident vector pointing toward the surface. The view direction V points away from the surface, so pass `-V`. ## File layout ```text shaders/ ├── skybox.vert.hlsl # Unit cube → clip space with depth=1.0 ├── skybox.frag.hlsl # Sample TextureCube ├── object.vert.hlsl # Standard MVP + model (same as lighting) └── object.frag.hlsl # Blinn-Phong + reflect() + cube map sample ``` ## References - [Lesson 14 — Environment Mapping](../../../lessons/gpu/14-environment-mapping/) - [Lesson 10 — Basic Lighting](../../../lessons/gpu/10-basic-lighting/) (Blinn-Phong) - [Math Lesson 01 — Vectors](../../../lessons/math/01-vectors/) (dot product, reflection)
Voir sur GitHub