Hello monkeys !
I’m designing a TextureAtlas to a Voxel Engine, to have a better memory usage and such. But I have a question about how to design it, follow-me:
I have a big picture texture which I got on those Minecraft forum, just for testing, so it’s a Textured Tiled png file, where I have 16x16 textures of 128 pixels on ABGR8 format.
What I understand that I have to do is to load this image into a single Texture (which I named “atlas”) and get the needed sub textures from it, so If I need the texture placed on (3, 4) of atlas, I just return a sub texture originated from this bigger texture.
So, my question is, since the main atlas Texture is backed by an Image which is backed by a ByteBuffer, how I supposed to get a reference from this main ByteBuffer (the “atlas” one) which contains only the relevant sub texture without copying (allocating more memory) it to a new ByteBuffer??
I don’t know If I was clear enough but since the main goal of TextureAtlas is to have a single copy of a bigger tiled texture on memory, when I have to create small ByteBuffer (sub textures) from this atlas, i’m duplicating my needed memory, no?
Here is my piece of code, where I generate a new Texture based on main bigger tiled Texture. On bellow code, I duplicated the needed memory because i’m hosting a bigger texture (atlas) and sub textures:
private Texture getTexture(int x, int y) {
//The texture loaded on atlas contains less then 2GB, so get the first ByteBuffer;
List<ByteBuffer> list = atlas.getImage().getData(0);
//those a constants, but they are here just to illustrate.
int IMAGE_TILE_SIZE = 16;
int IMAGE_PIXELS = 128;
int IMAGE_CHANNELS = 4;
int IMAGE_BYTES = IMAGE_PIXELS * IMAGE_CHANNELS;
int IMAGE_SIZE = IMAGE_PIXELS * IMAGE_PIXELS * IMAGE_CHANNELS;
int IMAGE_ROW_SIZE = IMAGE_BYTES * IMAGE_TILE_SIZE;
int beginIndex = (x * IMAGE_PIXELS * IMAGE_ROW_SIZE) + (y * IMAGE_BYTES);
//This may be switched to a global temp buffer, to avoip allocating new arrays every time.
byte[] b = new byte[IMAGE_SIZE];
for (int i = 0; i < IMAGE_PIXELS; i++) {
buffer.position(beginIndex + (i * IMAGE_ROW_SIZE));
buffer.get(b, i * IMAGE_BYTES, IMAGE_BYTES);
}
//To create a new Image, I must have to send to constructor a new direct allocated ByteBuffer
Image img = new Image(Image.Format.ABGR8, IMAGE_PIXELS, IMAGE_PIXELS, ByteBuffer.allocateDirect(IMAGE_SIZE).put(b));
return new Texture2D(img);
}