Minimog

Members
  • Content Count

    7
  • Joined

  • Last visited

About Minimog

  • Rank
    Newbie

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. I tried to find answers to these questions online, but was only partially success-full and most of the info I found was for pixi v3 version. Given that we are now on v5 and few things changed, I decided to ask this here to better understand pixi and webgl in general for optimising big amounts of assets. A small intro to my project I am working on a mobile / web game that relies on images for it's ui / characters / items / backgrounds etc. In some places we are talking high detail, fullscreen graphics for characters, something similar to this: https://www.artstation.com/artwork/n616E that have more graphics on top of them (equipment slot ui / equipment item graphics). As you can imagine to have these appear nice and crisp on retina devices some images can be rather big i.e (1125x2436 for a full screen iphoneX screen). And my game has a lot of these. My current experience with pixi and what I am doing now Right now I am not doing anything crazy. I have a loader that generates sprites for all my textures. I did however ran into an issue where some of the bigger character graphics caused lag when their scene was displayed because they were being uploaded to GPU (I think?). I was able to solve this issue by using renderTextures, what I did was map through all loader resources, created sprites, rendered them on render textures and stored those references for future sprites. I actually had separate question about this here My questions / concerns In general my approach so far has been working good, I see smooth animations and memory usage (at least what I see in XCode when I run app on my phone) looks good. I did start noticing few small hick-ups here and there though further into my development and am concerned that I am loading too many assets now. Furthermore I saw few posts saying that webgl can't handle many textures / big textures and this concerns me. What I want to do now is create separate loaders, so I don't load everything at once and ensure I destroy and recreate my renderTextures as they are needed. I also want to start creating spritesheets to group my assets logically. I have following questions: 1. How big can these sprite-sheets be and how many of them can I have? (My lowest supported target is webgl 1 on safari) 2. Do I actually need to use renderTextures to ensure my graphics are ready to go at a moments notice, or is there a better approach? 3. When I use loader with my sprite sheets and create sprites from those sources, what do I need to destroy to cleanup? Just loader, or also sprites and texture sources? 4. And in general what approaches / practices would you recommend for handling 100's of assets like examples below in a game designed for high density displays? 5. Is pixi even suitable for this kind of project? examples (not from my game, but I guess you can picture how big in terms of pixels these can get and there are many of them) https://www.artstation.com/artwork/n616E https://www.deviantart.com/maumonts/art/ITEM-ART-World-of-Reos-795990267 https://www.deviantart.com/francescabaerald/art/Map-of-Middle-Earth-Lord-of-the-Rings-642266670 https://www.deviantart.com/evil-s/art/Burnblade-UI-516602551
  2. @ivan.popelyshev You are tight, I didn't even know renderTexture achieved what I wanted to do with prepare. I cleaned up the code and added appropriate destroy methods, could you please give this a final glance to confirm that I understood everything correctly. Only caveat here that I can't figure out when comparing this to prepare plugin, is how can I know when renderTexture is loaded to gpu? Prepare provided a callback for this. Or is renderTexture gpu upload synchronous? loader.load((_, resources) => { const sprites = {}; Object.keys(resources).forEach(key => { const texture = resources[key]?.texture; const sprite = new Sprite(texture); const { width, height } = sprite; const renderTexture = RenderTexture.create(); // Resize image if it is too big for the device if (width > maxWidth) { const ratio = height / width; const maxHeight = maxWidth * ratio; renderTexture.resize(maxWidth, maxHeight); sprite.width = maxWidth; sprite.height = maxHeight; } else { renderTexture.resize(width, height); } renderer.render(sprite, renderTexture); sprites[key] = new Sprite(renderTexture); sprite.destroy(); texture?.destroy(); }); loader.reset(); loader.destroy(); });
  3. Just to add to the above, calling reset and destroy methods on loader seems to also work. I looked up sprites in chrome's memory profiler and ones stored there are correct renderTextures
  4. @ivan.popelyshev Alright, I tried to do that after it's been uploaded to GPU i.e following my example above renderer.plugins.prepare.upload(sprite, () => { resources[key]?.texture.destroy(true); }); But this throws various errors related to sprite scale / width etc being undefined. It feels like old texture is still being referenced somewhere. Can this be the case with my previous example above?
  5. @ivan.popelyshev Gotcha, so just to confirm that I am cleaning everything up correctly here is a snippet that works for me and resizes everything correctly, am I correct assuming that the only cleanup I need to do here is destroy a loader with original textures? loader.load((_, resources) => { const sprites = {}; Object.keys(resources).forEach(key => { const sprite = new Sprite(resources[key]?.texture); const { width, height } = sprite; // maxWidth is pre-determined beforehand if (width > maxWidth) { const ratio = height / width; const maxHeight = maxWidth * ratio; const renderTexture = RenderTexture.create({ width: maxWidth, height: maxHeight }); sprite.width = maxWidth; sprite.height = maxHeight; renderer.render(sprite, renderTexture); sprites[key] = new Sprite(renderTexture); } else { sprites[key] = sprite; } }); // sprites object is then sent to prepare plugin loader.destroy(); });
  6. I am working on a game that has few background graphics, these are stored in app bundle at big resolutions like 2000x2000 pixels to support bigger devices like iPad pro. Obviously something this big is an overkill for mobile and I wanted to ask if following optimisation assumption is correct: 1. I preload these assets with pixi loader 2. I create sprite for each texture 3. I then resize this sprite to fit device dimensions better i.e. 1000x1000 px for iphone When I inspect my sprites textures I still see them at 2000x2000 pixels even though sprite itself is 1000x1000. I am concerned that I am not optimising this correctly, especially because I use prepare plugin https://pixijs.download/dev/docs/PIXI.Prepare_.html for some of these assets, I upload my sprites not textures, but I still feel like I might be uploading those big 2000x2000 assets alongside which is a problem, as these occupy a lot of GPU memory. Hence this thread to clarify if my approach to this problem is correct. I don't want to create separate asset resolutions i.e. 2x / 3x etc if possible to avoid increasing final app bundle size.
  7. I made simple recreation available at Codesandbox In essence following code triggers alert function when I click on a text even though my interaction listener is set on the sprite. I was under impression that pixi handles this case (when element is covered by another), but I guess I was wrong. Is there a way to only fire interaction if I click on sprite explicitly and not on any element that is covering it? Code import * as PIXI from "pixi.js"; const application = new PIXI.Application({ resolution: window.devicePixelRatio, autoDensity: true, width: window.innerWidth / 1.2, height: window.innerHeight / 1.2, view: document.getElementById("app"), backgroundColor: 0x0000ff }); const sprite = PIXI.Sprite.from(PIXI.Texture.WHITE); sprite.width = window.innerWidth / 1.5; sprite.height = window.innerHeight / 1.5; sprite.interactive = true; sprite.addListener("pointertap", () => { alert("Click!"); }); const text = new PIXI.Text("Hello World"); text.style = { fontSize: window.innerWidth / 10 }; application.stage.addChild(sprite); application.stage.addChild(text);