I'm new to webgl and three js but I managed to finished a small project in a few weeks. But what I want to ask is, what can I do do improve loading times of the app? I'm not complaining about the fps's because the interaction with it is smooth, but it takes quite a while to load everything. Do you guys have any tips or resources that I can check to improve the bundle js loading times?
Im using d3, topojson and three js. The project is a 3d globe with a background image. The globe has a texture and it shows the overlay of the country you're hovering with (so it has mousemove and click events). It also has 3d markers (spheres and cylinders) and interact when you click them.
I tried removing all the code i could, avoid heavy computations, and use BufferGeometry everywhere I could. It also has particles. Since it uses click events I needed Projector.js and I needed OrbitControls.js for the controls logic. Im using debounce on the events also. I'm just asking about general three js tips, some guidelines to avoid waiting 6-9seconds for whole scene to load. Thanks!
shrink your 3D model data;
use compressed texture format such as dds or crunch;
cut big scene into small ones and load them by lods;
Hope this helpful.
I'm building a web app which has 360 degree images loaded into an a-sky primitive. I'm using aframe-react. There are total of 20+ 360 degree images and only one img asset inside a-assets. once user switches scene react will change src of asset img and scene will re render. Everything works fine but it's using lot of memory because of caching. One time it used 4GB+ memory. In mobile the web page crashes after switching through ~8+ images. How do I handle this situation?
I tried looking into THREE.Cache but images are not cached there.
Is this memory usage has anything to do with using React?
There's an issue for A-Frame to automatically manage it, but right now have to hack around to clear textures.
AFRAME.scenes[0].systems.material.textureCache[url].then(function (texture) {
texture.dispose();
});
I'm an engineer and we are currently porting our Red5 + Flash game into a Node.js + Easeljs html5 application.
Basicly: it's a board game, not an rpg. The layer system means we have multiple canvasses, based on functionally. For example there is a static background stage, with images. There is a layer for just the timers.
At default, all canvas size is 1920x1080, if needed we downscale to fit to the resolution.
The first approach used kinetic.js, but the performance fallen when the game got complex. Then we switched to easel, because it's abstraction level is lower, so we can decide how to implement some more function, not just use the provided robust one.
I was optimistic, but now it's starting to show slowness again, that's why I want to look deeper inside and do fine performance tuning. (Of course everything is fine in Chrome, Firefox is the problem, but the game must run smoothly on all modern browser).
The main layer (stage) is the map, contains ~30 containers, in each there is a complex custom shape, ~10 images. The containers are listening to mouse events, like mouseover, out, click. Currently, for example on mouseover I refill the shape with gradient.
Somehow, when I use cache, like the way in the tuts the performance get even worse, so I assume I'm messing up something.
I collected some advanced questions:
In the described situation when can I use cache and how? I've already tried cache on init, cacheUpdate after fill with other color or gradient, then stage.update(). No impact.
If I have a static, never changing stage cache doesn't make sense on that layer, right?
What stage.update() exactly do? Triggering the full layer redraw? The doc mentions some kind of intelligent if changed then redraw effect.
If I want to refill a custom shape with new color or gradient I have to completely redraw its graphics, not just use a setFill method, right?
In easel there is no possibility to redraw just a container for example, so how can I manage to not update the whole stage, but just the one container that changed? I thought I can achieve this with caching, cache all containers the just update the one that changed, but this way didn't work at all for me.
Does it make sense to cache bitmap images? If there are custom shapes and images in a container what is better? Cache the container or just the shape in container.
I found a strange bug, or at least an interesting clue. My canvas layers totally overlapping. On the inferior layers the mouseover listening is working well, but the click isn't on the very same container/object.
How can I produce a click event propagation to overlapped layers those have click listeners? I've tried it with simple DOM, jquery, but the event objects were far away from what canvas listeners wanted to get.
In brief, methods and props I've already played with bare success when tried tuning: cache(), updateCache(), update(), mouseEnabled, snapToPixel, clear(), autoClear, enableMouseOver, useRAF, setFPS().
Any answer, suggestion, starting point appreciated.
UPDATE:
This free board game is a strategy game, so you are facing a world map, with ~30 territories. The custom shapes are the territories and a container holds a territory shape and the icons that should be over the territory. This container overlapping is minimal.
An example mouse event is a hover effect. The player navigate over the territory shape then the shape is getting recolored, resized, etc and a bubble showing up with details about the place.
Basically, maximum amount of 1-3 container could change at once (except the init phase -> all at this time). Not just the animations and recoloring slow in FF, but the listener delay is high too.
I wrote a change handler, so I only stage.update() up on tick the modified stages and the stages where an animation is running (tweenjs).
In my first approach I put every image to the container that could be needed at least once during the game, so I only set visible flags on images (not vectors).
Regarding caching:
There are some strange caching-issues, somehow the performance can drop with certain sizes of the caching rectangle: CreateJS / EaselJS Strange Performance with certain size shapes
(2) Depending on how often you call stage.update();
(3)
Each time the update method is called, the stage will tick any
descendants exposing a tick method (ex. BitmapAnimation) and render
its entire display list to the canvas. Any parameters passed to update
will be passed on to any onTick handlers.
=> Afaik it rerenders everything if not cached
(4) Yes.
(5) No. (I don't know of any)
(6) If the content's of the container don't change often, I'd cache the whole container, otherwise the container will be reconstructed every frame.
I have a question though: Why do you use multiple canvases? How many do you use? I could imagine that using multiple canvases might slow down the game.
How many sprites do you use in total?
2: if your layer or stage doesn't change, don't call stage.update() for that layer (so it doesn't gets rerendered, gives me a much lower cpu!)
For example, keep a global "stagechanged" variable and set this to true when something has changed:
createjs.Ticker.addEventListener("tick",
function() {
if (stagechanged)
{
stagechanged = false;
stage.update();
}
});
(or do you already use this, as stated in your "update"?)
4: I found a way to update for example the fill color :)
contaier1.shape1.graphics._fillInstructions[0].params[1] = '#FFFFFF';
(use chrome debugger to look at the _fillInstructions array to see which array position contains your color)
5: I found a way to just paint one container :)
//manual draw 1 component (!)
var a = stage.canvas.getContext("2d");
a.save();
container1.updateContext(a); //set position(x,y) on context
container1.draw(a);
a.restore();
What I want to do:
I want to use sprite sheets to load all my enemies in the game. They would have to be removed once they are either destroyed by the good guy or when they go off screen. I have 6-7 enemies some of which are animations. I will be reusing them multiple times. I wan to load and unload them effectively from the memory.
What I am doing:
I first load the spritesheets:
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"Obstacles.plist"];
CCSpriteBatchNode *obstaclesspriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"Obstacles.pvr.ccz"];
[self addChild:obstaclesspriteSheet];
I have a class called BadBoys which handles the bad guys. Every time I want to create a bad guy I create an instance of the class. Inside the class I create the sprite and add it to the layer.
baddies[x] = [[BadBoys alloc] init];
//INSIDE THE CLASS
baddie = [CCSprite spriteWithSpriteFrameName:#"cannonball-hd.png"];
I remove the sprite from the layer when it gets destroyed and then release the instance of the class.
[self removeChild:[baddies[x] getBaddie] cleanup:YES]; //getBaddie returns the sprite
[baddies[x] release];
I know this is a good way to do it. What I want to know is if this is the most efficient way of doing this? I thought of another way of loading the image:
Load the image asynchronously to the CCTextureCache.
Then create a sprite using the texture from the cache.
Add it to a NSMutableArray which will hold all enemies that are alive
Then when I dont need it anymore I can destroy it the following way:
CCTexture2D * texture = spriteName.texture;
[spriteName.parent removeChild:spriteName cleanup:YES];
[[CCTextureCache sharedTextureCache] removeTexture:texture];
[backgroundSprites removeObject:spriteName];
Is this a better method? Please share your views and suggestions. Thanks.
What you're doing is good, as you said.
Your alternative is a terrible idea. I'll tell you why: you will want to avoid loading textures into memory and removing them from memory frequently during gameplay. Loading a texture from flash memory is slow. Removing the texture from memory also takes a little time, and is rather pointless if you have enough free memory available anyway.
Furthermore if you're using a spritesheet and you're removing one obstacle but try to remove the obstacle's texture (which is Obstacles.pvr.ccz) from memory as well, then the texture cache won't remove the texture from memory anyway. Because it's still being used by the spritesheet.
Lastly: premature optimization is the root of all evil.
CATransition is quite unusual. Consider the following code.
CATransition* trans=[CATransition animation];
trans.duration=0.5;
trans.type=kCATransitionFade;
[self.holdingView.layer addAnimation:trans forKey:nil];
self.loadingView.hidden=YES;
self.displayView.hidden=NO;
Notice that nowhere did I tell the transition that I wanted to display the displayView rather than loadingView, so the views must somehow access the transition themselves. Can anyone explain in more detail how this works?
When you add the transition as an animation, an implicit CATransaction is begun. From that point on, all modifications to layer properties are going to be animated rather than immediately applied. The way the CATransition performs this animation to to take a snapshot of the view before the layer properties are changed, and a snapshot of what the view will look like after the layer properties are changed. It then uses a filter (on Mac this is Core Image, but on iPhone I'm guessing it's just hard-coded math) to iterate between those two images over time.
This is a key feature of Core Animation. Your draw logic doesn't generally need to deal with the animation. You're given a graphics context, you draw into it, you're done. The system handles compositing that with other images over time (or rotating it in space, or whatever). So in the case of changing the hidden state, the initial-state fully composited image is blended with the final-state composted image. Very fast on a GPU, and it doesn't really matter what change you made to the view.