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.

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

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

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

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

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

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

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

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
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)
عرض على GitHub