NatureGL Islandv1.1.0

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

bash
cd naturegl-island
npm install

The 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

bash
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:

ParameterEffect
?scenario=pier-sunsetStart at one of the eleven scenarios. The default is village-day.
?quality=lowPick a quality tier: low, medium, high (default) or ultra.
?skypostRun NatureGL Sky's post pass over NatureGL Water's HDR render. Off by default; see Composing the libraries.
?smokeAutomation mode: no start card and no scenario applied. The test scripts use it.

#Build the static site

bash
npm run build      # vite build → dist/
npm run preview    # serve dist/ on port 5188

dist/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

bash
npm test

This 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:

demo/main.js (shortened)
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

ScriptDoes
npm run devVite dev server on port 5188, opens /demo/
npm run buildStatic build into dist/
npm run previewServes dist/
npm testHeadless GPU smoke test over every scenario (scripts/smoke.mjs)
npm run sync-libsCopies ../naturegl-{sky,water,grass,weather}/build into lib/
npm run sync-libs:rebuildRuns npm run build:lib in each library first, then copies
node scripts/shot.mjsScreenshots scenarios to test-results/shots/ without the error gate
node scripts/play-test.mjsScripted gameplay check with real key presses, screenshots to test-results/play/