Alex_Matveev

Used big size texture

Recommended Posts

After loaded images (5640x470)
Created movie clip:
var birdIdle = PIXI.BaseTextureCache[GAME.Assets.BIRD_IDLE];var partTexturebirdIdle0 = new PIXI.Texture(birdIdle, new PIXI.Rectangle(0, 0, 470, 470));var partTexturebirdIdle1 = new PIXI.Texture(birdIdle, new PIXI.Rectangle(470, 0, 470, 470));var partTexturebirdIdle2 = new PIXI.Texture(birdIdle, new PIXI.Rectangle(470 * 2, 0, 470, 470));var partTexturebirdIdle3 = new PIXI.Texture(birdIdle, new PIXI.Rectangle(470 * 3, 0, 470, 470));var partTexturebirdIdle4 = new PIXI.Texture(birdIdle, new PIXI.Rectangle(470 * 4, 0, 470, 470));var partTexturebirdIdle5 = new PIXI.Texture(birdIdle, new PIXI.Rectangle(470 * 5, 0, 470, 470));var partTexturebirdIdle6 = new PIXI.Texture(birdIdle, new PIXI.Rectangle(470 * 6, 0, 470, 470));var partTexturebirdIdle7 = new PIXI.Texture(birdIdle, new PIXI.Rectangle(470 * 7, 0, 470, 470));var partTexturebirdIdle8 = new PIXI.Texture(birdIdle, new PIXI.Rectangle(470 * 8, 0, 470, 470));var texturesBirdIdle = [partTexturebirdIdle0, partTexturebirdIdle1, partTexturebirdIdle2,partTexturebirdIdle3, partTexturebirdIdle4, partTexturebirdIdle5,partTexturebirdIdle6, partTexturebirdIdle7, partTexturebirdIdle8];var birdIdleMC_0 = new PIXI.MovieClip(texturesBirdIdle);birdIdleMC_0.play();this.container.addChild(birdIdleMC_0);

But in mobile i have error (very big images not more 4096)

Can create more baseTexture from one baseTexture.
 
P.s Problem only on mobile device
 

Share this post


Link to post
Share on other sites

You will need to split your asset into multiple images, and therefore multiple base-textures, 5640x470 is pretty big (8MB).

 

Depending on device a max texture size of 4096x4096 is pretty common, stay below that. In fact, your current texture could fit in that range if you rearrange it a bit.

 

See: http://webglstats.com/ near the bottom for MAX_TEXTURE_SIZE stats.

Share this post


Link to post
Share on other sites

Sorry, but i can't create new base texture.

Look:

var birdIdle = PIXI.BaseTextureCache[GAME.Assets.BIRD_IDLE];var tmpCanvas = document.createElement('canvas');tmpCanvas.width = 470 * 9;tmpCanvas.height = 470;var ctx = tmpCanvas.getContext('2d');ctx.drawImage(birdIdle.source, 0, 0);var imageData0 = ctx.getImageData(0, 0, 470*8, 470);var partBaseTexture0 = new PIXI.BaseTexture(imageData0);var imageData1 = ctx.getImageData(470*8, 0, 470*9, 470);var partBaseTexture1 = new PIXI.BaseTexture(imageData1);

partBaseTexture0 and partBaseTexture1 empty 

Share this post


Link to post
Share on other sites

So I have a question I haven't been able to look up an answer for that relates to this thread. I suppose it's a question best suited to you Xerver.

Say you have a very large image as Alex_Matveev has. Let's also say that you have to display the whole image on screen at one time.

Would it be faster to split the image up into some number of smaller parts and make more base textures and then show all of them on the screen all at once? If so, why would it perform better if the end result is the same amount of pixels on the canvas?

Thank you.

Share this post


Link to post
Share on other sites

Would it be faster to split the image up into some number of smaller parts and make more base textures and then show all of them on the screen all at once

 

No, there would be multiple draw calls instead of one so it would be slower. But you literally may not be able to send all the memory for that texture to the GPU at once anyway so you would *have* to break it up. He isn't splitting it up to increase performance, he is splitting it up because it is just too big to fit in a single texture memory alloc.

Share this post


Link to post
Share on other sites

Would it be faster to split the image up into some number of smaller parts and make more base textures and then show all of them on the screen all at once

 

No, there would be multiple draw calls instead of one so it would be slower. But you literally may not be able to send all the memory for that texture to the GPU at once anyway so you would *have* to break it up. He isn't splitting it up to increase performance, he is splitting it up because it is just too big to fit in a single texture memory alloc.

 

Hi, Thanks for the reply :)

 

My next question may be a little long winded, but I have to speak in very specific terms because I'm so new to pixi.js and the canvas element in general. Therefore, the underlying actions that pixi takes and just what is REALLY going on in the belly of the beast is mostly a mystery to me and I'm not quite sure how to fully articulate my thoughts. 

Also, if you think this questions belongs in a new thread, please let me know.

 

