three.js icon indicating copy to clipboard operation
three.js copied to clipboard

WebGPU module js build of Three.js

Open andreasrosdal opened this issue 1 year ago • 56 comments

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

andreasrosdal avatar Apr 27 '23 18:04 andreasrosdal

Um, what do you mean with "hidden away"? You can import the renderer like any other addon.

Mugen87 avatar Apr 27 '23 19:04 Mugen87

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.

andreasrosdal avatar Apr 27 '23 19:04 andreasrosdal

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.

donmccurdy avatar Apr 27 '23 19:04 donmccurdy

@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.

ghost avatar Apr 30 '23 10:04 ghost

@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 avatar Apr 30 '23 10:04 andreasrosdal

@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).

makc avatar May 11 '23 06:05 makc

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.

danrossi avatar May 22 '23 16:05 danrossi

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 avatar May 22 '23 16:05 andreasrosdal

@andreasrosdal why are you so lazy 🤣 but okay, try this js file:

import * as THREE from './three.gpu.js';
console.log(THREE);

three.gpu.js.zip

makc avatar May 22 '23 16:05 makc

(all the Nodes.js stuff should be under THREE.Nodes)

makc avatar May 22 '23 17:05 makc

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();
               }

danrossi avatar May 23 '23 05:05 danrossi

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 avatar May 23 '23 10:05 danrossi

@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)

makc avatar May 23 '23 10:05 makc

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

danrossi avatar May 23 '23 12:05 danrossi

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

danrossi avatar May 23 '23 15:05 danrossi

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 avatar May 29 '23 15:05 danrossi

@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?

andreasrosdal avatar May 29 '23 15:05 andreasrosdal

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.

danrossi avatar May 30 '23 15:05 danrossi

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

image image

Can I please have just one js module build file? Why is there a webgpu-renderer.module.js

andreasrosdal avatar May 30 '23 17:05 andreasrosdal

@andreasrosdal What version of Chrome is that and what OS?

mrdoob avatar May 31 '23 03:05 mrdoob

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.

andreasrosdal avatar May 31 '23 03:05 andreasrosdal

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.

sunag avatar May 31 '23 04:05 sunag

Do we still need this?

https://github.com/mrdoob/three.js/blob/95f678c9ca63fdb500e9c635d780428cb687855a/examples/jsm/capabilities/WebGPU.js#L1-L5

mrdoob avatar May 31 '23 14:05 mrdoob

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.

sunag avatar May 31 '23 15:05 sunag

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 avatar Jun 07 '23 02:06 danrossi

@danrossi can you share a project demo with your setup? The one making the iife bundle

marcofugaro avatar Jun 07 '23 07:06 marcofugaro

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.

danrossi avatar Jun 08 '23 18:06 danrossi

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

danrossi avatar Jun 08 '23 18:06 danrossi

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

danrossi avatar Jun 09 '23 14:06 danrossi

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

danrossi avatar Jun 10 '23 04:06 danrossi