Use DOM background layer with keyframe animations and Canvas layer for a physic engine
Asked Answered
C

2

24

In my next game I'm planning to mix a DOM background layer with the canvas(es) on top of it. I would like to move non-interactive background animations to that DOM layer, and use keyframe animations for transformations and opacity changes, like moving clouds around, air-planes etc.

As for me there are 2 pros for this:

  1. Simple keyframe animations are much easier to create. imho

  2. The most interesting point - it should improve performance:

    • transform and opacity animations can be GPU accelerated and performed on separate thread.
    • we do not perform those animations in our render frames, so we save here some milliseconds.

Or am I wrong? Perhaps browsers need much more time to make the composition of those layers, or are there some other caveats?

The biggest contrary for this technique is, that we can use it mostly for the decoration animations, and not for our game-play, as to control those animations is the hard task.

Does anybody have an experience with such layering?

Thank you in advance.

Celom answered 3/5, 2017 at 19:33 Comment(11)
This really depends on what are the animations you'll do... Some will cause a repaint of the whole page at each frame, some won't. Some will also make the painting of your visible canvas more complex than if all was on its surface. And in anyway, this will depend on the browser's implementations, there is no real strict answer you can get. The best is to try both, and check by yourself, on different implementations. And one third way you could try would be an background video.Neilneila
Sure it depends, for not GPU accelerated animations it is definitely better to use canvas in my case. But I was asking only about GPU accelerated animations: transform and opacity.Celom
Even though they are performed on the GPU, this doesn't mean they won't take some CPU process, nor that they won't be impacted by your js : jsfiddle.net/phhpxbq6 Also note that some canvas operations are also performed on GPU.Neilneila
@Kaiido, the keyfame animations with translate animations are not impacted by the js. jsfiddle.net/phhpxbq6/1 But sure, when having a lot of calculations the whole operation system will be laggy)Celom
And as a proof that all this depends on implementations, my FF does freeze with animations too.Neilneila
windows FF 51 not freezes the lime (keyframe animated) box. What version do you use?Celom
53 on mac and on androidNeilneila
There are some cons of this solution. You can eg. mix ReactJS and WebGL sitepoint.com/building-a-game-reactjs-and-webgl 3D objects can be inspected as regular DOM elements, you can separate views, and UI is easier to create.Vikiviking
You can also use WebGL context in "hackisch way" for GPU computation for any script: learningwebgl.com/blog/?p=1828Vikiviking
I suggest not, especially when the game is complex. 1.canvas mix with background might act different on different browser/platforms. 2.rendering on the same area might cost more even if you use GPU. 3.when you change scene, you do it twice. 4.using different skills need maintainer know both skills. still I prefer you are the forth-runner, and provide a performance report after you've done.Housebreak
Perhaps it would make precise alignment more difficult, since scoped units would be difficult to translate. On the other hand, distribution of duties to a "B Team" is a common practice among animation and game studios.Diatomic
G
1

I started off in much the same boat you are and have travelled many avenues of webgl, canvas, and my new go-to: svg.

SVG provides much of what you want out of your elements, but it's still within a graphical rendering engine, so you can still add a bunch of filters and effects, but the layers are more static, like you said you wanted. ( not rendering every tick ).

In my current app, the three.js engine has been stripped down, and no longer does image textures ( those are 3d transformed html elements ). I have a pure html+react scene, and a three.js scene which match perfectly ( either perspective camera or orthogonal ). It was a very long (fun) process to get them all to match.

Anyway, I only use three.js for some 3d decorations ( like handles to grab onto to resize elements ). It's an animation app by the way, so like a 3d editor in ways. I am debating whether to remove the threejs rendering completely ( I still will use three.js to have a scene structure, and call localToWorld on stuff, then render it on an svg overlay-- but I won't call render on the three scene [I have to manually call updateMatrixWorld() on everything, but its like 20x faster than rendering the scene] )

For real-time rendering, if the character moves for a while, then stands still, and you're trying to save time on those moments in time when the background doesn't move, I dunno if that's right thinking. Do you want lag when he is moving far enough to scroll the background?

That being said, caveats aside, it could be faster. Three.js has to load big textures into memory. If you're doing certain filters onto the background, then changing the background image in and out of a texture buffer would be pretty dang slow, but there are also webgl ways to do it all without changing the texture.

I probably wouldn't recommend doing a hybrid system unless you have exhausted your options and are just looking to try something new.

I definitely recommend using and learning svg.

I'm pretty sure there are hacks within webl that would probably prove to be more maintainable in the long run ( maintaining two engines is a bit mentally taxing ). It's not terrible, and I actually like my html engine much better than my three.js one.. but hmm..

Have you considered an all html 3d engine? It took me a long time to figure out a heirarchy, and until I was confortable using a ton of html elements ( and not trying to conserve them -- its fast with a lot )

My html elements are 0 based (i always translate 50%, 50%, working from the center of an element, like three.js does, it's much easier on the brain than doing top,left orientation) container anchor mesh children This is what I went with. The mesh is usually an img or an svg. Actually now most of my elements are 0x0. Only mesh has a width, usually. Originally I was doing a weird stuff, but now it's pretty much like a three.js scene, except with html elements, and I was using the CSS3dRenderer originally, but my own is just as good and more maintable ( everything is a react component )

Each "thing" is a class and it creates those 4 html elements. It also creates three.js elements ( for doing mouse intersections, raycasting, converting between coordinate systems, etc ).

Getting everything into and out of redux in a sane way was also interesting.

SVG meshes have children too ( the svg elements ).

You might enjoy doing some project with react and nested html elements, 3d transformed, and using svg for the elements + animations.. cuz I know I do.

You could pre-process the meshes and use a gif instead of an image or svg.

I dunno. You seem to want to do something weird, so imo, making a game in react with svg seems weird. I bet you'd get free press because people will up-vote anything with react in it.

Another thing I'll say is that after learning react + redux + immutable, my whole mind is different. My three.js engine for updating props is 10000% different. It's much lazier. You might find that just learning a new system of handling data + updating props will make you see your engine in a new way. I recommend learning react + redux + immutable, and perhaps even learning to apply them to three.js.

Another thing you could do would be multiple webgl scenes, and then just not need to render the background layer unless it's moving.

Also, if you look into doing the svg route, note that using css transform is different than using the attribute transform(built for svg elements). Firefox and IE can't handle svg elements ( like rect, path, circle, etc) being css transformed, but it does work if you use the attribute.

Also, css animations aren't faster than javascript animations.. not really. Using transform with a 3d translation or rotation or whatever, that's all you need to activate the video card. If you even do something like transform: translateZ(0), it'll activate the video card. You don't need to write css, you can use javascript, and most tween libraries just use javascript. You still will have performance things to work out, but it's also good to do your transitions in js, so things don't get out of sync.

If I were to send you on a vision quest, I'd tell you to write a 3d game in react + redux + immutable. And you'd get like 1000 upvotes on programmer websites.

Grandstand answered 30/1, 2018 at 2:55 Comment(0)
M
0

I am not certain about the performance with modern SVG but in 2016, I made a 2d space shooter game and found clear bottlenecks. I was only able to get 200 - 300 shapes to render. The only work around is to use WebGL for this task.

Malina answered 6/5, 2022 at 20:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.