mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
102.92k stars 35.39k forks source link

Improve compatibility of three/webgpu with nextjs #29916

Closed whatisor closed 1 day ago

whatisor commented 1 week ago

Description

As default, 1 threejs project working on nextjs, which wants to upgrade to WebGPU, needs dynamic import for three/webgpu component. This has some limitation during development.

Solution

We should be able to avoid all client code style as "self." in global scope.

Alternatives

NA

Additional context

No response

Mugen87 commented 1 week ago

Do you mind explaining in more detail what parts of WebGPURenderer have issues with nextjs? Based on what you have written so far I'm afraid this aspect is not clear yet.

whatisor commented 1 week ago

It cannot compile with error that self. is undefined because code is compiled in backend side without dynamic import. I know threejs is client side code but webglrenderer does not have that issue. image

whatisor commented 1 week ago

I am testing it here: next-three-webgpu

Mugen87 commented 1 week ago

@RenaudRohlinger This is the line in question:

https://github.com/mrdoob/three.js/blob/e0a7471d0d63c6a334afe9a3f4465695cb9baf41/src/renderers/webgpu/nodes/WGSLNodeBuilder.js#L22

Could this section be rewritten like so?

// GPUShaderStage is not defined in browsers not supporting WebGPU
const GPUShaderStage = ( typeof self !== 'undefined' ) ? self.GPUShaderStage : { VERTEX: 1, FRAGMENT: 2, COMPUTE: 4 };

const wrapNames = {
    [ RepeatWrapping ]: 'repeat',
    [ ClampToEdgeWrapping ]: 'clamp',
    [ MirroredRepeatWrapping ]: 'mirror'
};

const gpuShaderStageLib = {
    'vertex': GPUShaderStage.VERTEX,
    'fragment': GPUShaderStage.FRAGMENT,
    'compute': GPUShaderStage.COMPUTE
};
RenaudRohlinger commented 1 week ago

I believe so, also I'm surprised nextjs got the issue, I'm using the WebGPURenderer in OffScreen Canvas actively.

whatisor commented 1 week ago

It needs more broadly approaching for all "self." or "navigator." code around code of webgpu parts

donmccurdy commented 6 days ago

I am testing it here: next-three-webgpu

@whatisor cloning this repo and running yarn dev and yarn build locally, I'm not seeing any errors. Are additional steps needed to reproduce the error described in https://github.com/mrdoob/three.js/issues/29916#issuecomment-2483323549 ?

whatisor commented 5 days ago

@donmccurdy using dynamic import in that project is not a good way, just work around to overcome it. Client code have worse performance and less Lint activity.

donmccurdy commented 5 days ago

@whatisor WebGPU does not exist in Node.js, and cannot be used for server-side rendering (SSR). three.js renderers cannot operate in a Node.js environment, so I'm not sure a performance comparison is meaningful.

Maybe we can avoid top-level await, and fix issues that would prevent importing three.js in a Node.js environment, but I don't think putting typeof checks in front of every reference to Web APIs in three.js is a good use of time... are you sure that lazy-loading and dynamic import aren't the right choice here? I don't think you want your server to spend time parsing 3D models and textures on each request, for example, only to throw that work away.

whatisor commented 5 days ago

@donmccurdy Server will not handle any 3D resource, it compiles app script at compile time with best Lint support and prerender html only at runtime. There are many limitation of next dynamic you will get on because of 2 mode of ssr. It is not a good deal for big project. And you will not want to load big script bundle at client.

I am sure we can do it well as webglrenderer. This is not a big issue, just avoid "global scope" in code.