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;