diff --git a/examples/index.html b/examples/index.html
index 7abca21f73e..d5201213f36 100644
--- a/examples/index.html
+++ b/examples/index.html
@@ -158,6 +158,7 @@
Examples
Anchor (Mixed Reality)
Real World Meshing (Mixed Reality)
Importmap (import teapot geometry from three/addons)
+ WebGPU renderer and TSL
Examples from Documentation
diff --git a/examples/showcase/webgpu/index.html b/examples/showcase/webgpu/index.html
new file mode 100644
index 00000000000..b389908cf36
--- /dev/null
+++ b/examples/showcase/webgpu/index.html
@@ -0,0 +1,107 @@
+
+
+
+
+ WebGPURenderer and TSL • A-Frame
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/showcase/webgpu/message.html b/examples/showcase/webgpu/message.html
new file mode 100644
index 00000000000..f1c80a60ae1
--- /dev/null
+++ b/examples/showcase/webgpu/message.html
@@ -0,0 +1,7 @@
+
+ Galaxy
+
+ Based on
+ Three.js Journey
+ lessons
+
diff --git a/package.json b/package.json
index d5da1bf704f..c90b4ff9cd8 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,7 @@
"prerelease": "node scripts/release.js 1.5.0 1.6.0",
"start": "npm run dev",
"start:https": "npm run dev -- --server-type https",
+ "start:webgpu": "cross-env WEBGPU=true npm run dev -- --server-type https",
"test": "karma start ./tests/karma.conf.js",
"test:docs": "node scripts/docsLint.js",
"test:firefox": "npm test -- --browsers Firefox",
diff --git a/src/core/a-node.js b/src/core/a-node.js
index fd23571b191..5c53c9e3971 100644
--- a/src/core/a-node.js
+++ b/src/core/a-node.js
@@ -14,8 +14,8 @@ export var knownTags = {
'a-entity': true
};
-function isNode (node) {
- return node.tagName.toLowerCase() in knownTags || node.isNode;
+function isANode (node) {
+ return node.tagName.toLowerCase() in knownTags || node.isANode;
}
/**
@@ -29,7 +29,7 @@ export class ANode extends HTMLElement {
super();
this.computedMixinStr = '';
this.hasLoaded = false;
- this.isNode = true;
+ this.isANode = true;
this.mixinEls = [];
}
@@ -119,7 +119,7 @@ export class ANode extends HTMLElement {
if (this.hasLoaded) { return; }
// Default to waiting for all nodes.
- childFilter = childFilter || isNode;
+ childFilter = childFilter || isANode;
// Wait for children to load (if any), then load.
children = this.getChildren();
childrenLoaded = children.filter(childFilter).map(function (child) {
diff --git a/src/core/scene/a-scene.js b/src/core/scene/a-scene.js
index 49e2d6701e9..1144fac3cc1 100644
--- a/src/core/scene/a-scene.js
+++ b/src/core/scene/a-scene.js
@@ -547,7 +547,10 @@ export class AScene extends AEntity {
};
}
- renderer = this.renderer = new THREE.WebGLRenderer(rendererConfig);
+ renderer = this.renderer = new (THREE.WebGLRenderer || THREE.WebGPURenderer)(rendererConfig);
+ if (!renderer.xr.setPoseTarget) {
+ renderer.xr.setPoseTarget = function () {};
+ }
renderer.setPixelRatio(window.devicePixelRatio);
if (this.camera) { renderer.xr.setPoseTarget(this.camera.el.object3D); }
diff --git a/src/shaders/msdf.js b/src/shaders/msdf.js
index c638ca5c8aa..0d41e741055 100644
--- a/src/shaders/msdf.js
+++ b/src/shaders/msdf.js
@@ -1,5 +1,7 @@
import { registerShader } from '../core/shader.js';
import THREE from '../lib/three.js';
+import { UniformsUtils } from 'three/src/renderers/shaders/UniformsUtils.js';
+import { UniformsLib } from 'three/src/renderers/shaders/UniformsLib.js';
var VERTEX_SHADER = [
'#include ',
@@ -84,8 +86,8 @@ export var Shader = registerShader('msdf', {
fragmentShader: FRAGMENT_SHADER,
init: function () {
- this.uniforms = THREE.UniformsUtils.merge([
- THREE.UniformsLib.fog,
+ this.uniforms = UniformsUtils.merge([
+ UniformsLib.fog,
this.initUniforms()
]);
this.material = new THREE.ShaderMaterial({
diff --git a/src/shaders/sdf.js b/src/shaders/sdf.js
index 9e03dbcb972..e8a5e85d77e 100644
--- a/src/shaders/sdf.js
+++ b/src/shaders/sdf.js
@@ -1,5 +1,7 @@
import { registerShader } from '../core/shader.js';
import THREE from '../lib/three.js';
+import { UniformsUtils } from 'three/src/renderers/shaders/UniformsUtils.js';
+import { UniformsLib } from 'three/src/renderers/shaders/UniformsLib.js';
var VERTEX_SHADER = [
'#include ',
@@ -94,8 +96,8 @@ export var Shader = registerShader('sdf', {
fragmentShader: FRAGMENT_SHADER,
init: function () {
- this.uniforms = THREE.UniformsUtils.merge([
- THREE.UniformsLib.fog,
+ this.uniforms = UniformsUtils.merge([
+ UniformsLib.fog,
this.initUniforms()
]);
this.material = new THREE.ShaderMaterial({
diff --git a/src/systems/camera.js b/src/systems/camera.js
index 4c00ada75c8..d4615a4f44e 100755
--- a/src/systems/camera.js
+++ b/src/systems/camera.js
@@ -59,7 +59,7 @@ export var System = registerSystem('camera', {
});
// Load camera and wait for camera to initialize.
- if (cameraEls[i].isNode) {
+ if (cameraEls[i].isANode) {
cameraEls[i].load();
} else {
cameraEls[i].addEventListener('nodeready', function () {
diff --git a/tests/core/a-entity.test.js b/tests/core/a-entity.test.js
index 13eddfff21e..284173e65dc 100644
--- a/tests/core/a-entity.test.js
+++ b/tests/core/a-entity.test.js
@@ -37,7 +37,7 @@ suite('a-entity', function () {
});
test('createdCallback', function () {
- assert.ok(el.isNode);
+ assert.ok(el.isANode);
assert.ok(el.isEntity);
});
@@ -669,9 +669,9 @@ suite('a-entity', function () {
el.appendChild(a);
el.appendChild(b);
setTimeout(function () {
- a.isNode = false;
+ a.isANode = false;
a.hasLoaded = false;
- b.isNode = false;
+ b.isANode = false;
b.hasLoaded = false;
el.hasLoaded = false;
el.addEventListener('loaded', function () {
@@ -697,9 +697,9 @@ suite('a-entity', function () {
el.appendChild(a);
el.appendChild(b);
setTimeout(function () {
- a.isNode = false;
+ a.isANode = false;
a.hasLoaded = false;
- b.isNode = false;
+ b.isANode = false;
b.hasLoaded = false;
el.hasLoaded = false;
el.addEventListener('loaded', function () {
diff --git a/tests/core/scene/a-scene.test.js b/tests/core/scene/a-scene.test.js
index 75f51f587e0..e1803177549 100644
--- a/tests/core/scene/a-scene.test.js
+++ b/tests/core/scene/a-scene.test.js
@@ -76,7 +76,9 @@ suite('a-scene (without renderer) - WebXR', function () {
// Mock renderer.
assert.ok(sceneEl.renderer);
// Mock renderer is not a real WebGLRenderer.
- assert.notOk(sceneEl.renderer instanceof THREE.WebGLRenderer);
+ assert.notOk(
+ (THREE.WebGLRenderer && sceneEl.renderer instanceof THREE.WebGLRenderer) ||
+ (THREE.WebGPURenderer && sceneEl.renderer instanceof THREE.WebGPURenderer));
});
});
diff --git a/vendor/rStats.extras.js b/vendor/rStats.extras.js
index 56c87e5182b..3d3b8306773 100644
--- a/vendor/rStats.extras.js
+++ b/vendor/rStats.extras.js
@@ -138,7 +138,7 @@ window.threeStats = function ( renderer ) {
function _update () {
_rS( 'renderer.info.memory.geometries' ).set( renderer.info.memory.geometries );
- _rS( 'renderer.info.programs' ).set( renderer.info.programs.length );
+ _rS( 'renderer.info.programs' ).set( renderer.info.programs?.length ?? NaN );
_rS( 'renderer.info.memory.textures' ).set( renderer.info.memory.textures );
_rS( 'renderer.info.render.calls' ).set( renderer.info.render.calls );
_rS( 'renderer.info.render.triangles' ).set( renderer.info.render.triangles );
diff --git a/webpack.common.cjs b/webpack.common.cjs
index dff41f94d44..b009934b42e 100644
--- a/webpack.common.cjs
+++ b/webpack.common.cjs
@@ -1,6 +1,7 @@
+var path = require('path');
var webpack = require('webpack');
-module.exports = {
+var config = {
entry: './src/index.js',
devtool: 'source-map',
plugins: [
@@ -28,3 +29,13 @@ module.exports = {
]
}
};
+
+if (process.env.WEBGPU === 'true') {
+ config.resolve = {
+ alias: {
+ 'three$': path.resolve(__dirname, 'node_modules/three/build/three.webgpu.js')
+ }
+ };
+}
+
+module.exports = config;