使用引擎 API
直接使用 PlayCanvas 引擎,逐步创建一个可交互环绕的 3D 玩具猫场景。
起点
创建 HTML 和 JavaScript 两个文件。
先创建 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());
这用 Application 创建空 3D 场景,画布:
- 填满浏览器窗口(FILLMODE_FILL_WINDOW)。
- 按设备像素比自动调整分辨率(RESOLUTION_AUTO)。
- 窗口变化时正确调整大小。
此时仍无可见内容,需要加载资源、添加相机和场景。
性能优化
为优化性能,在图形设备选项禁用 antialias,减少片元处理负载,这是高斯泼溅的主要瓶颈。参见性能。
加载资源
显示内容或添加相机控制前,先加载资源。使用 Asset 定义资源,AssetListLoader 高效加载。在 main.js 的“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.sog'
})
];
const loader = new AssetListLoader(assets, app.assets);
await new Promise(resolve => loader.load(resolve));
加载两个资源:
- 支持环绕场景的相机控制脚本。
- 玩具猫 .sog 文件。
AssetListLoader 高效加载全部资源,await 确保加载完成后再继续。
添加相机
通过 Entity 创建实体并添加相机组件。在加载代码后添加:
// Create camera entity
const camera = new Entity('Camera');
camera.setPosition(0, 0, 2.5);
camera.addComponent('camera');
app.root.addChild(camera);
相机位于 Z 轴正方向 2.5 单位。默认沿负 Z 观察,因此朝向稍后放置场景的原点。
添加相机控制
通过脚本组件附加控制脚本,使相机可交互。在创建相机后添加:
// Add camera controls
camera.addComponent('script');
camera.script.create('cameraControls');
脚本已由 AssetListLoader 加载,因此可直接创建组件。支持:
- 左键拖动:环绕目标。
- 中键拖动:平移相机。
- 滚轮:缩放。
添加高斯泼溅
通过 gsplat 组件添加玩具猫,在相机控制后添加:
// Create splat entity
const splat = new Entity('Toy Cat');
splat.setPosition(0, -0.7, 0);
splat.setEulerAngles(0, 0, 180);
splat.addComponent('gsplat', { asset: assets[1] });
app.root.addChild(splat);
assets[1] 引用数组第二个资源。位置在原点稍下方,Y 为 -0.7,并绕 Z 转 180 度以调整正确朝向。
完整代码
包含以上所有步骤的完整文件:
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.sog'
})
];
const loader = new AssetListLoader(assets, app.assets);
await new Promise(resolve => loader.load(resolve));
// Create camera entity
const camera = new Entity('Camera');
camera.setPosition(0, 0, 2.5);
camera.addComponent('camera');
camera.addComponent('script');
camera.script.create('cameraControls');
app.root.addChild(camera);
// Create splat entity
const splat = new Entity('Toy Cat');
splat.setPosition(0, -0.7, 0);
splat.setEulerAngles(0, 0, 180);
splat.addComponent('gsplat', { asset: assets[1] });
app.root.addChild(splat);
最终结果
完成后,应看到可以环绕、平移和缩放的交互式 3D 玩具猫。
动手试试
将两个文件放入同一目录,在浏览器打开 index.html 查看首个应用,再使用引擎完整能力继续扩展。