Lighting

Every scene3d scene starts with a default ambient light — it illuminates everything equally. That’s fine for seeing shapes, but it’s flat and lifeless.

Real lighting shapes how a scene feels. Dimming the world and adding a warm spotlight creates atmosphere. Colored lights can suggest fire, moonlight, or neon. A moving light casts shifting illumination that brings a scene to life.

In this notebook you’ll learn how to control the ambient light, add point lights, use color, and animate lights for dynamic effects.

Open In Jupyter K-12

The Ambient Light

Every scene starts with a hemispheric ambient light that shines evenly on every surface. scene.ambient lets you adjust its brightness and color.

Brightness runs from 0 to 100. The default is 90 — nearly full. Dropping it to 20 or 30 creates a darker, more atmospheric scene.

Use the slider to see how brightness changes the mood.

import scene3d

BRIGHTNESS = 40 #@param {type:"slider", min:0, max:100, step:5}

scene = scene3d.Scene()
scene.set_sky('#0f3460')
ground = scene.set_ground(length=12, width=12)
ground.set_material(scene3d.Material.Gravel.DarkGray)
ground.set_tiling(4)

for x, color in [(-3, '#e94560'), (0, '#f5a623'), (3, '#44cc88')]:
  s = scene3d.Shapes.Sphere(diameter=1.2, segments=16)
  s.set_color(color)
  s.set_position(x, 0.6, 0)
  scene.add(s)

scene.ambient.set_brightness(BRIGHTNESS)

Ambient Color — Setting the Mood

scene.ambient.set_color() tints the whole scene with a color. Combined with a low brightness, this is how you create distinct moods: a warm orange sunset, a cold blue moonlit night, a dim underground cavern.

The dropdown below switches between preset moods — notice how both color and brightness work together to create the effect.

import scene3d

MOOD = 'sunset' #@param ["daylight", "sunset", "moonlight", "underground"]

moods = {
  'daylight':    ('#ffffff', 90),
  'sunset':      ('#ff9955', 55),
  'moonlight':   ('#aabbff', 25),
  'underground': ('#334422', 18),
}
color, brightness = moods[MOOD]

scene = scene3d.Scene()
scene.set_sky('#1a1a2e')
ground = scene.set_ground(length=14, width=14)
ground.set_material(scene3d.Material.Gravel.DarkGray)
ground.set_tiling(4)

for x, z in [(-3, 0), (0, 0), (3, 0), (-1.5, 3), (1.5, 3)]:
  b = scene3d.Shapes.Box(width=1.2, height=1.2, depth=1.2)
  b.set_material(scene3d.Material.Marble.Gray)
  b.set_position(x, 0.6, z)
  scene.add(b)

scene.ambient.set_color(color)
scene.ambient.set_brightness(brightness)

{ “question_type”: “true_false”, “question”: “scene.ambient.set_brightness(0) makes the scene completely dark.”, “answer”: “True”, “submitted_answer”: “” }

Adding a Point Light

A point light shines in all directions from a single position in space — like a light bulb. scene.add_light(x, y, z) creates one and returns a Light object you can configure.

light = scene.add_light(0, 5, 0)   # light directly overhead
light.set_brightness(80)           # 0–100 scale
light.set_visible(True)            # show a glowing marker at the light's position

To see exactly where your light is while setting it up, call light.set_visible(True) — it places a small glowing sphere at the light’s position.

The scene below dims the ambient light so the point light stands out. Run it and look for the marker.

import scene3d

scene = scene3d.Scene()
scene.set_sky('#1a1a2e')
ground = scene.set_ground(length=14, width=14)
ground.set_material(scene3d.Material.Gravel.DarkGray)
ground.set_tiling(4)

# Dim the ambient light so the point light makes a visible difference
scene.ambient.set_brightness(15)

for x, color in [(-3, '#e94560'), (0, '#f5a623'), (3, '#44cc88')]:
  s = scene3d.Shapes.Sphere(diameter=1.2, segments=16)
  s.set_color(color)
  s.set_position(x, 0.6, 0)
  scene.add(s)

# Point light overhead — set_visible shows its position as a glowing sphere
light = scene.add_light(0, 6, 0)
light.set_brightness(100)
light.set_visible(True)

set_visible — Your Positioning Tool

The glowing indicator sphere sits exactly where the light is — so you can see if it’s in the right spot. Hide it when you’re happy with the result:

light.set_visible(True)   # show while building — does the light land where you expect?
light.set_visible(False)  # hide for the final scene

set_visible only affects the indicator. The light itself — its brightness, color, and influence on every surface — stays exactly the same either way.

Try changing set_visible(True) to set_visible(False) in the cell above and re-running.

{ “question_type”: “multiple_choice”, “question”: “What does light.set_visible(True) do?”, “options”: [ { “key”: “a”, “text”: “Turns the light on” }, { “key”: “b”, “text”: “Shows a small glowing sphere at the light’s position” }, { “key”: “c”, “text”: “Makes the light only affect visible meshes” }, { “key”: “d”, “text”: “Makes the light pulse on and off” } ], “answer”: “b”, “submitted_answer”: “” }

Light Color

Point lights can be any color. The light color mixes with the surface colors beneath it: a red light on a blue sphere produces a very different result than white light.

Using a neutral gray material (like marble) makes the color effect clearest — the surface has no bias, so it reflects whatever color the light brings.

