Lighting
2D lights, occluders, shadows and the scene’s light map.
Files: lighting.odin.
File overviews
Section titled “File overviews”From lighting.odin:
2D lighting: a scene drawn dark (its ambient light) and lit by Light2D nodes, with shadows cast by LightOccluder nodes (and, if the scene says so, its static bodies’ shapes).
<scene name="Cave" lighting="true" ambient="#202436" bodyShadows="true"> <node kind="Light2D" name="Torch" x="200" y="120" color="#ffb060" energy="1.2" lightRadius="260"/> <node kind="LightOccluder" name="Pillar" x="300" y="160" width="40" height="120"/></scene>- Turning it on (
SceneSettings.lighting,ambient;Scene.lightingat run time): the world layers are multiplied by a light map: the ambient color everywhere (black: pitch dark; white: fully lit), plus each light. Screen layers (HUDs, menus) aren’t lit. - Lights (
Light2D,LightSettings): a point light shines all around, a spot light in a cone (angledegrees wide) the way the node faces (its world rotation; 0 is right). Itscolortimesenergyat its center fades to nothing atradius. Lights add up. - Shadows (
shadowson the light): a light stops at the edges of occluders:LightOccludernodes (a rectangle, circle, polygon or segment, like a CollisionShape’s) and, with the scene’sbodyShadows, the shapes of its static bodies (a TileMap’s or LDtk level’s walls).Light_Visibilitycomputes what a light reaches: the polygon its light fills. - How it draws: the light map is a render target the size of the screen (
Scene.lightingkeeps it); lights are triangle fans over it with their brightness in the vertices’ colors, added together, and the map is drawn over the world with multiply blending. No shaders, so it works with every renderer, the software one and the web’s included. Normal-mapped sprites need shaders (a later feature).
LightKind
Section titled “LightKind”LightKind :: enum { // All around it Point, // A cone the way it faces Spot,}What a light is shaped like
enum. Source: lighting.odin:34
LightSettings
Section titled “LightSettings”LightSettings :: struct { // Point or Spot kind: LightKind, // Its color at the center color: sdl.Color, // How bright: the color times this (2 is twice as bright, up to white) energy: f32, // How far it reaches, in pixels (world units) radius: f32, // Spot lights: the cone's width in degrees angle: f32, // It stops at occluders shadows: bool,}A light’s settings (SceneNodeData.light; a Light2D’s settings).
struct. Source: lighting.odin:44
Light2D
Section titled “Light2D”Light2D :: struct { // The node part: transform, hierarchy, hooks using node: Node, // Its settings (change them any time) settings: LightSettings,}A scene’s light: see the file’s overview
struct. Source: lighting.odin:63
LightOccluder
Section titled “LightOccluder”LightOccluder :: struct { // The node part: transform, hierarchy, hooks using node: Node, // Rectangle (`size`), Circle (`radius`), Polygon or Segment (`points`); a Capsule is its box shape: CollisionShapeKind, // Rectangle: width and height, centered on the node size: [2]f32, // Circle radius: f32, // Polygon, Segment: points in the node's space points: [dynamic][2]f32,}A shape that stops light: see the file’s overview
struct. Source: lighting.odin:71
SceneLighting
Section titled “SceneLighting”SceneLighting :: struct { // The world layers are lit (dark outside the lights) enabled: bool, // The light everywhere, before the lights ambient: sdl.Color, // Static bodies' shapes cast shadows too bodyShadows: bool, // The light map, made and resized as needed target: ^RenderTarget, // One light at a time is drawn here, then added to the map: its triangles overwrite each other // (added straight to the map, the software renderer lit their shared edges twice: bright seams) scratch: ^RenderTarget,}A scene’s lighting at run time (Scene.lighting)
struct. Source: lighting.odin:85
Procedures
Section titled “Procedures”CreateLight2D
Section titled “CreateLight2D”CreateLight2D :: proc(scene: ^Scene, settings := DEFAULT_LIGHT_SETTINGS) -> ^Light2DCreates a Light2D and adds it to the scene (at the start of the next update).
Inputs
- scene: The scene
- settings: Its settings
Returns
- The light
Example
torch := e.CreateLight2D(scene, {kind = .Point, color = {255, 180, 90, 255}, energy = 1.2, radius = 240, shadows = true})torch.position = {320, 200}e.Scene_SetLighting(scene, true, {20, 22, 34, 255})procedure. Source: lighting.odin:120
CreateLightOccluder
Section titled “CreateLightOccluder”CreateLightOccluder :: proc(scene: ^Scene, size := [2]f32{32, 32}) -> ^LightOccluderCreates a LightOccluder and adds it to the scene (at the start of the next update).
Inputs
- scene: The scene
- size: A rectangle’s width and height, centered on the node
Returns
- The occluder
Example
wall := e.CreateLightOccluder(scene, {40, 120})wall.position = {300, 160}procedure. Source: lighting.odin:144
Scene_SetLighting
Section titled “Scene_SetLighting”Scene_SetLighting :: proc(scene: ^Scene, enabled: bool, ambient := DEFAULT_AMBIENT, bodyShadows := false)Turns a scene’s lighting on or off.
Inputs
- scene: The scene
- enabled: Light the world layers (dark outside the lights)
- ambient: The light everywhere (black: pitch dark)
- bodyShadows: Static bodies’ shapes cast shadows too
Example
e.Scene_SetLighting(scene, true, {10, 10, 20, 255})procedure. Source: lighting.odin:172
Light_Visibility
Section titled “Light_Visibility”Light_Visibility :: proc(light: ^Light2D, allocator := context.allocator) -> [][2]f32What a light reaches: the polygon its light fills, in world coordinates, as seen from its position (occluders’ edges stop it when it has shadows; a spot light’s cone limits it).
Inputs
- light: The light (its scene’s occluders are used)
- allocator: For the points
Returns
- The polygon’s points, around the light in angle order (a spot light’s: from one edge of its cone to the other; the light’s position isn’t included)
procedure. Source: lighting.odin:190
Constants and variables
Section titled “Constants and variables”DEFAULT_LIGHT_SETTINGS
Section titled “DEFAULT_LIGHT_SETTINGS”DEFAULT_LIGHT_SETTINGS :: LightSettings{kind = .Point, color = {255, 240, 220, 255}, energy = 1, radius = 200, angle = 60, shadows = true}A light’s settings when the scene file sets none: a warm white point light
constant. Source: lighting.odin:60
DEFAULT_AMBIENT
Section titled “DEFAULT_AMBIENT”DEFAULT_AMBIENT :: sdl.Color{40, 42, 60, 255}A scene’s ambient light when its file sets none
constant. Source: lighting.odin:100
LIGHT_SEGMENTS
Section titled “LIGHT_SEGMENTS”LIGHT_SEGMENTS :: 48Rays a shadowless point light’s circle is drawn with (and shadowed lights’ edges between)
constant. Source: lighting.odin:103