Ok, so basically I'm trying to figure out how to maintain performance while allowing a large graphic on the canvas. (by "graphic", I don't necessarily mean PIXI.Graphics, please forgive the constant misuse of the proper jargon throughout this question :) ) The image/graphic in question is an isometric "map" that pretty much the entire game performs on. It's a large grassy grid surrounded by "environmental elements" (moutains, crystals) in the non-playable areas. This image/texture/graphic/sprite/whatever alone is approximately 5000px in width and 3500 px in height. If I just make a texture out of that bad boy and render it to the canvas without moving it or doing anything to it, I get something around 10-20 fps at best. 

Now, if the game constrained you to never seeing the full "map" then I think tiling the large image and then culling the out of view tiles would probably be the answer and the end of the discussion. However, the games design dictates that the player should be allowed to zoom out and see the whole map. Which would therefore put all of the tiles of the map on the screen. I can only assume that this would be just as bad as having the whole image on the screen un-tiled.

Now, the "zooming out" I figured can be achieved by scaling the display object that the map is on. Does scaling the display object cause any more performance issues? There would be less total pixels on the canvas if the display object was scaled down, but I'm not sure if that's any better.

Would scaling/reducing and moving the tiles of the island (while culling off screen tiles) instead of scaling the whole display object be better? If I did that, I could also possibly utilize a mipmapping system to use smaller map iamges as you zoom out. 

 

And then let's not forget about all of the things that go ON the map! Every "thing" that goes on the map would be a 16 frame (4x4) animated sprite sheet. I've already figured out how to show only a fame of the sprite sheet and move through them in pixi to get it to animate. So there's no problem there! I modified the bunny mark demo to see how it would perform with large spritesheets (724 width x 612 height). I found that I wouldn't get very many images bouncing around when the full sprite sheets were visible. But when I did the new PIXI.TilingSprite(buildingTexture, 181,153) line and constrained the spritesheets the 181,153 I could put thousands on the screen before going lower than 30fps. So I realized that how many pixels was visible in the sprite is what mattered, not how many pixels were in the texture.

 

but... The map.... How am I going to get hundreds of animated sprite sheets (all framed down) on top of that map I mentioned earlier which by itself is a bit of a fps hog?

AND I was hoping to use Spine animations with all of my "creatures"! (I don't need help with that right now, just mentioning it to show the complexity of what I'm trying to achieve on screen).

Add a UI and whatever else comes up and there's going to be a lot needing to be painted to the screen. I just know that canvas with pixi.js can put all the little things on the screen and I'll still have room to wiggle. My biggest concern is that map. 

 

So TL;DR

What's the best method for putting a very large image on the screen, given that sometimes you will need to see the whole image at once in a "zoomed out" state and still have enough processing power to add hundreds of other animating sprite sheets on top of it? Scaling, culling, and mipmapping are all things that I'm willing to try if I need to (as well as anything other suggestions or combinations thereof)

 

Sorry for so many questions, and thank you for your time! Again, please let me know if I should start a new thread for these questions.

 

Thanks.

 

P.S.

If I have a lot of animated sprite sheets, should I put multiples of the same kind (more than one of the same kind of building) on their own display object and use SpriteBatch? If I did that, I would end up with about 50 different display objects if a player managed to get all of the different kinds of buildings on their map. Which makes me think, should I put the map on its own display object? Does having more than one display object even make a difference in anything? Thanks :)

Share this post


Link to post
Share on other sites

Tilemaps are what solve your case. Think about google maps. They have a huge map with lots of items that can be zoomed in and out.

 

The way that works is the world is divided into tiles, only the tiles that are visible at any given time are actualkly drawn. For zooming, you don't use the same tiles when zooming out, you use "zoomed out" tiles. So you actually switch to a different set of tiles that represent the "zoomed out" version of the map. That way when zooming out you never really have more tiles to draw, you just draw something different.

Share this post


Link to post
Share on other sites

The way that works is the world is divided into tiles, only the tiles that are visible at any given time are actualkly drawn. For zooming, you don't use the same tiles when zooming out, you use "zoomed out" tiles. So you actually switch to a different set of tiles that represent the "zoomed out" version of the map. That way when zooming out you never really have more tiles to draw, you just draw something different.

 

That... makes perfect sense.. I think :)

 

I guess this isn't really mipmapping, but it's cousin. 

I should take my huge imageand then split it into multiple image tiles at it's native resolution. How many image tiles? I'm not sure. I guess that depends on just how much will be going on on the screen when fully zoomed in and full screen.

Then I should take the big image and reduce it's resolution/size, then split it up into the same number of tiles as I figured for the full one? Maybe less?

Then I should keep doing that for however many zoom level transitions I think are necessary. 

Then I need to figure out how to cull out the off screen tiles and then make a smooth mouse scroll-able zoom between all of the assets.

 

Do you think that the "zooming" should be done by scaling the sprites and shifting their positions and then swapping the images and re-scaling/positioning?

Or should I put each zoom level on it's own display object and then hide and show them at the appropriate times?

 

Thanks again for all your help

Share this post


Link to post
Share on other sites

The implementation I described exists at: https://github.com/englercj/phaser-tiled

 

Particularly the tilelayer: https://github.com/englercj/phaser-tiled/blob/master/src/tiled/Tilelayer.js

 

