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 para a instalação

Informações da origem

Repositório
Nebulavenus/forge-gpu
Última atividade na origem
1 de março de 2026 às 21:31
Idioma detectado do SKILL.md
inglês
Estrelas
38
Forks
7

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
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 no GitHub