React-three-fiber: Multiple canvases display the same thing

Created on 13 Mar 2019  路  35Comments  路  Source: pmndrs/react-three-fiber

Hey again, so I'm still trying to replicate this example. From their code, a canvas is created for each couple of images.

Here is my attempt, also based on the sandbox you provided me in issue #23 (thanks again!)
https://codesandbox.io/s/w5902o607

I'm not sure if it's updating to v1.3.7 that created this but now all canvases are showing the same image, and behave like one. I had it running properly at one point (under v1.3.6) but then I was running into THREE.WebGLRenderer: Context Lost issues.

Maybe this is not the right place to ask, but it really felt related to the version bump from v1.3.6 to v1.3.7

Most helpful comment

Here is the complete sandbox similar to the Tympanus original example btw: https://codesandbox.io/s/n74213346l

All 35 comments

there seems to be something wrong with codesandbox, too, look at this: https://codesandbox.io/s/40v634pk9

remove the first canvas and you still get images 1 and 2. probably bad cache?

Not sure really, this is new behavior. Reloading the page also changes the images... Don't know what happens to be honest. I'll try to investigate later.

maybe caching in the texture loader, something is really, really weird.

Looks like TextureLoader > ImageLoader uses a global cache: https://github.com/mrdoob/three.js/blob/master/src/loaders/ImageLoader.js

Isn鈥檛 it weird that all canvases also react to hover simultaneously?

yes, that's most likely my fault. never tried it with multiple canvases - i'll focus this week on interaction.

tried a little more, i don't understand what's causing it tbh. if you have time, here's how you can run stuff and debug directly in the root folder: https://github.com/drcmda/react-three-fiber/tree/master/examples

Ran some more tests, the mouse events are fine, only one image component gets hit. (see the same box i posted above) To me it looks like they're all using the same shader, which gets compiled and then cached. So one image receive the hover, moves over, the others have their own state and meshes, but display the first shader.

Hm makes sense. I'll try to revert to 1.3.6 and the previous code see if this changes anything.

when i give it the same shader under two different names, at least they start interacting right again, weirdly image is still doubled. https://codesandbox.io/s/40v634pk9

hm, i refreshed and now it works ... anyway, you need to figure out how to compile shaders without cache, this is probably all a three thing. i start to doubt any of this is related to this lib.

Using the same shader but with the previous way you suggested structuring the code (plus some rookie mistakes I guess), I do get different images though...

https://codesandbox.io/s/w5902o607

With 1.3.7 the hover wasN'T working with progress interpolation, now on 1.3.6 it does work properly.

it's "uniforms-dispFactor-value={progress}" ... but the other thing should work as well, i think need to tweak a little so that it accepts objects and atomics. next patch will be able to run both

Yes I know, the idea was to replicate the previous code that ran on 1.3.6 see if there was the same "caching" issue, and the fact there isn't. Regardless of the hover and progress, and even regardless of the versions:

This:

 <anim.shaderMaterial
        name="material"
        args={[XFadeShader]}
        uniforms-texture-value={texture1}
        uniforms-texture2-value={texture2}
        uniforms-disp-value={dispTexture}
        uniforms-dispFactor-value={0}
      />

Doesn't do the same as:

      <anim.shaderMaterial name="material" args={[args]} />
// args include all the uniforms value in the props above

To prove this, here is the updated sandbox: https://codesandbox.io/s/w5902o607

The first row of images is done using the first code, the second row using the second one.

image

interesting, looks like putting shader defs inside the args object stops three from caching it? so is this fixed? i pushed a patch as well for object piercing so both xxx-value={...} and xxx={{ ..., value: ... }} work again.

Cool! Looks like it鈥檚 fixed indeed!

Here is the complete sandbox similar to the Tympanus original example btw: https://codesandbox.io/s/n74213346l

Great! The code has remained glanceable. If you want to tweet it, i'd love to retweet. It's a nice example for using shadermaterial.

