singe/testScripts/scene21.singe

131 lines
4.6 KiB
Text

-- Point-light shadows inside geometry: two bulbs in a closed room built from ordinary boxes (their
-- faces point outward, so from inside only back faces show), with pillars. One bulb hangs under a
-- cone shade on a stand; the other sits inside a cage of bars and rings. Inside, the walls are lit
-- with no seams, the shade throws its shadow on the ceiling and the cage its stripes across the
-- corners; outside, the room stays dark.
local font = fontLoad("Singe/FreeSansBold.ttf", 28)
local frames = 0
fontSelect(font)
discPlay()
sceneEnable(true)
sceneSetBackground(0, 0, 0, 0)
sceneSetAmbient(8, 8, 12)
local plaster = materialNew()
materialSetColor(plaster, 200, 190, 170)
materialSetRoughness(plaster, 0.95)
materialSetDoubleSided(plaster, true)
local brass = materialNew()
materialSetColor(brass, 180, 140, 70)
materialSetMetallic(brass, 0.7)
materialSetRoughness(brass, 0.4)
materialSetDoubleSided(brass, true)
local glow = materialNew()
materialSetColor(glow, 255, 240, 200)
materialSetEmissive(glow, 255, 230, 170)
materialSetUnlit(glow, true)
-- The room: six slabs 8 x 4 x 8 inside, all outward facing like any box.
local function slab(x, y, z, w, h, d)
local node = nodeNew()
nodeSetMesh(node, meshBox(w, h, d), plaster)
nodeSetPosition(node, x, y, z)
return node
end
slab(0, -0.1, 0, 8.4, 0.2, 8.4)
slab(0, 4.1, 0, 8.4, 0.2, 8.4)
slab(-4.1, 2, 0, 0.2, 4.4, 8.4)
slab(4.1, 2, 0, 0.2, 4.4, 8.4)
slab(0, 2, -4.1, 8.4, 4.4, 0.2)
slab(0, 2, 4.1, 8.4, 4.4, 0.2)
-- Pillars and a crate.
for i, p in ipairs({ { -2.5, -2.5 }, { 2.5, -2.5 }, { -2.5, 2.5 }, { 2.5, 2.5 } }) do
local pillar = nodeNew()
nodeSetMesh(pillar, meshCylinder(0.25, 4, 16), plaster)
nodeSetPosition(pillar, p[1], 2, p[2])
end
local crate = nodeNew()
nodeSetMesh(crate, meshBox(0.8, 0.8, 0.8), brass)
nodeSetPosition(crate, 2.2, 0.4, -1.8)
-- The lamp: a stand, a cone shade above the bulb, which hangs just below its rim so the shade
-- throws a ring of shadow on the ceiling and the bulb lights everything below.
local stand = nodeNew()
nodeSetMesh(stand, meshCylinder(0.04, 1.4, 8), brass)
nodeSetPosition(stand, -0.5, 0.7, -0.3)
local shade = nodeNew()
nodeSetMesh(shade, meshCone(0.45, 0.5, 24), brass)
nodeSetPosition(shade, -0.5, 2.05, -0.3)
local bulbMesh = nodeNew()
nodeSetMesh(bulbMesh, meshSphere(0.08, 12), glow)
nodeSetPosition(bulbMesh, -0.5, 1.55, -0.3)
nodeSetShadow(bulbMesh, false) -- The bulb's own glass casts nothing.
local bulb = lightNew(LIGHT_POINT)
nodeSetPosition(bulb, -0.5, 1.55, -0.3)
lightSetIntensity(bulb, 6)
lightSetShadow(bulb, true)
-- The second lamp: a bulb inside a cage of eight bars and three rings of short segments, its own
-- glass excused from casting. The bars are the harsh case: thin casters right beside the light.
local cx, cy, cz = 2.2, 2.1, 1.6
local function bar(x, y, z, rx, ry, rz, radius, h)
local node = nodeNew()
nodeSetMesh(node, meshCylinder(radius, h, 8), brass)
nodeSetPosition(node, x, y, z)
nodeSetRotation(node, rx, ry, rz)
return node
end
for i = 0, 7 do
local a = i / 8 * 2 * math.pi
bar(cx + 0.35 * math.cos(a), cy, cz + 0.35 * math.sin(a), 0, 0, 0, 0.02, 1.0)
end
for _, dy in ipairs({ -0.5, 0, 0.5 }) do
for i = 0, 7 do
local a = (i + 0.5) / 8 * 2 * math.pi
bar(cx + 0.35 * math.cos(a), cy + dy, cz + 0.35 * math.sin(a), 0, -math.deg(a), 90, 0.015, 0.28)
end
end
local cagedMesh = nodeNew()
nodeSetMesh(cagedMesh, meshSphere(0.06, 12), glow)
nodeSetPosition(cagedMesh, cx, cy, cz)
nodeSetShadow(cagedMesh, false)
local caged = lightNew(LIGHT_POINT)
nodeSetPosition(caged, cx, cy, cz)
lightSetIntensity(caged, 4)
lightSetColor(caged, 255, 230, 190)
lightSetShadow(caged, true)
local camera = nodeNew()
cameraSet(camera)
cameraSetPerspective(70, 0.05, 60)
function onOverlayUpdate()
frames = frames + 1
overlayClear()
if frames < 50 then
-- Inside: from a corner, looking across the room at the shaded lamp, pillars and the far wall.
nodeSetPosition(camera, 3.2 - frames * 0.006, 1.6, -3.2)
nodeLookAt(camera, -1.5, 1.4, 1.5)
elseif frames < 95 then
-- Inside, looking up at the ceiling above the shade.
nodeSetPosition(camera, 1.5, 0.8, -1.5)
nodeLookAt(camera, -0.5, 3.8, -0.3)
elseif frames < 140 then
-- Under the cage, looking up at its stripes running over the ceiling corner.
nodeSetPosition(camera, 1.6, 0.5, 1.0)
nodeLookAt(camera, 3.6, 3.8, 3.6)
else
-- Outside: the closed room from above; nothing of either bulb may leak out.
nodeSetPosition(camera, 9, 7, 9)
nodeLookAt(camera, 0, 1.5, 0)
end
fontPrint(20, 20, "Bulbs in a room, frame " .. frames)
if frames == 40 or frames == 85 or frames == 130 or frames == 175 then
singeScreenshot()
end
if frames == 180 then
singeQuit()
end
end