Skip to main content

Using the Engine API

Let's build a simple Gaussian splat application step by step using the PlayCanvas Engine directly. We'll create a scene with an interactive 3D toy cat splat that you can rotate around.

Starting Point

Let's set up our project with two files: an HTML file and a JavaScript file.

First, create an index.html file:

index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
body { margin: 0; overflow: hidden; }
</style>
<script type="importmap">
{
"imports": {
"playcanvas": "https://cdn.jsdelivr.net/npm/playcanvas/+esm"
}
}
</script>
</head>
<body>
<script type="module" src="main.js"></script>
</body>
</html>

Next, create a main.js file with the basic PlayCanvas application setup:

main.js
import { Application, Asset, AssetListLoader, Entity, FILLMODE_FILL_WINDOW, RESOLUTION_AUTO } from 'playcanvas';

// Create application
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);

const app = new Application(canvas, {
graphicsDeviceOptions: {
antialias: false
}
});
app.setCanvasFillMode(FILLMODE_FILL_WINDOW);
app.setCanvasResolution(RESOLUTION_AUTO);
app.start();

window.addEventListener('resize', () => app.resizeCanvas());

This creates an empty 3D scene using the Application class with a canvas that:

  • Fills the entire browser window (FILLMODE_FILL_WINDOW)
  • Automatically adjusts resolution based on device pixel ratio (RESOLUTION_AUTO)
  • Properly resizes when the window changes size

We can't see anything rendered yet though - we need to load assets and add a camera and content.

Performance Optimization

We've disabled antialias in the graphics device options for optimal splat rendering performance. This setting helps reduce the fragment processing load, which is the primary bottleneck in Gaussian splat rendering. Learn more in the Performance guide.

Loading Assets

Before we can display a splat or add camera controls, we need to load the assets our app will use. We'll use the Asset class to define our assets and the AssetListLoader to load them efficiently. Add this code to main.js where the comment says "We'll add our code here step by step":

// Load assets
const assets = [
new Asset('camera-controls', 'script', {
url: 'https://cdn.jsdelivr.net/npm/playcanvas/scripts/esm/camera-controls.mjs'
}),
new Asset('toy', 'gsplat', {
url: 'https://developer.playcanvas.com/assets/toy-cat.compressed.ply'
})
];

const loader = new AssetListLoader(assets, app.assets);
await new Promise(resolve => loader.load(resolve));

We're loading two assets:

  • A camera controls script that will let us orbit around the scene
  • A compressed PLY file containing a toy cat splat

The AssetListLoader loads all assets efficiently and we use await to ensure they're fully loaded before proceeding.

Adding a Camera

To view our scene, we need to create a camera entity using the Entity class and add a camera component to it. Add this code to main.js after the asset loading:

// Create camera entity
const camera = new Entity('Camera');
camera.addComponent('camera');
camera.setPosition(0, 0, -2.5);
app.root.addChild(camera);

We've positioned the camera 2.5 units down the negative Z axis. By default, a camera looks down the negative Z axis, so our camera is now looking toward the origin where we'll place our splat.

Adding Camera Controls

Now let's make the camera interactive by attaching the camera controls script using the script component. Add this code to main.js after the camera creation:

// Add camera controls
camera.addComponent('script');
camera.script.create('cameraControls');

Since we've already loaded the camera controls script using AssetListLoader, we can directly create the script component. The camera controls will allow you to:

  • Left mouse drag: Orbit around the target
  • Right mouse drag: Pan the camera
  • Mouse wheel: Zoom in and out

Adding the Splat

Now let's add our toy cat splat to the scene using the gsplat component. Add this code to main.js after the camera controls:

// Create splat entity
const splat = new Entity('Toy Cat');
splat.addComponent('gsplat', { asset: assets[1] });
splat.setPosition(0, -0.7, 0);
splat.setEulerAngles(180, 0, 0);
app.root.addChild(splat);

We reference the splat asset using assets[1] (the second asset in our array). We've positioned the splat slightly below the origin (-0.7 on the Y axis) and rotated it 180 degrees around the X axis to orient it properly.

Complete Code

Here are the complete files with all the code from the steps above:

index.html:

index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
body { margin: 0; overflow: hidden; }
</style>
<script type="importmap">
{
"imports": {
"playcanvas": "https://cdn.jsdelivr.net/npm/playcanvas/+esm"
}
}
</script>
</head>
<body>
<script type="module" src="main.js"></script>
</body>
</html>

main.js:

main.js
import { Application, Asset, AssetListLoader, Entity, FILLMODE_FILL_WINDOW, RESOLUTION_AUTO } from 'playcanvas';

// Create application
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);

const app = new Application(canvas, {
graphicsDeviceOptions: {
antialias: false
}
});
app.setCanvasFillMode(FILLMODE_FILL_WINDOW);
app.setCanvasResolution(RESOLUTION_AUTO);
app.start();

window.addEventListener('resize', () => app.resizeCanvas());

// Load assets
const assets = [
new Asset('camera-controls', 'script', {
url: 'https://cdn.jsdelivr.net/npm/playcanvas/scripts/esm/camera-controls.mjs'
}),
new Asset('toy', 'gsplat', {
url: 'https://developer.playcanvas.com/assets/toy-cat.compressed.ply'
})
];

const loader = new AssetListLoader(assets, app.assets);
await new Promise(resolve => loader.load(resolve));

// Create camera entity
const camera = new Entity('Camera');
camera.addComponent('camera');
camera.addComponent('script');
camera.script.create('cameraControls');
camera.setPosition(0, 0, -2.5);
app.root.addChild(camera);

// Create splat entity
const splat = new Entity('Toy Cat');
splat.addComponent('gsplat', { asset: assets[1] });
splat.setPosition(0, -0.7, 0);
splat.setEulerAngles(180, 0, 0);
app.root.addChild(splat);

Final Result

After completing the steps above, you should see an interactive 3D toy cat splat that you can orbit around, pan, and zoom!

Try it yourself

Create both files above (index.html and main.js) in the same directory and open index.html in your browser to see your first splat app in action! Then extend it in any way you like using the full power of the PlayCanvas Engine!