Use the dropdown to try different light colors on the same gray surfaces.

import scene3d

LIGHT_COLOR = '#ff8844' #@param ["#ffffff", "#ff8844", "#4488ff", "#ff3300", "#44ff88", "#ffff44"]

scene = scene3d.Scene()
scene.set_sky('#1a1a2e')
ground = scene.set_ground(length=14, width=14)
ground.set_material(scene3d.Material.Gravel.DarkGray)
ground.set_tiling(4)

scene.ambient.set_brightness(10)

box = scene3d.Shapes.Box(width=1.5, height=1.5, depth=1.5)
box.set_material(scene3d.Material.Marble.Gray)
box.set_position(-2, 0.75, 0)
scene.add(box)

sphere = scene3d.Shapes.Sphere(diameter=1.4, segments=24)
sphere.set_material(scene3d.Material.Marble.Gray)
sphere.set_position(2, 0.7, 0)
scene.add(sphere)

light = scene.add_light(0, 5, -2)
light.set_color(LIGHT_COLOR)
light.set_brightness(100)
light.set_visible(True)

{ “question_type”: “multiple_choice”, “question”: “A gray marble sphere is lit only by a pure red point light (ambient brightness = 0). What color does the sphere appear?”, “options”: [ { “key”: “a”, “text”: “Gray, because the material color overrides the light” }, { “key”: “b”, “text”: “Black, because the sphere absorbs red light” }, { “key”: “c”, “text”: “Red, because the light color tints the surface” }, { “key”: “d”, “text”: “White, because marble is always white” } ], “answer”: “c”, “submitted_answer”: “” }

Animated Lights

Lights can move just like meshes. Call light.set_position(x, y, z) inside @scene.on_frame to sweep light across a scene, simulate a torch flickering around a room, or orbit a spotlight.

The scene below has a warm light orbiting a cluster of gray boxes. Watch how the lit faces shift as the light sweeps around. Click Stop (■) when you’re done.

import scene3d
import math

scene = scene3d.Scene()
scene.set_sky('#1a1a2e')
ground = scene.set_ground(length=14, width=14)
ground.set_material(scene3d.Material.Gravel.DarkGray)
ground.set_tiling(4)

scene.ambient.set_brightness(10)

for x, z in [(-3, 0), (0, 0), (3, 0), (-1.5, 3), (1.5, 3)]:
  b = scene3d.Shapes.Box(width=1.2, height=1.2, depth=1.2)
  b.set_material(scene3d.Material.Marble.Gray)
  b.set_position(x, 0.6, z)
  scene.add(b)

light = scene.add_light(0, 4, 0)
light.set_color('#ff8844')
light.set_brightness(100)
light.set_visible(True)

t = 0.0

@scene.on_frame
def animate(dt):
  global t
  t += dt
  x = math.sin(t) * 5
  z = math.cos(t) * 4
  light.set_position(x, 4, z)

scene.run()

{ “question_type”: “multiple_choice”, “question”: “To make a point light orbit around the scene, you would:”, “options”: [ { “key”: “a”, “text”: “Call scene.add_light() multiple times per frame” }, { “key”: “b”, “text”: “Call light.set_position() each frame using math.sin and math.cos” }, { “key”: “c”, “text”: “Call scene.camera.follow(light)” }, { “key”: “d”, “text”: “Call light.set_visible(True) each frame” } ], “answer”: “b”, “submitted_answer”: “” }

Try It Yourself

Build a scene lit by two colored point lights. Use the sliders and dropdowns to experiment with brightness, colors, and height. Try combining a warm color and a cool color and see how they blend on the same neutral surfaces.

import scene3d

AMBIENT      =  10 #@param {type:"slider", min:0, max:60, step:5}
LIGHT1_COLOR = '#ff8844' #@param ["#ffffff", "#ff8844", "#4488ff", "#ff3300", "#44ff88", "#ffff44"]
LIGHT2_COLOR = '#4488ff' #@param ["#ffffff", "#ff8844", "#4488ff", "#ff3300", "#44ff88", "#ffff44"]
LIGHT_HEIGHT =   5 #@param {type:"slider", min:2, max:12, step:1}

scene = scene3d.Scene()
scene.set_sky('#1a1a2e')
ground = scene.set_ground(length=14, width=14)
ground.set_material(scene3d.Material.Gravel.DarkGray)
ground.set_tiling(4)

scene.ambient.set_brightness(AMBIENT)

for x, z in [(-3, 0), (0, 0), (3, 0), (-1.5, 3), (1.5, 3)]:
  b = scene3d.Shapes.Box(width=1.2, height=1.2, depth=1.2)
  b.set_material(scene3d.Material.Marble.Gray)
  b.set_position(x, 0.6, z)
  scene.add(b)

light1 = scene.add_light(-4, LIGHT_HEIGHT, 0)
light1.set_color(LIGHT1_COLOR)
light1.set_visible(True)

light2 = scene.add_light(4, LIGHT_HEIGHT, 0)
light2.set_color(LIGHT2_COLOR)
light2.set_visible(True)

Think about a scene you’d like to create where lighting tells a story — a torch in a dungeon, a neon-lit city street at night, a campfire in a clearing.

What colors would you use for the lights? How bright would the ambient light be? Would the lights be still or moving? Describe the atmosphere you want to create and how you’d use scene.ambient and scene.add_light to achieve it.