Sure. I鈥檓 just adding a few tweaks (is handling events from the dom rather than from THREE so that it can support touch, also at the moment unhover isn't triggered when the mouse leaves the window). I鈥檓 also testing performance against the Tympanus code, I鈥檒l do a screen capture and post it here if anything interesting comes out.

@drcmda arf, I'm actually running into a Safari specific issue, that happens also on your sandbox here: https://codesandbox.io/s/x37p4kk6p4

null is not an object (evaluating 'context.drawImage')

Maybe this should require an issue on its own?

I get "Cannot find variable: ImageBitmap", but i think these are already known: https://github.com/mrdoob/three.js/issues/15885

I think it's even related to the texture flip stuff, there was a regression in threejs.

Oh, that might explain why I don't get the Safari error on the Tympanus example code, that ships with a minified version of three js that I guess compiled at the time.

yep, going back to three version 100 fixes it: https://codesandbox.io/s/x37p4kk6p4

I think they have already fixed it in dev, but not released as a patch yet

Ok so not that it proves anything about the performance of this lib, but I've captured a side-by-side comparison between the react version (left) and the vanilla version (right) from Tympanus with a 4x CPU slowdown, and for some reason the hover events are triggered with a significant delay on the react version, although the smoothness of the animation is equal on both.

perf

EDIT: forgot to mention that the react version is built, running a React in production.

could it be its just the spring starting slower, or friction being higher than the curve in the original? i think visually you'll not be able to profile it in a meaningful way unless the configs match. you could use duration and the same easing. but using dev console profiling would be a way. then you see how much time is spent on a single frame, that will be a better indication.

original

Screenshot 2019-03-14 at 12 46 35

three fiber (in codesandbox, which i believe runs development env (?))

Screenshot 2019-03-14 at 12 47 22

it looks like react is a tiny bit faster, insignificantly, though. But i could be better - right now react-spring and react-three-fiber use their own requestAnimationFrame loops. If they share one i can cut off a couple of ms still. That's one of the goals for 2.x.

I鈥檒l re-run some tests after lunch but I had inserted console.logs and there was a significant delay between when the dom got the event and when it was propagated to the props. I鈥檒l investigate further in a few hours.

Regarding your last comment did you try slowing down the CPU in the performance tab?

Codesandbox does run in dev mode btw!

no i didn't, but running both on the same browser and system should give comparable results. dev mode should put react at a disadvantage, so im a little surprised it comes out on top, spend lots and lots of time optimizing react-spring though. and it's the part that's being profiled here because react otherwise isn't involved - it renders once and stays out, lets three just render. react-spring also functions 100% outside of react when it animates.

Maybe it鈥檚 the way that Chrome emulates the CPU slowdown that creates the delay.

Final note regarding perf, initial scrolling on my iPhone X seems to stutter a bit on the react version.

that as well could be how we're setting up textures. in the original they do it before the view is constructed. we're doing it right smack in the middle of UI built-up.

im not so concerned about perf otherwise, because react has no relation to three, it just renders once, then keeps out completely. In the frame readout you can set it - react is entirely missing, there's not so much as a single function of the react kernel being called.

but compiling textures and stuff is costly, and that has to be done carefully. we could also do that in global scope like in the codrops example, or perhaps using reacts new tools like scheduling. or using a splash until textures are done, like many webgl sites do. but these are userland considerations.

You鈥檙e right, this is approximately what I thought but if I wait for a couple of seconds before scrolling then the shader should be built and useMemo should make sure it鈥檚 not recompiled for any reason? But yes I understand that this lib can鈥檛 have impact on perfs per se, I鈥檓 just curious on why this happens really ^^

there's also gl.compile(scene, camera)

https://threejs.org/docs/index.html#api/en/renderers/WebGLRenderer.compile

which could maybe be utilized. It's finishing all shaders and textures in the scene. three otherwise will start doing it lazy, when they first appear or something like that. i guess memo isn't good enough for this kind of thing, textures need to be made before the component is ready to render.

here i'm not so knowledgable, this is the first time i'm using three for website related stuff.

Ok thanks I鈥檒l definitely have a look! I鈥檒l close the issue since I think it鈥檚 resolved by now 馃槄

Was this page helpful?
0 / 5 - 0 ratings

Related issues

UltimateForm picture UltimateForm  路  4Comments

brandonreid picture brandonreid  路  3Comments

objectisundefined picture objectisundefined  路  4Comments

mattrossman picture mattrossman  路  5Comments

francopetra picture francopetra  路  3Comments