PainKKKiller Posted January 27, 2017 Share Posted January 27, 2017 In my project I have some animations which made from too many frames, and on machines with weak videocards I am getting error with MAX_TEXTURE_SIZE and animation shows as black rectangle. To avoid that I divided spritesheet with animation into smaller ones, and make movieclip from them. Code looks like this: this.loader = new PIXI.loaders.Loader(); this.loader // load spritesheets with anime .add("b_b_0", 'res/anime/b_b_0.json') .add("b_b_1", 'res/anime/b_b_1.json') ... AssetsManager.prototype.getFrames = function(resName) { var json = this.getJSON(resName); var frames = []; var framesKeys = Object.keys(json.frames).sort(naturalSort); var textures; if(this.commonLoader.resources[resName]) textures = this.commonLoader.resources[resName].textures else if(this.ringLoader.resources[resName]) textures = this.ringLoader.resources[resName].textures; else throw new Error("There is no textures with name " + resName); for(var i = 0; i < framesKeys.length; i++) { frames.push(textures[framesKeys[i]]); } return frames; } //MAX_TEXTURE_SIZE problem WebGL AssetsManager.prototype.getBigMovieClip = function(resName, length) { var frames = []; for (var i = 0; i < length; i++) { frames = frames.concat(this.getFrames(resName + "_" + i)); } var movie = new PIXI.extras.AnimatedSprite(frames); return movie; } and the I use getBigMovieClip("b_b", 2) to get MovieClip made from 2 spritesheets. Everything ok, but I see small lag while movieclip playing and I have no idea how to overcome it. Thanks for any suggestions in advance. Quote Link to comment Share on other sites More sharing options...
themoonrat Posted January 27, 2017 Share Posted January 27, 2017 Use the prepare plugin to upload textures to the gpu before you play the animation Quote Link to comment Share on other sites More sharing options...
PainKKKiller Posted January 30, 2017 Author Share Posted January 30, 2017 Quote Use the prepare plugin to upload textures to the gpu before you play the animation Please, can you explain it? What does you mean by prepare plugin? Quote Link to comment Share on other sites More sharing options...
themoonrat Posted January 30, 2017 Share Posted January 30, 2017 Quote Link to comment Share on other sites More sharing options...
PainKKKiller Posted January 30, 2017 Author Share Posted January 30, 2017 Thanks, didn't knew about that, I'll give it a try Quote Link to comment Share on other sites More sharing options...
PainKKKiller Posted February 8, 2017 Author Share Posted February 8, 2017 Don't know how to use it properly, just found this post, tried to use it in several ways. one of attempts looks like this: renderer = PIXI.autoDetectRenderer(consts.resolutions[consts.RESOLUTION].width, consts.resolutions[consts.RESOLUTION].height, { view: document.getElementById("game-canvas") }); ... AssetsManager.prototype.getBigMovieClip = function(resName, length) { var frames = []; for (var i = 0; i < length; i++) { var fr = this.getFrames(resName + "_" + i); renderer.plugins.prepare.upload(fr); frames = frames.concat(this.getFrames(resName + "_" + i)); } var movie = new PIXI.extras.AnimatedSprite(frames); return movie; } But anyway I still have a lag in the middle of movieclip. Quote Link to comment Share on other sites More sharing options...
ClusterAtlas Posted February 8, 2017 Share Posted February 8, 2017 tried using the 'time' property in the frames? maybe slow things down a bit? https://servercharlie.bitbucket.io/1-PIXI-Animated-Sprites.html Quote Link to comment Share on other sites More sharing options...
PainKKKiller Posted February 8, 2017 Author Share Posted February 8, 2017 ServerCharlie thanks for reply, tried in this way: AssetsManager.prototype.getBigMovieClip = function(resName, length) { var frames = []; for (var i = 0; i < length; i++) { var fr = this.getFrames(resName + "_" + i); renderer.plugins.prepare.upload(fr); frames = frames.concat(fr); } var fr_set = []; for (var j = 0; j < frames.length; j++) { var frame = { texture: frames[j], time: 50 }; fr_set.push(frame); } var movie = new PIXI.extras.AnimatedSprite(fr_set); return movie; } Animation has got much slower, but lag still exists. Quote Link to comment Share on other sites More sharing options...
Brenwell Posted March 13, 2017 Share Posted March 13, 2017 So I smoothed out my movie clip animation with the following. The prepare plugin was the right solution but never worked. WebGL needs the entire texture(s) uploaded not the frames. The way textures are uploaded to the GPU is via renderer.bindTexture(texture). When the PIXI loader receives a sprite atlas url e.g. my_sprites.json it automatically downloads the image file and names it as mysprites.json_image in the loaders resources. So you need to grab that, make a texture and upload it to the GPU. let loader = new PIXI.loaders.Loader() loader.add('http://mysite.fake/sprite1.json') loader.add('http://mysite.fake/sprite2.json') loader.add('http://mysite.fake/sprite3.json') loader.once('complete', callback) loader.load() function uploadToGPU(resourceName){ resourceName = resourceName + '_image' let texture = new PIXI.Texture.fromImage(resourceName) this.renderer.bindTexture(texture) } loadSpriteSheet(function(resource){ uploadToGPU('http://mysite.fake/sprite1.json') uploadToGPU('http://mysite.fake/sprite2.json') uploadToGPU('http://mysite.fake/sprite3.json') // helper function to get all the frames from multiple textures let frameArray = getFrameFromResource(resource) let animSprite = new PIXI.extras.AnimatedSprite(frameArray) this.stage.addChild(animSprite) animSprite.play() }) jonforum 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 13, 2017 Share Posted March 13, 2017 That's what prepare is doing. I don't know why its not working for you, we really need demo for it. Quote Link to comment Share on other sites More sharing options...
Brenwell Posted March 13, 2017 Share Posted March 13, 2017 I suspect that the prepare plugin is not registering the location of the WebGL texture and therefore uploads it again on the initial play. If I get a free moment I will make a jsfiddle. Quote Link to comment Share on other sites More sharing options...
PainKKKiller Posted March 13, 2017 Author Share Posted March 13, 2017 I am making demo with defect just now, I''ll attach it to the post as soon as I can. ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
PainKKKiller Posted March 13, 2017 Author Share Posted March 13, 2017 Quick explanation about attached demo. Sorry for little mess, I tried to include only necessary files. Demo made in big (1920x1080 resolution) to show effect. I do my project with browserify, so if you want to compile it from source (in src folder) you have to install it. Otherwise you can use app.bundle.js file, it not minified, just check index.html to use it. When click button PLAY movieclip plays, and in first time I clearly see lag when stone falls on back, after that movieclip plays without lag. The module where movieclips are making is src/AssetsManager.js where getBigMovieClip function is located, where I tried to use prepare plugin. Then I play it in app.js with settimeout function just to check that all uploaded. Thanks in advance. bigdemo.zip Quote Link to comment Share on other sites More sharing options...
Brenwell Posted March 13, 2017 Share Posted March 13, 2017 I will check it out. I also made a quick demo https://jsfiddle.net/brenwell/pbts8c0y/ Toggle the constant `workAround` to see the difference PainKKKiller 1 Quote Link to comment Share on other sites More sharing options...
PainKKKiller Posted March 13, 2017 Author Share Posted March 13, 2017 Thank for demo! Quote Link to comment Share on other sites More sharing options...
Brenwell Posted March 13, 2017 Share Posted March 13, 2017 Adding this to your code worked for me. As has been pointed out this is not the proper solution. But it works. AssetsManager.prototype.preloadCommon = function(callBack) { preloader.show(); this.commonLoader ... //Added this on complete handler .on("complete",function(loader, resource){ console.log(resource) renderer.bindTexture(new PIXI.Texture.fromImage("b_k_0_image")) renderer.bindTexture(new PIXI.Texture.fromImage("b_k_1_image")) }) ... .load(function() { callBack(); preloader.remove(); }); PainKKKiller 1 Quote Link to comment Share on other sites More sharing options...
Brenwell Posted March 13, 2017 Share Posted March 13, 2017 Hey @ivan.popelyshev, It would be much appreciated if would take a look at my jsFiddle and tell me how to use the prepare plugin correctly. Thanks https://jsfiddle.net/brenwell/pbts8c0y/ Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 13, 2017 Share Posted March 13, 2017 From slack: Quote andrewstart [5:03 PM] looking at that, I am assuming that no one is actually passing a callback to `renderer.plugins.prepare.upload()`, so they are telling it to get prepared, then immediately trying to use it I dont see in your demo the place when you actually wait for prepare. Quote Link to comment Share on other sites More sharing options...
Brenwell Posted March 13, 2017 Share Posted March 13, 2017 If you are talking in regard to my demo, I am waiting because the sprite is only added to the stage and played when the user clicks the canvas. You can wait as long as you like for the for the prepare to work. Quote Link to comment Share on other sites More sharing options...
PainKKKiller Posted March 13, 2017 Author Share Posted March 13, 2017 I am check it with console.log in plugins callback, It was the first thing I did think of. Brenwell 1 Quote Link to comment Share on other sites More sharing options...
Brenwell Posted March 13, 2017 Share Posted March 13, 2017 I have done some further research and I have found at least one of the possible issues. PIXI.extras.AnimatedSprite extends PIXI.Sprite, which assumes the concept that it has one BaseTexture. Creating an AnimatedSprite from frames from multiple sources still results in an AnimatedSprite with one BaseTexture, it appears to choose the last frames texture as the BaseTexture. Then when you run the prepare plugin it uses a function called `findBaseTextures` which uploads the baseTexture of an item to the GPU. In the case of an AnimatedSprite it uploads only the one texture, meaning one is the GPU and the others are not and when you play you AnimatedSprite it has to load any other things into the GPU at that time. Hence the laggy playback. I might place all this info in the PIXI issue tracker, see If I can get some help. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 13, 2017 Share Posted March 13, 2017 Just checking does not help. You have to start rendering only after the callback fires. Quote Link to comment Share on other sites More sharing options...
Brenwell Posted March 13, 2017 Share Posted March 13, 2017 I am pretty sure my jsfiddle is correct app.renderer.plugins.prepare.upload(sprite,function(){ console.log('uploaded animated sprite') enableButton() }) ... function enableButton(){ var button = document.getElementById('button') button.disabled = false button.innerHTML = 'Ready, play animation' button.addEventListener('click',function(){ if(!app || !app.stage) return console.log('click') app.stage.addChild(sprite) sprite.gotoAndPlay(0) }) } Quote Link to comment Share on other sites More sharing options...
Brenwell Posted March 13, 2017 Share Posted March 13, 2017 just in case my link is to an old version here is the latest https://jsfiddle.net/brenwell/pbts8c0y/10/ Quote Link to comment Share on other sites More sharing options...
Brenwell Posted March 13, 2017 Share Posted March 13, 2017 Ok, so I posted an issue on Github and I am pleased to see that my researching was not for nothing. The current state of the prepare function will not work with an AnimatedSprite with multiple BaseTextures. https://github.com/pixijs/pixi.js/issues/3829 ivan.popelyshev and themoonrat 2 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.