-- Culling and instancing: a field of dragons on a plain. Every dragon is the same model, so -- its parts batch into a handful of instanced draw calls, and the camera looks along the field so -- most of them are behind it and culled. The overlay shows what sceneGetStats reports and the -- frame time, so the sheet doubles as the measurement. local font = fontLoad("Singe/FreeSansBold.ttf", 28) local frames = 0 local last = singeGetTicks() local ms = 0 fontSelect(font) sceneEnable(true) sceneSetSky("testScripts/sky.png") sceneSetFog(190, 200, 215, 60, 220) sceneSetShadowSize(2048) sceneSetShadowDistance(80) local ground = materialNew() materialSetColor(ground, 110, 120, 90) materialSetRoughness(ground, 0.95) local plain = nodeNew() nodeSetMesh(plain, meshPlane(400, 400), ground) local dragonModel = modelLoad("testScripts/Models/DragonModel.glb") local across = 20 local count = 0 for i = 0, across - 1 do for j = 0, across - 1 do local dragon = modelInstance(dragonModel) nodeSetPosition(dragon, (i - across / 2) * 6, 0, (j - across / 2) * 6) nodeSetRotation(dragon, 0, (i * 7 + j * 13) % 360, 0) nodeSetScale(dragon, 0.35) count = count + 1 end end local sun = lightNew(LIGHT_DIRECTIONAL) nodeSetPosition(sun, 40, 60, 30) nodeLookAt(sun, 0, 0, 0) lightSetIntensity(sun, 2.5) lightSetShadow(sun, true) local camera = nodeNew() cameraSet(camera) cameraSetPerspective(60, 0.1, 400) local stops = { { 0, 4, 130, 0, 2, 0 }, -- From the edge, looking across the field { 0, 60, 0, 0, 0, -140 }, -- High above, half the field in view { 3, 2, 3, -40, 3, -40 }, -- In among them, low { 0, 200, 1, 0, 0, 0 }, -- Straight down: everything in view } function onOverlayUpdate() local stop = stops[math.min(#stops, math.floor(frames / 45) + 1)] local now = singeGetTicks() frames = frames + 1 ms = ms * 0.9 + (now - last) * 0.1 last = now nodeSetPosition(camera, stop[1], stop[2], stop[3]) nodeLookAt(camera, stop[4], stop[5], stop[6]) local total, drawn, batches = sceneGetStats() overlayClear() fontPrint(20, 20, string.format("%d dragons: %d draws, %d in view, %d draw calls, %.1f ms, frame %d", count, total, drawn, batches, ms, frames)) if frames == 40 or frames == 85 or frames == 130 or frames == 175 then singeScreenshot() debugPrint(string.format("frame %d draws %d in view %d calls %d ms %.1f", frames, total, drawn, batches, ms)) end if frames == 180 then singeQuit() end end