# Web workers for three

**URL:** <https://discourse.threejs.org/t/web-workers-for-three/71207>\
**Category:** Questions\
**Tags:** web-worker, multithreading\
**Created:** [September 25, 2024, 6:49pm UTC](https://discourse.threejs.org/t/web-workers-for-three/71207 "2024-09-25T18:49:44Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gaelle\_Berton](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/gaelle_berton/32/47621_2.png) [@Gaelle\_Berton](https://discourse.threejs.org/u/Gaelle_Berton)\
**Post date:** [September 25, 2024, 6:49pm UTC](https://discourse.threejs.org/t/web-workers-for-three/71207/1 "2024-09-25T18:49:44Z")

</div>

I am merging all object of a scene and using another modifier subsequently, this can ttake up to half a minute.  
The idea is to move these operations (modify geometries, merge then tessellate) to a web worker, but I get errors as soon as i set up the imports. Is this the best way to proceed?  
Note that i am using Angular

```javascript
/// <reference lib="webworker" />

//import * as THREE from "three";
//import * as BGU from "three/examples/jsm/utils/BufferGeometryUtils.js";
//import { TessellateModifier } from "three/examples/jsm//modifiers/TessellateModifier.js";
//import toonShader from "~shaders/toon-shader";
//import { SceneStore } from "~stores/scene.store";

addEventListener("message", ({ data }) => {
  const response = `worker response to ${data}`;
  postMessage(response);
});

const wireScene = (scene: any, sceneStore: any): string => {
  return "done";
};

```

---

<div class="post-metadata">

**Author:** ![Gaelle\_Berton](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/gaelle_berton/32/47621_2.png) [@Gaelle\_Berton](https://discourse.threejs.org/u/Gaelle_Berton)\
**Post date:** [November 1, 2024, 10:50pm UTC](https://discourse.threejs.org/t/web-workers-for-three/71207/2 "2024-11-01T22:50:04Z")

</div>

Any idea anyone?

---

<div class="post-metadata">

**Author:** ![GitHubDragonFly](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/githubdragonfly/32/20752_2.png) [@GitHubDragonFly](https://discourse.threejs.org/u/GitHubDragonFly)\
**Post date:** [November 2, 2024, 12:38am UTC](https://discourse.threejs.org/t/web-workers-for-three/71207/3 "2024-11-02T00:38:05Z")

</div>

See if you might adapt and use anything from [this topic](https://discourse.threejs.org/t/performance-issues-rendering-large-ply-point-cloud-in-three-js-downsampling-and-background-loading/69135/1).

---

<div class="post-metadata">

**Author:** ![hofk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/hofk/32/44944_2.png) [@hofk](https://discourse.threejs.org/u/hofk)\
**Post date:** [November 2, 2024, 8:03pm UTC](https://discourse.threejs.org/t/web-workers-for-three/71207/4 "2024-11-02T20:03:07Z")

</div>

I can’t make out much from your brief code. A short live example would be appropriate.

I use a worker for the complex calculation of several geometries. The parameters are passed as an array of { } - objects.

For example, for a number of geometries, the parameters in the array param:

in the main program:

```javascript
//Assignment for the individual geometries in loop(s) ........
param[i] = {
	triangleSide: triangleSide,
	radius: param[0].holes[i1][2], // from first Geo index 0  
	height: iHeight,
	radiusBottom: param[0].radius, // radius from first Geo index 0 
	btmDiff: btmDiff[i],
	topDiff: topDiff[i]
}
//..........................................................

worker.postMessage( param );

worker.onmessage = function( e ) {

	 gc = e.data; // calculated data

	for ( let i = 0; i <= count; i ++ ) { // create geometries
				
		geo[i] = new BufferGeometry( );
		
		geo[i].type = gc[i].type;
		geo[i].ang = gc[i].ang;
		 geo[i].div4 = gc[i].div4;
		// ... further data on geometry
		geo[i].setIndex( new BufferAttribute( gc[i].indices, 1 ) );
		geo[i].setAttribute( 'position', new BufferAttribute( gc[i].positions, 3 ) );

		// further calculations for the geometries
		...
	}
		
}

```

in the worker

```javascript
onmessage = function( e ) { 
                  
    const param = e.data;
    
    const gc = [];
    const buffers = [];
    
    for ( let j = 0; j < param.length; j ++ ) { // calculate geometry values
         
        gc[j] = Calculate( param[j] );
        
        buffers.push( gc[j].positions.buffer );
            
    }
    
    postMessage( gc, buffers );

}

function Calculate( p ) {

    indices = [];
    positions = [];
	
   // calculation in loop(s) ...
   indices[idx] = ...
   positions[pIdx] = ...
   //..........................
    gc.indices = new Uint32Array( indices );
    gc.positions = new Float32Array( positions );

    return gc;

}

```

---

<div class="post-metadata">

**Author:** ![Attila\_Schroeder](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/attila_schroeder/32/36097_2.png) [@Attila\_Schroeder](https://discourse.threejs.org/u/Attila_Schroeder)\
**Post date:** [November 2, 2024, 10:16pm UTC](https://discourse.threejs.org/t/web-workers-for-three/71207/5 "2024-11-02T22:16:31Z")

</div>

Hi hofk, I have a live example on github but it’s a bit more extensive. But the part that sends data to the worker and receives from the worker is manageable

> **[GitHub - Spiri0/Threejs-WebGPU-IFFT-Ocean-V2](https://github.com/Spiri0/Threejs-WebGPU-IFFT-Ocean-V2)**
>
> Contribute to Spiri0/Threejs-WebGPU-IFFT-Ocean-V2 development by creating an account on GitHub.

```javascript
//your functions and classes

self.onmessage = (msg) => {

   const received datas = msg.data;

   //include your code
   const result = ...

   self.postMessage({data: result});

};

```

I think I’m doing something similar to what you’re trying to do. My worker is called:

```javascript
ocean-builder-threaded-worker.js

```

in the ocean folder. `ocean-builder-threaded.js` then sends the geometry data created by the worker to `ocean-chunk.js`, where the geometries are then generated from the data. I use a slightly more extensive worker manager because I distribute the work to 7 workers. You probably won’t need it to that extent. The reason why your worker doesn’t want to do this is, as mentioned, the missing self. I don’t see anything in your worker that triggers it.

---

<div class="post-metadata">

**Author:** ![hofk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/hofk/32/44944_2.png) [@hofk](https://discourse.threejs.org/u/hofk)\
**Post date:** [November 3, 2024, 5:10pm UTC](https://discourse.threejs.org/t/web-workers-for-three/71207/6 "2024-11-03T17:10:28Z")

</div>

> [@Attila\_Schroeder](#):
>
> I distribute the work to 7 workers. You probably won’t need it to that extent.

For a few connected geometries (my profile picture here shows 3) you don’t need a worker at all. However, if a large number of geometries are involved and the triangle size must therefore be very small, it is no longer possible without a worker.

Using several workers for many partial geometries certainly requires some additional effort. The problem is that the number of geometries can change constantly and within

`worker.onmessage = function( e ) { ...`

further complex calculations are performed and additional geometries are created. To do this, all geometries geo[i] must be retrievable in sequence in the data field geo.

---

<div class="post-metadata">

**Author:** ![Attila\_Schroeder](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/attila_schroeder/32/36097_2.png) [@Attila\_Schroeder](https://discourse.threejs.org/u/Attila_Schroeder)\
**Post date:** [November 3, 2024, 5:32pm UTC](https://discourse.threejs.org/t/web-workers-for-three/71207/7 "2024-11-03T17:32:45Z")

</div>

wrong recipient 😅  
This was intended for Gaelle\_Berton

---

<div class="post-metadata">

**Author:** ![hofk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/hofk/32/44944_2.png) [@hofk](https://discourse.threejs.org/u/hofk)\
**Post date:** [November 3, 2024, 7:12pm UTC](https://discourse.threejs.org/t/web-workers-for-three/71207/8 "2024-11-03T19:12:59Z")

</div>

> [@Attila\_Schroeder](#):
>
> wrong recipient 😅

No problem, it made me think 🤔 about it again. 🙂

---

<div class="post-metadata">

**Author:** ![aardgoose](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/aardgoose/32/32355_2.png) [@aardgoose](https://discourse.threejs.org/u/aardgoose)\
**Post date:** [November 4, 2024, 1:14pm UTC](https://discourse.threejs.org/t/web-workers-for-three/71207/9 "2024-11-04T13:14:57Z")

</div>

When transfering geometry attributes is is more efficient to take advantage of the fact ArrayBuffers() are ‘transferable’, where the data isn’t copied, just the ownership/visibility of the underlying memory changed.

> **[Transferable objects - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects)**
>
> Transferable objects are objects that own resources that can be transferred from one context to another, ensuring that the resources are only available in one context at a time.
> Following a transfer, the original object is no longer usable; it no...

---

<div class="post-metadata">

**Author:** ![Attila\_Schroeder](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/attila_schroeder/32/36097_2.png) [@Attila\_Schroeder](https://discourse.threejs.org/u/Attila_Schroeder)\
**Post date:** [November 4, 2024, 4:50pm UTC](https://discourse.threejs.org/t/web-workers-for-three/71207/10 "2024-11-04T16:50:04Z")

</div>

Hi aardgoose, I usually use SharedArrayBuffers to avoid copies, but I deactivated it in the ocean repo on github because otherwise it wouldn’t work with the guthub server.  
That’s why I already use ArrayBuffers instead of SharedArrayBuffers. But I didn’t know that ArrayBuffers also avoid copies. I learned something again there.
