I have an image consisting of many images arranged nicely as tiles, and want to use each tile as a separate texture. Is there anyway to load the whole image and crop the part I want as a texture? The solution of adjusting texture coordinates on a material to bound an individual tile does not appeal to me because I like to use all materials and all textures in a uniform manner, if possible. The reason is each individual tile is meant to be a full-citizen texture, they just happen to live in a single image.
Well, that kind of IS the solution. What you describe is a texture atlas. Texture atlases are based on texture coordinates.
Else you will have to split the image into multiple images yourself and take the performance hit of having a ton of textures instead of just one.
Here are some thoughts on that matter:
texture atlas:
- If you use texture min/mag filters with mipmaps, your tiles must be a power of two size - e.g. 64x64 tiles in a 1024x1024 texture. Which will then work for the first 6 mipmap levels and break at the 7th mipmap level, because the tiles âbleedâ into each other (âcolor bleedingâ is actually the term for that phenomenon).
- You will get problems with âwrap aroundâ - i.e. when trying to use a large polygon with one of your tiles repeating multiple times, then strange lines will appear between the repetitions. This comes from having different pixels next to your quad. I observed this behavior when writing a special shader with tiled textures. Note: this is not a problem if you use the tiles on e.g. quads (max number of repetitions is 1).
- Texture atlases are often used for game characters and objects and to avoid the problems above, special care must be taken - example: configure a margin of 8 or 16 pixels when you bake your textures in Blender - which then minimizes âcolor bleedingâ (parts in such an atlas are not power two tiles but random sized n-gons) and it also fixes âwrap around artifactsâ (when using a special tile-based shader)
other (better?) solution:
- In more recent versions of OpenGL you have âtexture arraysâ or âarray texturesâ
- I donât know if jME 3.0 or 3.1 support that feature (but I would like to know)
- I donât know what kinds of graphics cards support that feature (driver version, GL version)
- But itâs definitely going to solve the problems of a texture atlas
- Another possi might be to use a â3D textureâ (sampler3d) which is quite an old feature (I think) and then you would simply put your tiles as slices in the w-coordinate (u and v are sampler2d, w is the third axis)
Not sure what you are trying to do - so I just said everything that came to my mind regarding that topicâŚ
@pspeed, thanks for the reply. I actually tried to use TextureAtlas before I post my question. In Libgdx, I can have a âsprite sheetâ and use TextureRegion to designate the different tiles as separate textures. It is conceptually very simple. TexturePacker is easy to use. For nice tile maps, it is straight forward to manually create the âatlasâ by using a notepad (that is actually how I create).
Unfortunately the scene graph support of Libgdx is weak. I decided to convert my games to JMonkey. I am less familiar with JMonkey; it seems JMonkeyâs TextureAtlas is a different concept, am I right?
I am currently working on a 2D game. I will add 3D feature after I port the game. If I already have a sprite sheet. Do I have to cut the tiles and save them as individual images on my hard drive before loading them back to JMonkey as different textures? It is much easier for me to edit the sprites if they are all on one single sheet; thus I donât want to cut them up.
I am thinking the second possibilities is to load the sprite image as one BufferedImage and draw the individual tiles on smaller BufferedImage and convert them to Texture. This seems straight forward, does JMonkey has built-in functions such as loadBufferedImage() and bufferedImageToTexture()?
Can TextureAtlas be used to avoid all these mess? If so, can you give me a hint how to do it. Thanks
Ah, this is about sprite sheets and 2d games. That changes a lotâŚ
Did you look at jme3test.tools.TestTextureAtlas.java ? It demonstrates the jME texture atlas.
What do you mean by âcreate the âatlasâ by using a notepadâ ? I assume you mean a text editor?
When I think how my workflow would look ⌠I would also prefer editing all on one image.
But I would want to have a nice tool for it - not a text editor. Something to mark rectangles which are then saved to a file like: image_name.txt or image_name_meta.txt and then use a text editor to edit those meta info files. Even better is a tool that combines both: image editor and a panel for the text - similar to the svg editor âInkscapeâ (lets you edit the xml text while editing the vector graphics at the same time) - so you can give the texture regions names while still editing them.
@Ogli, The âatlasâ in Libgdx is actually a simple ASCII file annotating the âtilesâ in the sprite sheet. It may looks like:
vehicles.png format: RGBA8888 filter: Nearest,Nearest repeat: none airplane rotate: false xy: 10, 150 size: 280, 200 orig: 280, 200 offset: 0, 0 index: 4 ...
To use the atlas, just load the text file, Libgdx will then know how to craft the texture region âairplaneâ. The Libgdxâs Texture Packer can aggressively (optimally) places individual images of different sizes in a single bigger image, and write the âatlasâ. For an already packed sprite sheet, there is no juggling of the tiles, hence it is very easy to generate the âatlasâ (or create by hand, if necessary) â just write the actual position of the tiles to a text file.
Ah ⌠Aha ⌠I just watched this ⌠Creating and Using Spritesheets in LibGDX - YouTube
âTexture atlasâ (.atlas) is the libgdx term for the image_name_meta.txt that I sketchedâŚ
âSprite sheetâ is the thing that in jME is called âTexture atlasâ.
EDIT:
Saw your text popping up at the same time. :chimpanzee_grin:
Okay ⌠so you see how important context and exact words areâŚ
I doubt that jME has support for .atlas files (and does not seem to have a concept for that either).
You could write some custom code that reads .atlas files (should be quite easy).
.fnt files is very similar in concept - it is very similar to .atlas files, but comes from a different corner. Iâm currently working on a .fnt2 format that might be âmissusedâ as .atlas files. But still those are all font-related. My .fnt2 files will also contain information that .atlas files contain (names for regions, image format and even sub-channel format).
In the end - itâs just some small text data written in a .atlas (or .fnt) file - and a large texture, that contains many smaller texture regions (in computer sience this is called âtexture atlasâ for 3d and âsprite sheetâ for 2d)âŚ
libgdx might be hiding the texture coordinates from you but it is almost certainly using them under the covers to implement this feature.
yes, the texture coordinates are in the .atlas files
Yes, the actual pixel coord are in the text file âatlasâ, I assume they will be converted to a fraction internally by Libgdx. Conceptually, the whole sprite sheet is a single Libgdxâs Texture, and the individual rectangles (sub-images) are Libgdxâs TextureRegion. To use the smaller sub-image texture, I just provide the single large Tetxure, and specify the TextureRegion. Since the single large image is common to many objects, I donât really need to worry about it. Conceptually, I can treat each small sub-image as a full-citizen texture in my game.
See the video I posted at [6:20] - [7:05] and [8:38] - [8:41] â he explains it.
Also note that I edited that post quite a bit to contain more useful information.
Thanks for the extra info. I am still trying to load the WHOLE sprite sheet in one SINGLE load, and use the sub-images in a simple manner.
To try to understand TextureAtlas, I cut the sprite sheet as tiles and save them as individual images, and then try the following:
TextureAtlas ta = new TextureAtlas(1024, 1024); Texture tex1 = assetManager.loadTexture(tileFilename1); ta.addTexture(tex1, "T1"); // master map is T1 Texture tex2 = assetManager.loadTexture(tileFilename2); // tex2 and tex1 will share same tex-coord (0,0) to (1,1) ta.addTexture(tex2, "T2", "T1"); // master map is T1 Texture tex3 = assetManager.loadTexture(tileFilename3); ta.addTexture(tex3, "T3", "T3"); // master map is T1 ...
But the above doesnât work. My understanding of TextureAtlas must be wrong. Even if it works, it doesnât solve my problem because it still require many individual image files because I might just load the individual image as a Texture directly.
So, if you already split the images up then you donât need texture atlas. It is taking multiple images and making them into an atlas. You already started with an atlas.
So basically you took an atlas, chopped it up, then turned it back into an atlas again. I mean, you can do it that way⌠but then youâd also need to show use the code where you are actually using the atlas. You set it up but you donât show us how you use it so itâs impossible to guess what could be wrong.
You are going through a lot of trouble to avoid calculating texture coordinates, though. Seems like you could read the atlas file and calculate them yourself and then just set them on your mesh as you like. Once calculated you could do it in one line of code per quad.
OkayâŚ
There are generally two pathes that you could take:
- Trying to build all new from scratch in jME (assets and game)
- Trying to convert your Libgdx assets, then code game with jME
path 1:
In fact, you are using it wrong. Look for âUsage examplesâ in this javadoc:
http://javadoc.jmonkeyengine.org/jme3tools/optimize/TextureAtlas.html
The geometry that you use will be your quads (whatâs the name for that in libgdx?).
You will need to serialize the resulting texture and quads (write to .j3o file) in prestep.
And then you will need to deserialize (load from .j3o file) them at game init again.
You probably will need to create lots of clones too (best have a pool for each type).
(If you need really many clones - like in bullet hell games - you need some tricks).
During your running 2d / 2.5d game you will make your clones visible/invisible.
â Thatâs all just my very basic ideas, others might explain the detailsâŚ
path 2:
You could use .atlas files and write some import logic or convert logic for that.
It sounds very simple to me, at least for the .atlas files and sprite sheets.
Then you could keep the workflow that you know for asset creation.
The rest should be similar to path 1.
Sorry, not really a full jME expert yet, maybe could help somehowâŚ
I really dont want to split the images. I split it just to try TextureAtlas. The reason I want to approach the way I approach is because: (1) sprite sheet is very common in 2D games (at least for amateur game developers), (2) most 2D game developer treat each sprite as an independent image, not part of the larger sprite sheet, (3) I have a somewhat high-level treatment of sprites in my Libgdx code base, I like to port the code as high level as possible.
I am interested in hiding the details of texture coord in JMonkey port, although I donât know how to do atm.
You just have to ask yourself if the port is really necessary and what you gain from it.
Your real intentions were very unclear to me at the beginning and are becoming important now.
Compare the engine features (you already start to notice that jME is not designed for 2d games).
But still there are very cool 2d games that people made (like âDotsâ).
And then there is this tutorial series:
The link is an excellent tutorial. I looked at that before and learned something. The game uses separate images for separate sprites, hence one texture per sprite. Since there is only a handful of sprites in that tutorial, so it is not a problem to have a few small images in the asset folder. No effort, at least in this particular tutorial, is attempted on using one single Texture.
If that game were done in Libgdx, (as far as sprites are concerned) it would be very natural to have all sprites live in one bigger image, and have the whole image as one single Libgdxâs Texture. Thus more efficient in rendering, without game developerâs effort at all!
I know JMonkey and Libgdx are not 2D game engines. But I want to be able to add a touch of 3D-ness to my 2D games. With this in mind, I believe both are the best choices for Java game developers. The deciding feature of choosing JMonkey is the scene graph.
We donât really have enough information to help you. You are trying to âbe compatibleâ with something but there will already be a thousand differences and it seems like you are going a loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong way to avoid:
quad.setBuffer(Type.TexCoord, 2, new float[]{x1/width, y1/height,
x2/width, y1/height,
x2/width, y2/height,
x1/width, y2/height});
To me it seems like it would take about five minutes to wrap that in something more palatable.
@pspeed: Your snipcode is exactly what I need! Thanks a lot!!! I was playing with the material and TextureAtlas earlier. I didnât know that it is so simple to set texture coord in the quad.
Now I can have the whole sprite sheet as a single Texture and use the sub-images as tiles! I can hide this details easily in my own code, and thus use the higher level stuff from my Libgdx code!
You guys are great. Really glad that I started exploring JMonkey.