Start here
Getting started
Run the island locally, build the static site, and run the headless GPU test. You need Node 18 or later and a browser with WebGL2.
#Install
cd naturegl-island
npm installThe only dependencies are three (^0.186), vite and playwright-core (for the test scripts). The four NatureGL libraries are already in lib/ as prebuilt bundles, so there is nothing else to install. See sync-libs and lib/ if you want to refresh them.
#Start the dev server
npm run dev # http://localhost:5188/demo/Vite opens /demo/ on port 5188. The page shows Loading the island… while it builds the terrain, sky, ocean, grass, vegetation and village, then a Click to explore card. Click it to lock the pointer and start walking.
#Pick a starting point and a tier
Add query parameters to the URL:
| Parameter | Effect |
|---|---|
?scenario=pier-sunset | Start at one of the eleven scenarios. The default is village-day. |
?quality=low | Pick a quality tier: low, medium, high (default) or ultra. |
?skypost | Run NatureGL Sky's post pass over NatureGL Water's HDR render. Off by default; see Composing the libraries. |
?smoke | Automation mode: no start card and no scenario applied. The test scripts use it. |
#Build the static site
npm run build # vite build → dist/
npm run preview # serve dist/ on port 5188dist/index.html is a small landing page with links; the game itself is dist/demo/index.html. The build uses a relative base (./), so dist/ works from any folder or sub-path.
#Run the smoke test
npm testThis starts Vite, opens demo/?smoke in Chromium on the real GPU, loads every scenario, saves test-results/<scenario>.png and prints the fps. It fails on any page error, console error or failed request. See Scenarios and automation.
#Put the game in your own page
demo/main.js is the whole page. It creates a renderer, hands it to IslandGame, adds the Hud and runs the loop:
import * as THREE from 'three';
import { IslandGame, Hud } from 'naturegl-island';
const renderer = new THREE.WebGLRenderer({ antialias: false, powerPreference: 'high-performance' });
renderer.setPixelRatio(1);
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
const game = await IslandGame.create({
renderer,
quality: 'high',
assetsUrl: new URL('../', document.baseURI).href, // where models/pirate-kit/ lives
onProgress: msg => console.log(msg),
});
game.resize(innerWidth, innerHeight);
game.applyScenario('village-day');
const hud = new Hud(game, { weather: game.rain });
const timer = new THREE.Timer();
renderer.setAnimationLoop(t => {
timer.update(t);
const dt = timer.getDelta();
game.update(dt);
game.render();
hud.update(dt);
});
addEventListener('resize', () => {
renderer.setSize(innerWidth, innerHeight);
game.resize(innerWidth, innerHeight);
});#Scripts
| Script | Does |
|---|---|
npm run dev | Vite dev server on port 5188, opens /demo/ |
npm run build | Static build into dist/ |
npm run preview | Serves dist/ |
npm test | Headless GPU smoke test over every scenario (scripts/smoke.mjs) |
npm run sync-libs | Copies ../naturegl-{sky,water,grass,weather}/build into lib/ |
npm run sync-libs:rebuild | Runs npm run build:lib in each library first, then copies |
node scripts/shot.mjs | Screenshots scenarios to test-results/shots/ without the error gate |
node scripts/play-test.mjs | Scripted gameplay check with real key presses, screenshots to test-results/play/ |