gamedev-2d-art-lighting-art
Painting 2D art for dynamic lighting: workflow for Unity 2D Lights / Godot CanvasLight, normal map authoring (Sprite Lamp / hand-painted), separation in layers (diffuse / normal / emissive / mask), self- shadowing in pixel art, day/night palette swaps vs realtime light mixing, glow / emissive layers. USE WHEN: integrating 2D Lights with hand-painted sprites, deciding baked vs dynamic lighting, painting normal maps for pixel art.
What this skill does
# 2D Lighting (Art Side) Two paradigms for 2D lighting: 1. **Baked into the sprite** (classic). Highlights and shadows painted directly. Fast, predictable, locks the lighting direction. 2. **Dynamic (engine 2D Lights)**. Sprite is "neutral" diffuse, engine computes lighting from scene lights at runtime. Allows day/night shifts, point lights, dynamic shadows. Modern indie pixel art usually combines both: baked rim light + dynamic fill from scene Lights. ## Engine systems | Engine | 2D lighting system | |--------|-------------------| | **Unity URP 2D** | `2D Renderer Data` + `Light 2D` components (Point/Sprite/Freeform/Parametric/Global). Normal map secondary texture. Shadow Caster 2D for occlusion. | | **Godot 4** | `PointLight2D` / `DirectionalLight2D` + `LightOccluder2D` for shadows. Normal map via shader. | | **Defold** | Custom shaders. | | **Phaser / web** | Pixi.js light filter or custom shader. | ## Sprite layer separation for dynamic lighting A "lit-aware" sprite needs (at minimum): 1. **Diffuse / albedo**: the base color. Drawn flat, no baked shadows. 2. **Normal map**: surface direction encoded in RGB. (See `seamless-textures/SKILL.md` for authoring.) 3. **(Optional) Emissive / glow mask**: pixels that should ignore lighting and stay bright (street lamps, lava, magic). RGB = emission color, alpha = mask. 4. **(Optional) Specular / smoothness**: where light reflects. 5. **(Optional) Self-shadow / occlusion**: which surfaces of the sprite shadow other surfaces of the sprite. Rare in pixel art. Most pixel-art games stop at diffuse + normal + emissive. Adding more is diminishing returns vs hand-painting. ## Painting flat diffuse for dynamic lighting If you'll use 2D Lights, the diffuse should be **flat-lit** — single ambient lighting condition, no strong shadow side. The engine adds the directional shading. Typical workflow: 1. Paint with **uniform mid-tone shading** (no strong light direction). 2. Add **ambient occlusion** (where surfaces meet — under hat brim, under chin, in joints). 3. Don't paint a strong rim/highlight; engine will do it. If you instead want classic **fully-shaded diffuse**, the engine's 2D Light affects it ON TOP of the bake — works but the result is double-shaded (cool effect for dramatic lighting; bad for naturalistic). ## Normal map workflow See `seamless-textures/SKILL.md` for normal map authoring options (Sprite Lamp, Sprite DLight, Materialize, hand-paint). For pixel art: normals on small sprites can look strange because neighboring pixels have different normals → light shifts pixel-by-pixel unevenly. Solutions: - **Smooth normals**: blur the normal map slightly so light transitions smoothly across small sprites. Loses some surface detail but feels more cohesive. - **Hand-paint flat regions**: large flat surfaces of a character (chest, back) should have uniform normal (#8080FF), not noisy. - **Strong normals only at silhouette**: where the form turns away from camera, use stronger Z-component variation; flat interior keeps uniform. ## Self-shadowing in pixel art Real-time self-shadow on a pixel sprite is usually **not worth it**. Dynamic shadows on a 32×32 character look noisy, low-resolution, jittery as the light moves. Common approaches: ### Bake self-shadow into diffuse The cheap way. Paint the sprite with shadow side darker (lit assumed from upper-left). Limits dynamic lighting (always upper-left feel) but looks sharp. ### Use separate top-light and rim-light layers Author two diffuse variants: top-lit and rim-lit. Engine blends based on light direction. Doubles art cost but feels alive. ### Skip self-shadow, rely on directional fill Flat-painted diffuse + 2D Light gives a soft directional fill. Sprite doesn't really self-shadow, but the rim-light hint feels lit. Works for most indie pixel art. ## Emissive / glow Emissive pixels ignore lighting and stay full-bright. Use cases: - Street lamps, candles, fireflies, eyes glowing in dark. - Magic spells, neon signs, lava, screens. - HUD elements. Authoring: - Paint emissive layer in Aseprite (separate layer named "emissive"). - Export as separate texture OR RGBA where alpha = emissive mask. - Engine shader: `final_color = lit_color + emissive_color * emissive_mask`. In Unity URP 2D: assign emissive secondary texture in Sprite Renderer. ## Day / night palette swap vs realtime mixing ### Palette swap approach - One palette per time-of-day (day, dusk, night, dawn). - Engine fades between palettes over X seconds. - Pros: total artist control, retro look. - Cons: doesn't react to dynamic lights (torches stay torch-bright at noon and night). ### Realtime light mixing - One neutral / day diffuse. - Multiple Lights with color tint: - Global Light 2D = sun (warm noon, cool night). - Point Lights = torches (warm, flicker). - Pros: dynamic, torches naturally bloom in night, dynamic shadows. - Cons: can look "modern" vs intended retro feel. ### Hybrid (most modern indie) - Authored ramp shifts per time of day (day uses warm ramp, night uses cool ramp). - Plus Global Light 2D color tint. - Plus emissive lights for explicit glow sources. Stardew Valley uses palette swap (retro fit). Hyper Light Drifter uses realtime. Hollow Knight uses realtime + heavy emissive. ## Glow / bloom Two ways to achieve "glow": 1. **Pre-baked glow halo**: paint a halo around emissive pixels. No shader needed. Cheaper but static. 2. **Post-process bloom**: extract bright pixels, blur, add back. Looks dynamic, requires post-process pass (URP volume Bloom override in Unity, post-process shader in Godot). For pixel art: option 2 conflicts with the pixel-perfect aesthetic (blur softens pixels). Common compromise: enable bloom only on emissive layer, not on the diffuse. ## Common bugs - **Double-shaded sprites**: fully baked diffuse + dynamic light = shadow stacks. Solution: paint flat diffuse OR flat rim, not both. - **Normal map green channel inverted**: light comes from "wrong" direction. Toggle Y-flip in Sprite Renderer / shader. - **Emissive layer also gets lit**: forgot to mask out lighting on emissive. Solution: emissive added AFTER lighting, not multiplied. - **Bloom blurs pixels**: pixel art aesthetic broken. Limit bloom to emissive mask only. - **Pixel-by-pixel normal noise**: sprite looks "wrong" under light. Smooth the normal map. ## See also - [seamless-textures/SKILL.md](../seamless-textures/SKILL.md) — normal map authoring - [palettes/SKILL.md](../palettes/SKILL.md) — palette swap vs realtime - [vfx-2d/SKILL.md](../vfx-2d/SKILL.md) — emissive vfx - Engine: `unity-2d-lighting`
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.