I would have them both ready to go in DOCs and turn them on/off depending on zoom level. Basically you split your world image into tiles (sizes depend on your use-case), then scale down your large image by some factor and split *that* into tiles, then do it again, etc. Until you what can make the effect seem nice for your use-case, generally you scale the tiles a bit until you reach a certain point where you switch to the other tiles. Wash, rinse, repeat.

Share this post


Link to post
Share on other sites

I guess this isn't really mipmapping, but it's cousin. 

 

 

I think it is exactly mipmapping. If webgl-only solution is ok for you, set the texture's mipmap property to true(make sure you do that before the texture is used and its width and height are power of two) and PIXI will make use of opengl mipmapping.

 

 

How many image tiles? I'm not sure.

 

As few tiles as possible, but small enough tiles to fit in the device's MAX_TEXTURE_SIZE. In your case, just split it into two pieces and both of them will be below 4096.

 

 

 

Do you think that the "zooming" should be done by scaling the sprites and shifting their positions and then swapping the images and re-scaling/positioning?

Put everything inside a parent DOC and only scale that DOC.

 

 

"Every "thing" that goes on the map would be a 16 frame (4x4) animated sprite sheet."

You should combine them into a single texture atlas, see this: http://www.html5gamedevs.com/topic/11747-particles-system/

Share this post


Link to post
Share on other sites

...set the texture's mipmap property to true...

 

How would you go about doing that? I cant find that in the documentation

 

  

"Every "thing" that goes on the map would be a 16 frame (4x4) animated sprite sheet."

You should combine them into a single texture atlas, see this: http://www.html5gamedevs.com/topic/11747-particles-system/

If I did that... there's at least 50 different 4x4 sprite sheets. Each sprite sheet is 724 x 612. That'll make a huge, huge image. Aren't there downfalls there?

Thanks your your suggestions!!

Share this post


Link to post
Share on other sites

 

How would you go about doing that? I cant find that in the documentation

 

The documentation is out of date :(

If you use AssetLoader, get any of your textures by Texture.fromFrame and then its baseTexture and set mipmap = true. I'm sure there's a prettier way to get the baseTexture... but this works:

myAssetLoader.onComplete = function () {    var tree = PIXI.Texture.fromFrame('tree.png');    tree.baseTexture.mipmap = true;

That's it, zoom as you wish and it will use the correct mipmap level.

 

 

If I did that... there's at least 50 different 4x4 sprite sheets. Each sprite sheet is 724 x 612. That'll make a huge, huge image.

 

So you'll need two 4096x4096 texture atlasses. Create 2 SpriteBatches and make sure all sprites on spiteBatch1 get their textures from baseTexture1 and all sprites on spiteBatch2 - from baseTexture2.

 

 

Aren't there downfalls there?

Well, It's much better than multiple textures. As long as it fits in texture memory :)

 

 

Thanks your your suggestions!!

No problem ;)

Share this post


Link to post
Share on other sites

Hey thanks again! This is very helpful to someone that's never worked on the canvas before. 
 

Well, It's much better than multiple textures. As long as it fits in texture memory :)


Can you explain why that is? I know the answer is probably a little technical, but that's fine.

 

To me, several assets or bigger assets are still the same "size" (pixels and bytes).

I get how larger but fewer files are better for downloading speed, but how is it better for performance?

 

Thanks!

Share this post


Link to post
Share on other sites

Can you explain why that is? I know the answer is probably a little technical, but that's fine.

Drawing using webgl works like this: you upload the vertex array and the texture to the GPU, and then call gl.drawElements(....). It works faster if you draw a large array of vertices each time and thus call drawElements less often. A texture atlas is a single texture as far as GPU is concerned, so you can draw everything with a single drawElements call, while using multiple textures forces you to call drawElements multiple times.

Share this post


Link to post
Share on other sites

Drawing using webgl works like this: you upload the vertex array and the texture to the GPU, and then call gl.drawElements(....). It works faster if you draw a large array of vertices each time and thus call drawElements less often. A texture atlas is a single texture as far as GPU is concerned, so you can draw everything with a single drawElements call, while using multiple textures forces you to call drawElements multiple times.

 

Thanks! That makes a lot of sense!

What about if you were constrained to having to use CanvasRenderer? Would you still benefit from this method? (I'm not constrained, but just curious) 

 

Thanks!

Share this post


Link to post
Share on other sites

Thanks! That makes a lot of sense!

What about if you were constrained to having to use CanvasRenderer? Would you still benefit from this method? (I'm not constrained, but just curious) 

 

Thanks!

 

No, on the canvas each thing that is "drawn" is a call to "drawImage". Regardless of if they are from the same base image. Using a common base texture is a huge performance boost for webgl and makes no change to canvas.

Share this post


Link to post
Share on other sites

No, on the canvas each thing that is "drawn" is a call to "drawImage". Regardless of if they are from the same base image. Using a common base texture is a huge performance boost for webgl and makes no change to canvas.

 

Ok then, so if you were constrained to using canvas only, would making larger texture atlases be any worse than another option?

 

thanks!

Share this post


Link to post
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.