protectwise / troika

A JavaScript framework for interactive 3D and 2D visualizations
MIT License
1.64k stars 124 forks source link

troika-three-text: possible to use in a webworker? #323

Open LukeWood opened 3 months ago

LukeWood commented 3 months ago

When attempting to get troika text to run in a webworker I get the following error:

ReferenceError: document is not defined
    at getTextRenderInfo (troika-three-text.js?v=a6a14d45:4775:20)
    at Text.sync (troika-three-text.js?v=a6a14d45:5511:9)

Any interest in fixing this?

lojjic commented 3 months ago

How are you trying to use it in a worker? Rendering to an OffscreenCanvas? Gimme some context.

LukeWood commented 3 months ago

Of course - sorry about that!

Yes, I'm rendering to an OffscreenCanvas with a WebGLRendererer ( NOT webGPU ).

LukeWood commented 3 months ago

It is something like...

  const canvas = document.getElementById('game-canvas') as any;
  const offscreen = canvas.transferControlToOffscreen();

  // const proxy = new ElementProxy(window as any, orbitalEventHandlers, orbitalExtraArgs, (data: any) => {
  //   gameHandle.handleProxiedEvent(data)
  // });

  gameHandle.setupGraphics(
    offscreen,
    window.innerWidth,
    window.innerHeight,
    window.devicePixelRatio
  );

Then in the worker I do:

function createText() {
    const text = new Text();
    text.text = this.parent.name.toUpperCase();
    text.fontSize = 1;
    text.rotateX(Math.PI / 2);
    text.scale.set(-1, 1, 1);
    text.color = 0xffffff;
    text.anchorX = 'center';
    text.anchorY = 'top';
    text.material.opacity = 0.5;
    text.sync();
    return text;
}

and it fails.

LukeWood commented 3 months ago

It looks like in: https://github.com/protectwise/troika/blob/d23f360c4316fa782d351151062ea3b0c2629ca1/packages/troika-three-text/src/TextBuilder.js#L167

We can replace document.createElement('canvas') with new OffscreenCanvas perhaps. That is the only reference to document I see.

lojjic commented 3 months ago

Makes sense. If I recall, I originally tried using an OffscreenCanvas instead of (or optionally to) the document.createElement('canvas') but there was some issue with that where the SDFs rendered into it would render incorrectly -- maybe a colorspace difference so the color channel values were wrong?

That was a while ago, though, so if you try it out and it works then I'd definitely be open to merging it.

LukeWood commented 3 months ago

Makes sense. If I recall, I originally tried using an OffscreenCanvas instead of (or optionally to) the document.createElement('canvas') but there was some issue with that where the SDFs rendered into it would render incorrectly -- maybe a colorspace difference so the color channel values were wrong?

Yeah unfortunately you have to set colorspaces a bit more consistently in the worker/offscreen world than in the main thread. It is a bit of a pain. I'll let you know if I figure it out.