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.

Ir a la instalación

Datos de origen

Repositorio
Nebulavenus/forge-gpu
Última actividad en el origen
1 de marzo de 2026 a las 21:31
Idioma detectado de SKILL.md
inglés
Estrellas
38
Forks
7

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
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)
Ver en GitHub