Vousk-prod. Posted March 29, 2015 Share Posted March 29, 2015 Hello boys (and girls, maybe... I hope ), Is it possible to create a new BABYLON.Texture from a particular area of texture file instead of the whole file ? In some cases, to avoid too much http requests, it would be usefull to download only a few spritesheets and be able to assign a sprite to a BABYLON.Texture instead of whole a file, is that possible ? Quote Link to comment Share on other sites More sharing options...
fenomas Posted March 30, 2015 Share Posted March 30, 2015 Hello boys (and girls, maybe... I hope ), Is it possible to create a new BABYLON.Texture from a particular area of texture file instead of the whole file ? In some cases, to avoid too much http requests, it would be usefull to download only a few spritesheets and be able to assign a sprite to a BABYLON.Texture instead of whole a file, is that possible ? I've been working on this. You can do it but it's not built in or anything, you have to wrangle the uv scale and offset of each material. Also, at least in my tests I had to leave two blank pixels between sprites to avoid bleeding. It would be might handy if BJS supported one of the various spritesheet formats. Quote Link to comment Share on other sites More sharing options...
RaananW Posted March 30, 2015 Share Posted March 30, 2015 If you want to use one single texture with different u and v offsets you will have to either change the UV coordinates (suprisingly, it was discussed a few days ago here - http://www.html5gamedevs.com/topic/13420-display-one-video-on-multiple-objects-with-the-videotexture/) or "duplicate" the texture and set different offsets an scales. The current relation between texture and ov offset and scale is 1-to-1. You can't change one without the other, but you can count on the browser's and babylon's cache mechanism to actually support that. create different textures using the same url for a single image, and it won't be downloaded multiple times. This is the safest solution I see for regular images. You can then set new u and v offsets:http://www.babylonjs-playground.com/#1GLIH9this is just a simplified version of the materials demo in the playground. check how many requests are sent and you will see the file is only loaded once. Quote Link to comment Share on other sites More sharing options...
Vousk-prod. Posted March 30, 2015 Author Share Posted March 30, 2015 Yep I know that a single file is never downloaded multiple times, that's a big great feature of BJS !! I'm not sure changing the materials UV is the right way to go, they're pretty complex, coming from objects unwrapping and they're finely tuned for correct lightmapping, bump, etc... I think it would be interesting to simply have a method that creates a BABYLON.Texture array from a single spritesheet (supporting one of the various spritesheet formats, as fenomas suggested).For instance, if a 1024x1024 spritesheet contains 128x128 sprites, we'll get 64 BABYLON.Texture. We then use them as usual, no material UV modification needed. Quote Link to comment Share on other sites More sharing options...
fenomas Posted March 30, 2015 Share Posted March 30, 2015 I think it would be interesting to simply have a method that creates a BABYLON.Texture array from a single spritesheet (supporting one of the various spritesheet formats, as fenomas suggested).For instance, if a 1024x1024 spritesheet contains 128x128 sprites, we'll get 64 BABYLON.Texture. We then use them as usual, no material UV modification needed. That would be 2D canvas operations - draw the texture into a canvas and then read out subsections. BJS already does something similar to convert textures to power-of-two sizes. However, the point of using texture atlases is generally to avoid texture binds, and splitting one into separate textures would lose that benefit. I expect the ideal thing would be for BJS to grok texture atlases in such a way that the user doesn't have to wrangle all the scales and offsets, but behind the scenes the whole atlas texture stays intact. Quote Link to comment Share on other sites More sharing options...
RaananW Posted March 30, 2015 Share Posted March 30, 2015 (edited) This is a very simple function to implement - in the case of what you just suggested:var imageUrl = "http://www.awsomeserver.com/someSillyCat.jpg";var meshesArray = getMyMeshes(); //well, this is up to you :-)var spriteWidth = 8;var spriteHeight = 8;for(var w = 0 ; w < spriteWidth ; ++w) { for(var h = 0 ; h < spriteHeight; ++h) { var texture = new BABYLON.Texture(imageUrl, myScene); texture.uScale = 1/spriteWidth; texture.vScale = 1/spriteHeight; texture.uOffset = w - spriteWidth/2; texture.vOffset = h - spriteHeight/2; meshesArray[w*spriteHeight + h].material.diffuseTexture = texture; }}I have to admit I haven't tested this, but it should work. Edited March 30, 2015 by RaananW Quote Link to comment Share on other sites More sharing options...
RaananW Posted March 30, 2015 Share Posted March 30, 2015 Correcting my initial post - http://www.babylonjs-playground.com/#1GLIH9#4 the offset should be calculated differently, but it works. There, sprites for meshes :-) Quote Link to comment Share on other sites More sharing options...
Vousk-prod. Posted April 1, 2015 Author Share Posted April 1, 2015 Thanks RaananW for this example. I like the idea, but I'm not sure it's totally perfs friendly...for(var w = 0 ; w < spriteWidth ; ++w) { for(var h = 0 ; h < spriteHeight ; ++h) { textures[index++] = new BABYLON.Texture("textures/earth.jpg", scene); texture.uScale = 1/spriteWidth; texture.vScale = 1/spriteHeight; texture.uOffset = (w - spriteWidth/2) + 0.5; texture.vOffset = (h - spriteHeight/2) + 0.5; }}The idea of creating textures from a spritesheet is to avoid too much HTTP requests. For that, your idea is great. But this will create a lots of textures in memory. That's not a big deal for a realtime engine if those textures are small (at sprite's width and height resolution), but here those textures will be really big (at spritesheet's width and height resolution).Pretty sure that will kill memory, particularly on mobile devices. Apart from that, there also are some cases where we need to change texture's UV scale or offset for a particular object, but it will be impossible here, since that won't just change the we will not change the aspect of the texture but also its content... Is it possible to take a picture and to cut it in part and then to use that parts to create Texture objects ? That would do the trick. Quote Link to comment Share on other sites More sharing options...
Vousk-prod. Posted April 1, 2015 Author Share Posted April 1, 2015 Or, as fenomas suggested, since the point of using texture atlases is generally to avoid texture binds, and splitting one into separate textures would lose that benefit, maybe BJS could have a method to assign to material a spritesheet texture (specifying which sprite to use). I don't know if this would be optimised or not in terms of performances. Quote Link to comment Share on other sites More sharing options...
RaananW Posted April 1, 2015 Share Posted April 1, 2015 Hi, sorry, just saw your last message.You are right, this will create quite a lot of textures with the same image, but i doubt it is using more memory (haven't tested thou), as the images come from babylon's cache and not the browser's cache - https://github.com/BabylonJS/Babylon.js/blob/master/Babylon/Materials/Textures/babylon.texture.ts#L65 . It is using the cache for the texture, and it is only stored once. So the only memory used is the texture class and not the image, which is not too large. Setting the uv offset and scale on your own would be possible if you provide a certain "sprite manifest", much like the css sprite definitions. This of course requires the frameworks support, but I have to admit would be a nice feature. You could also do it already at the scene's file (set all of those variables by yourself), and then no need for any framework extension at all. I am not sure what will one big texture improve, this has to be tested, but it is of course possible - put all textured loaded textures onto acanvas and store as as png in the cache (for example). Or use it directly. I believe however this will create unneeded load on the GPU, as this texture will have to be sent everytime the object is being rendered. And as png/jpg are totally not GPU optimized, that would mean that the entire texture will have to be decompressed. Not so nice when it comes to large textures... Quote Link to comment Share on other sites More sharing options...
Vousk-prod. Posted April 1, 2015 Author Share Posted April 1, 2015 Yes, images files are stored in cache, but once the textures are instanciated in the engine they're allocated as separate objects in GPU memory, aren't they ? I do not exactly know how the GPU works but I think each different texture object allocated take its own space in GPU memory (and for realtime engine, the higher the resolution, the -very- higher memory amount needed). Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted April 1, 2015 Share Posted April 1, 2015 No, if you create 10 x BABYLON.Texture on the same file, in GPU memory only one texture is created Quote Link to comment Share on other sites More sharing options...
Vousk-prod. Posted April 1, 2015 Author Share Posted April 1, 2015 What a piece of info! That's a great news! Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted April 1, 2015 Share Posted April 1, 2015 My job in this affair is to guarantee that things are performant but simple to use Quote Link to comment Share on other sites More sharing options...
Vousk-prod. Posted April 1, 2015 Author Share Posted April 1, 2015 And we are lucky you're good at it GameMonetize 1 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.