three.js
three.js copied to clipboard
WebGPU module js build of Three.js
Description
I would like a WebGPU build of Three.js in the /build directory. For example: three.webgpu.module.min.js So that I can begin testing and implementing WebGPU support.
At the moment WebGL is hidden away in this directory: https://github.com/mrdoob/three.js/blob/dev/examples/jsm/renderers/webgpu/WebGPURenderer.js
Solution
three.webgpu.module.min.js
Alternatives
Alternative: Include WebGPU in default module js build.
Additional context
No response
Um, what do you mean with "hidden away"? You can import the renderer like any other addon.
The WebGPURenderer isn't included in the Three.js module js build. Instead it is stored in the /examples/jsm/renderers/webgpu/ subdirectory, and imports many other js files with specific relative paths.
So I wish that the WebGPU support with the WebGPURenderer was either included fully in the default module build of Three.js, or that there was a specific build of Three.js with WebGPU support.
I don't think we should do anything immediately here, this approach is how many other important parts of three.js are packaged. But it would be worth planning a longer-term roadmap for WebGPU support; it will not be an addon forever.
@andreasrosdal are you building using default vite or using own setup? I'm asking because I'm experiencing issues building with vite (development version runs but production version is not).
Sorry for off-topic I'm relatively new to Threejs and WebGPU and want to verify that his is not an issue on my side.
@rv4Flyver Fciv.net imports Three.js as a module directly, with a workaround. See the source code here: https://github.com/fciv-net/fciv-net/blob/main/freeciv-web/src/main/webapp/webclient/index.jsp#L58
The rest of the source code is built with Maven and Closure compiler.
I would like to use a more modern build system.
@andreasrosdal since you host the file yourself I dont see why cant you just build the version of 3js you want yourself? ~~by editing this file and running standard 3js build, for example~~ (this would not work because of circular dependency of three on itself).
I've tried to look at this. Its referencing the module I create a custom build from sources as I found duplicates trying to reference the module when adding other imports.
The renderer tries to setup webgpu immediately with an async and not in the init method and patch Matrix4 in the init method. This breaks in an iife package. It needs to be setup in the init method.
I've tried to look at this. Its referencing the module I create a custom build from sources as I found duplicates trying to reference the module when adding other imports.
The renderer tries to setup webgpu immediately with an async and not in the init method and patch Matrix4 in the init method. This breaks in an iife package. It needs to be setup in the init method.
Cool, can you provide a WebGPU module build of Three.js?
@andreasrosdal why are you so lazy 🤣 but okay, try this js file:
import * as THREE from './three.gpu.js';
console.log(THREE);
(all the Nodes.js stuff should be under THREE.Nodes)
I'm working on figuring out how to make my custom three build as it references sources to stop duplicated imports that happens using the module. The code keeps making references to the module so might have to keep it that way. But there is refactoring required so it doesn't immediately setup webgpu. I may have to make a build of webgpu and reference my custom iife module build that includes custom components as global.
Here is refactoring snippets
patchApi() {
Matrix4.prototype.makePerspective = makePerspective;
Matrix4.prototype.makeOrthographic = makeOrthographic;
Frustum.prototype.setFromProjectionMatrix = setFromProjectionMatrix;
_frustum = new Frustum();
_projScreenMatrix = new Matrix4();
_vector3 = new Vector3();
}
async init() {
if ( navigator.gpu !== undefined ) {
staticAdapter = await navigator.gpu.requestAdapter();
}
this.patchApi();
Await when bundled causes an issue when trying to make a umd/iife bundle. Needs to be in init
staticAdapter = await navigator.gpu.requestAdapter();
And then I can do
if ( WebGPU.isAvailable()) {
renderer = new THREE.WebGPURenderer();
renderer.init();
console.log("using webgpu renderer");
} else {
renderer = new THREE.WebGLRenderer();
}
Referencing the module to bundle the files, causes no files to be included and rollup just bundles the whole entire module. Its wierd. Only source includes works for me. But the webgpu files reference the module. I may have to fork that portion to use source includes also.
includePaths({
paths: ["../three.js/src", "../three.js/examples/jsm"],
include: {
'three': '../three.js/build/three.module.js'
}
}),
The WebGPU support tries to setup webgpu globally in the bundle. await breaks iife bundling. So support api check needs to be changed into a method.
if ( navigator.gpu !== undefined ) {
const adapter = await navigator.gpu.requestAdapter();
if ( adapter !== null ) {
isAvailable = true;
}
}
@danrossi
So support api check needs to be changed into a method.
why not just make a separate PR for this (separate from this issue, that is)
Understood. I've setup this build project for now with the mods. I've got to test it still.
https://github.com/danrossi/three-webgpu-renderer/tree/master/build
The modded files
https://github.com/danrossi/three-webgpu-renderer/blob/master/src/renderers/webgpu/WebGPURenderer.js https://github.com/danrossi/three-webgpu-renderer/blob/master/src/capabilities/WebGPU.js
There is other problems I found. This gets bundled up with a tonne of stuff not needed normally for webglrenderer to support both and is run in the iife bundle but broken when compressing with terser. gets an error thrown. Should only be run when setting up the webgpurenderer if it needs it at all.
https://github.com/mrdoob/three.js/blob/d732ceb51ab154b870b01b940e550b4fdb2b5ea5/examples/jsm/nodes/core/Node.js#L429
It's caused by a circular dependancy when trying to bundle it. Claims to not be a class when compressing because it has no class name.
(!) Circular dependency
three.js/examples/jsm/nodes/lighting/AnalyticLightNode.js -> three.js/examples/jsm/nodes/materials/MeshBasicNodeMaterial.js -> three.js/examples/jsm/nodes/materials/NodeMaterial.js -> three.js/examples/jsm/nodes/lighting/LightsNode.js -> three.js/examples/jsm/nodes/lighting/AnalyticLightNode.js
I'm hoping that external project works. I did test it and realised I have to change alot of the integration, I use RawShaderMaterial with custom shader and it doesn't like that. I have to try and support both WebGLRenderer and WebGPURenderer. I may need to modify how the nodes are loaded. They all get initialized at once and may not all be needed or included. The bundle with WebGPU is 1.6mb compared to 600k. I'm looking at it once I can fix the WebXR polyfill as it seems threejs breaks it, not the other way.
@danrossi Thank you for making this! Is this build ready for me try test in www.Fciv.net?
What about Water2, Gltfimporter and other addons I use?
I haven't been able to properly test it yet outside the examples as stuff I use doesn't work with the renderer. There is a circular dependency bug that may prevent it working but import the built module and give it a try. The one bundled with three is huge, a 1.6mb bundle.
I get this error: Uncaught referenceError: GPUShaderStage is not defined
when using this build: https://github.com/danrossi/three-webgpu-renderer/blob/master/build/three-webgpu.module.js
Can I please have just one js module build file? Why is there a webgpu-renderer.module.js
@andreasrosdal What version of Chrome is that and what OS?
Chromium Version 112 on OpenSUSE tumbleweed. I realize now that it doesn't support WebGPU yet. So I can try to use Google Chrome instead.
https://github.com/mrdoob/three.js/blob/517ce63ecc63e675643af6f7c16e4c94092b3e7f/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js#L20-L26
This code snippet is currently deprecated, I think it would be nice to update the code, important updates have been made.
Do we still need this?
https://github.com/mrdoob/three.js/blob/95f678c9ca63fdb500e9c635d780428cb687855a/examples/jsm/capabilities/WebGPU.js#L1-L5
Do we still need this?
Hmm... maybe not. I would just leave it until I make a GPU layout generation system, auto layout is limiting shadow integration.
I'm looking back into the external module bundle as I believe WebGPU may be where we have to move to. However the bundle is huge I think and includes all the nodes one may not need. I'm going to figure something out to make it selective. The support check needs to be inside a method to await for a start where the api patch happens. So fallback support can be made for WebGLRenderer. The external async breaks in an iife bundle.
https://github.com/danrossi/three-webgpu-renderer/blob/master/src/renderers/webgpu/WebGPURenderer.js#L190
@danrossi can you share a project demo with your setup? The one making the iife bundle
I'm rebundling the module due to a refactor of the webgpu api. And this is the rollup output trying anything other than esm output. I'll have a look updating the rendererer in my build. But both files might have to be moved across to do it.
[!] Error: Module format iife does not support top-level await. Use the "es" or "system" output formats rather.
three.js/examples/jsm/renderers/webgpu/WebGPUBackend.js
Error: Module format iife does not support top-level await. Use the "es" or "system" output formats rather.
I've updated the bundles and moving the async into init allows for an iife bundle. Ive yet to test it until I can figure out how to setup for equi and stereo video. I use rawshadermetarial with a trimmed down shader with no lighting and it doesn't like that.
https://github.com/danrossi/three-webgpu-renderer/blob/master/src/renderers/webgpu/WebGPUBackend.js#L66
I added some tests with the build and seems to work. The support check does an await with my modified WebGPU class. I need to figure out how to get everything I have integrated working with this webgpu api. more specifically sphere geometry and video textures and rawshadermaterial. This example is adding an image texture to a background.
https://github.com/danrossi/three-webgpu-renderer/blob/master/tests/webgpu_equirectangular.html
I've integrated the tests I need personally. So the renderer is a drop in replacement without differences to webgl renderer or does it need to use the texture and uv methods from nodes ?
I have an RTX2060 and with webgl I see 13% usage. With WebGPU it's 3% usage. The colours are washed out and high contrasted compared to WebGL.
And seems there is no xr manager yet for it so XR hasn't been implemented for WebGPU. This doesnt exist setReferenceSpaceType
I've seen how that might possibly be done below. So not 100% usable until XR support ?
https://github.com/danrossi/three-webgpu-renderer/blob/master/tests/webgpu_video_panorama_equirectangular.html https://github.com/danrossi/three-webgpu-renderer/blob/master/tests/webgpu_webxr_vr_video.html
https://github.com/immersive-web/WebXR-WebGPU-Binding/blob/main/explainer.md