129 lines
4.7 KiB
Text
129 lines
4.7 KiB
Text
-- The Khronos Sponza atrium, packed with util/packGlb.py from the glTF-Sample-Models 2.0 Sponza.
|
|
-- A warm sun falls through the roof opening onto the atrium floor with cascaded shadows, the sky lights
|
|
-- the stone from above in place of a flat ambient, a breath of haze softens the far end of the nave,
|
|
-- braziers along the nave add pools of firelight with particle flames and smoke, each crackling from
|
|
-- where it stands (the listener is the camera), dust drifts in the sunbeams, and the frame is graded
|
|
-- through the ACES curve; the camera walks the ground floor, crosses the atrium, climbs to the
|
|
-- gallery, then passes the columns.
|
|
local font = fontLoad("Singe/FreeSansBold.ttf", 28)
|
|
local frames = 0
|
|
|
|
fontSelect(font)
|
|
sceneEnable(true)
|
|
sceneSetBackground(120, 150, 200, 255)
|
|
sceneSetAmbient(120, 126, 150)
|
|
sceneSetShadowSize(2048)
|
|
sceneSetShadowCascades(4)
|
|
sceneSetShadowDistance(40)
|
|
sceneSetBloom(1.2, 0.25)
|
|
sceneSetSky("testScripts/sky.png")
|
|
sceneSetSkyIntensity(0.35)
|
|
sceneSetFog(200, 205, 215, 35, 140)
|
|
sceneSetTonemap(TONEMAP_ACES)
|
|
|
|
local model = modelLoad("testScripts/Models/Sponza.glb")
|
|
local sponza = modelInstance(model)
|
|
|
|
-- The sun: high and warm so it falls through the roof opening onto the atrium floor.
|
|
local sun = lightNew(LIGHT_DIRECTIONAL)
|
|
nodeSetPosition(sun, 5, 22, 4)
|
|
nodeLookAt(sun, -2, 0, -1.5)
|
|
lightSetIntensity(sun, 4.5)
|
|
lightSetColor(sun, 255, 236, 205)
|
|
lightSetShadow(sun, true)
|
|
|
|
-- Braziers: warm point lights along the nave, the two nearest the camera path casting shadows,
|
|
-- each with a flame and a thread of smoke.
|
|
local fire = materialNew()
|
|
materialSetColor(fire, 60, 40, 30)
|
|
local crackle = soundLoad("testScripts/crackle.wav")
|
|
local braziers = {}
|
|
for i, p in ipairs({ { 6.5, 1.1, -2.2 }, { 6.5, 1.1, 2.2 }, { -6.5, 1.1, -2.2 }, { -6.5, 1.1, 2.2 }, { 0, 1.1, -2.4 }, { 0, 1.1, 2.4 } }) do
|
|
local bowl = nodeNew()
|
|
nodeSetMesh(bowl, meshCylinder(0.35, 0.25, 12), fire)
|
|
nodeSetPosition(bowl, p[1], p[2] - 0.15, p[3])
|
|
local glowNode = nodeNew()
|
|
nodeSetPosition(glowNode, p[1], p[2] + 0.35, p[3])
|
|
local lamp = lightNew(LIGHT_POINT)
|
|
nodeSetParent(lamp, glowNode)
|
|
lightSetColor(lamp, 255, 170, 80)
|
|
lightSetIntensity(lamp, 6)
|
|
lightSetRange(lamp, 12)
|
|
lightSetShadow(lamp, i <= 2)
|
|
local flame = emitterNew(glowNode)
|
|
emitterSetBlend(flame, PARTICLE_ADD)
|
|
emitterSetRate(flame, 60)
|
|
emitterSetLife(flame, 0.4, 0.8)
|
|
emitterSetSpeed(flame, 0.5, 1.1)
|
|
emitterSetDirection(flame, 0, 1, 0)
|
|
emitterSetSpread(flame, 18)
|
|
emitterSetSize(flame, 0.22, 0.04, 0.15)
|
|
emitterSetColor(flame, 255, 190, 90, 255, 255, 60, 0, 0)
|
|
emitterSetRadius(flame, 0.1)
|
|
emitterStart(flame)
|
|
local smoke = emitterNew(glowNode)
|
|
emitterSetRate(smoke, 12)
|
|
emitterSetLife(smoke, 2.5, 4)
|
|
emitterSetSpeed(smoke, 0.4, 0.7)
|
|
emitterSetDirection(smoke, 0, 1, 0)
|
|
emitterSetSpread(smoke, 12)
|
|
emitterSetSize(smoke, 0.15, 0.8, 0.15)
|
|
emitterSetColor(smoke, 90, 80, 75, 90, 50, 45, 45, 0)
|
|
emitterSetSpin(smoke, -25, 25)
|
|
emitterSetLit(smoke, true)
|
|
emitterSetSoftness(smoke, 0.4)
|
|
emitterStart(smoke)
|
|
local channel = soundPlay(crackle, -1)
|
|
if channel >= 0 then
|
|
soundSetNode(channel, glowNode)
|
|
soundSetRange(channel, 1.5, 14)
|
|
end
|
|
braziers[i] = glowNode
|
|
end
|
|
|
|
-- Dust in the sunbeams over the atrium floor.
|
|
local air = nodeNew()
|
|
nodeSetPosition(air, 0, 3, 0)
|
|
local dust = emitterNew(air)
|
|
emitterSetRate(dust, 40)
|
|
emitterSetLife(dust, 5, 8)
|
|
emitterSetSpeed(dust, 0.05, 0.25)
|
|
emitterSetSpread(dust, 180)
|
|
emitterSetSize(dust, 0.05, 0.05)
|
|
emitterSetColor(dust, 255, 240, 210, 0, 255, 240, 210, 190)
|
|
emitterSetRadius(dust, 5)
|
|
emitterSetMax(dust, 400)
|
|
emitterStart(dust)
|
|
emitterBurst(dust, 300)
|
|
|
|
local camera = nodeNew()
|
|
cameraSet(camera)
|
|
cameraSetPerspective(65, 0.05, 100)
|
|
|
|
local stops = {
|
|
{ 10, 1.6, 0, -10, 2.5, 0 }, -- Ground floor, along the nave past the braziers
|
|
{ 1.2, 1.6, 5.2, -1, 3.5, -5 }, -- Across the atrium toward the far arcade
|
|
{ -9, 5.5, -1, 6, 3, 1 }, -- From the upper gallery
|
|
{ 5, 1.2, -1.5, -8, 2, 1.5 }, -- Low, past the columns and a brazier
|
|
}
|
|
|
|
function onOverlayUpdate()
|
|
local stop = stops[math.min(#stops, math.floor(frames / 45) + 1)]
|
|
frames = frames + 1
|
|
nodeSetPosition(camera, stop[1], stop[2], stop[3])
|
|
nodeLookAt(camera, stop[4], stop[5], stop[6])
|
|
overlayClear()
|
|
fontPrint(20, 20, "Sponza, frame " .. frames)
|
|
if frames == 40 or frames == 85 or frames == 130 or frames == 175 then
|
|
singeScreenshot()
|
|
local total, drawn, calls, textureKB = sceneGetStats()
|
|
debugPrint(string.format("frame %d draws %d in view %d calls %d texture %d KB", frames, total, drawn, calls, textureKB))
|
|
for channel = 0, 5 do
|
|
local x, y, z, gain = soundGetPosition(channel)
|
|
debugPrint(string.format("frame %d brazier channel %d at %.1f %.1f %.1f gain %.2f", frames, channel, x, y, z, gain))
|
|
end
|
|
end
|
|
if frames == 180 then
|
|
singeQuit()
|
|
end
|
|
end
|