计划执行与检查节点
executing-plans
按既定实施计划完成工作,保持过程检查和反馈。
scenario-godot-rendering-lighting【效率与协作】Use when lighting or rendering a Godot 4.7 3D scene: pick a renderer (Forward+, Mobile, Compatibility), choose GI (SDFGI, VoxelGI, LightmapGI, reflection probes), bake lightmaps without a mouse, tune WorldEnvironment, tonemapper (AgX, ACES, Filmic), glow, fog, volumetric fog and god rays, shadows and shadow acne, quality presets for PC and phones, Co…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Target: Godot 4.7.2.stable, macOS Apple Silicon (Metal by default).
Expert level here means that lighting comes from a measured loop: a calibration scene, one variable at a time, a rendered image looked at after every change, numbers on that image, and a GPU cost for every effect. The renderer and the GI method are chosen first, because they decide what the other settings can do. The art direction (value pattern, warm and cool, focal contrast) is judged on pixels the agent actually opened, never on the inspector. If a sibling skill named here is missing from your available skills, ask the user to install it (npx skills add scenario-labs/skills --skill <name>); unattended, proceed from tool schemas and flag the gap.
REQUIRED BACKGROUND: scenario-godot-expert (channels, gd_run, the review loop, 4.7 traps).
lookdev.gd builds an exterior and a sealed room.fallback_to_opengl3 defaults to true (docs, P15): set it false on PC so a bad driver fails loudly; on Android keeping it true is a choice, so test the Compatibility look..gdshader (Acerola 9:39). The docs list Forward+ and Mobile, but the docs pattern (color as a storage image) logs 172 errors on Mobile in 4.7.2 because Mobile's color buffer lacks the storage bit, and Compatibility ignores the effect silently (P12). Ship it on Forward+ and guard Mobile. Callbacks run on the render thread: mutex any state shared with the main thread, pad push constants to multiples of 16 bytes, and remember upscaling runs after post (docs). For post with UI on top, a CanvasLayer ColorRect works everywhere (Lukky).| Input | Default if not given |
|---|---|
| Target platforms and renderer per platform | Forward+ desktop. Project default rendering_method.mobile="mobile", .web="gl_compatibility" |
| Frame budget and reference GPU | 60 fps (16.6 ms) on PC; measure on Vulkan (Metal reports 0 GPU ms) |
| Static or dynamic world: moving sun, destructible geometry, size | static interior: lightmaps; open day/night: SDFGI; mid-size dynamic: VoxelGI |
| Mood references and time of day | one image or three words ("cold dawn, foggy, hopeful") |
| Hero subject and camera(s) | a Camera3D path, else the scene's current camera |
| Asset source | glTF from blender-expert or scenario-* skills: check UV2 and stray emission |
Load the toolkit: sys.path gets skills/scenario-godot-expert/scripts and skills/scenario-godot-rendering-lighting/scripts, then import gd_lighting as gl and gl.install(P). Full code: references/procedures.md.
rendering_method, Jolt, fallback) (P1). gl.capture_renderers(P, scene) captures one view per renderer and returns the WARNING lines. GATE: renderer written in project.godot; parity sheet opened; dropped features listed in the handoff.gl.build_lookdev(P) (P3), capture the three cameras. GATE: look_checks p95 minus p05 above 0.25, clipped under 5 percent; opened: dark sphere shows form, white not clipped, mirror reflects sky.gi_bake.gd:prepare (sun Dynamic, others Static, hidden lights Disabled, UV2 check), then the windowed gi_bake.gd:lightmap editor job (P7);gi_bake.gd:voxelgi, windowed (P6);gl.audit(P, scene, ["forward_plus", "mobile"]) (P2). GATE: no error flags; squint(img) opened with one focal value; focal_contrast at least 0.05.gl.sweep one variable at a time: tonemapper (tonemap_variants, P5), exposure, glow, fog, volumetric fog (P10), Adjustments last (cool shadows, warm lights via the color-correction gradient, Picster 45:07). GATE: each sheet opened, winner named with its numbers, no variant clipping over 5 percent unless briefed.shadow_normal_bias first, then shadow_bias (SeasonalAsh 0.05 against the 0.1 default, frames 4:13); blend splits on; max distance set to the playable range (Picster 400 outdoors, default 100). GATE: grazing-angle close-up opened, no stripes, contact shadow attached.graphics_tiers.gd presets through a sweep with call and measure=60 on --rendering-driver vulkan (P11): low and medium use 2 shadow splits, high and ultra 4. Per-effect deltas from the P9 template. On Mobile use MetalFX spatial on Apple, else bilinear (P13). GATE: each tier's GPU ms fits the budget on the target renderer, and the low tier keeps the mood.compositor_tools.gd:attach plus post_effect.gd and a GLSL compute shader (P12). GATE: the effect shows on Forward+; Mobile skips with one warning.meshes/light_baking=2 (Static Lightmaps; the default 1 is plain Static) and meshes/lightmap_texel_size (default 0.2; 0.5 or more on huge scenes that crash the bake) (P15, docs). Never gitignore *.unwrap_cache (keeps UV2 stable); keep .lmbake external (docs).rendering/lightmapping/denoising/denoiser is project-wide: 0 JNLM (default), 1 OIDN (needs the external binary) (docs, P15).LightmapGI.shadowmask_mode: None (0, default), Replace (1, realtime near, baked beyond max distance, best for foliage), Overlay (2, fast cameras). Only the first Dynamic DirectionalLight3D; switch without rebake (docs, P15).ssao_light_affect defaults to 0.0 (docs, P15).importer="3d_texture", slices/horizontal); a 256x16 strip with 16 slices loads as 16x16x16 (P15). HDR Clamp Exposure compresses only luminance above about 4096 (a 100000 sun pixel became 14988; 50 stayed 50, P15). Debanding is off by default. Exposure and DOF live in CameraAttributes on the Camera3D, quality knobs in Project Settings.| Value | What it is relative to | Source |
|---|---|---|
shadow_bias 0.05 | default 0.1 | SeasonalAsh frames 4:13; P1 |
| shadow blur 2 to 3 | default 1.0 | SeasonalAsh 5:13 |
| directional max distance 100 | default; Picster 400 outdoors | P1; Picster 54:08 |
| volumetric fog volume size | 64 default, 256 good, 512 best; +0.2 to 1.1 (64), +1.5 to 2.7 (256), +3.9 (512) ms at 1080p | Four Games 2:44; P9 |
| fog anisotropy 0.7 for god rays | default 0.2 | Four Games 0:32; P1 |
| SDFGI convergence | about 30 frames (enum index 5); capture after 40 | P1, P8 |
| SDFGI bounce feedback | default 0.5; above 0.5 risks runaway | P1; Omogonix 28:10 |
| SDFGI max distance | 204.8 default, camera far 4000 | P15 |
| lights per mesh | Mobile 8 omni + 8 spot; Forward+ 512 clustered elements per view | docs |
| spot shadow angle | fails above 89° | docs |
| LightmapGI quality order | supersampling, then texel size, then quality | Brackeys 34:34 |
| LightmapGI Low bake, lookdev room | 3.6 to 15 s bake (M5 Max, under load) | P7 |
| effect GPU ms at 1080p, tiny scene | SSIL +1.4 to 1.7, SSR +0.9 to 1.3, SDFGI +0.7 to 1.1; SSAO, glow, TAA, SMAA, MSAA 2x each under 0.8 (under 0.5 is noise) | P9, Vulkan |
| tier GPU ms (Forward+ / Mobile) | low 1.5 / 0.62, high 2.9 to 4.3 / 1.73, ultra 3.6 to 4.85 / 1.64 | P11, tiny scene |
Effect costs scale with resolution and scene: re-measure with the P9 template before quoting them.
gl.audit zero error flags per target renderer; gd_run.check_all zero parse errors; look_checks clipped under 0.05, crushed under 0.3, p95 minus p05 above 0.25, focal_contrast at least 0.05; bake files exist and lightmap_textures at least 1; .gitignore has no unwrap_cache; each tier's GPU ms within budget on Vulkan.references/critique.md is the rubric.| Mistake | What it looks like | Fix |
|---|---|---|
| Leaving Linear tonemap | blown highlights, flat sky | AgX or ACES, then exposure |
| Lighting in the editor preview sun | game is gray | WorldEnvironment and sun in the scene (SeasonalAsh 1:40) |
| SDFGI plus VoxelGI | double bounce, cost | one GI per area |
| Lightmap meshes without UV2 | black or garbage bake | add_uv2 on primitives, Static Lightmaps on glTF |
| Hidden light still baked | ghost light | Bake Mode Disabled (prepare does it) |
| Expecting FSR1 on Mobile | identical to bilinear, warning "FSR1 3D scaling is only available when using the Forward+ renderer" | MetalFX spatial on Apple, else bilinear (P13) |
| docs CompositorEffect on Mobile | 170+ errors per run | storage-bit guard (post_effect.gd) |
| Stray emission on imported glTF | glowing props | audit emissive_without_glow, zero it (Gamefromscratch 5:25) |
| Writing "30" into frames_to_converge | wrong enum index | gl.setting_index(key, 30) gives 5 |
| SSAO on, nothing changes | AO invisible in direct light | raise ssao_light_affect |
| LUT as a plain PNG | color correction ignored | reimport as Texture3D with slices |
graphics_tiers.gd); scenario-godot-shaders (compositor GLSL needs); scenario-godot-expert (sheets, audit JSON, parity notes). Scene and .tres files committed, plus .agent_out/ sheets and JSON.Observed in 4.7.2 (references/expert-notes.md, Observed):
LightmapGI.bake does not exist for scripts; the editor button route works (P7). VoxelGI.bake exists but headless saves empty data.GeometryInstance3D.lightmap_scale is gone: use gi_lightmap_texel_scale.--rendering-driver vulkan.references/procedures.md: P0 to P15, full code, live test, result line each.references/expert-notes.md: judgment by expert with timestamps, plus Observed 4.7.2 facts.references/critique.md: image rubric. references/gui-paths.md: editor paths. references/sources.md: sources and timestamps.scripts/gd_lighting.py and scripts/agentkit/rendering/: lookdev, light_audit, sweep, gi_bake, graphics_tiers, compositor_tools, compositor/.