-
Notifications
You must be signed in to change notification settings - Fork 698
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Discussion: Texture Packing and Texture Atlas #620
Comments
Yay, this will make custom fonts easy =) |
In theory it should increase frame rate for texture heavy scenes too. Maybe I should include my |
👍 for the text support if you're willing to open it up. |
@daveHD after thinking about it some I think it makes the most sense to make it an input to enable compression on the fly when the atlas output is added to the texture manager. I'm not sure if that's what you are describing but its how I would do it |
FWIW I'm @Davhed, not that Davehd guy :P That makes good sense. Enabling texture compression would be a param in the packing class:
Packing would be a one-time process, but mObject.addTexture(TextureAtlas.getBitmap(fileName)); // alternatively .getCompressedAtlas(fileName) It will also require modified UVs. Instead of a range of |
This makes me think we should integrate it into the new // -- create texture atlas
TextureAtlas atlas = mTextureManager.createTextureAtlas(String name, ... other params);
// -- ... do atlas stuff ...
// -- retrieve texture atlas
TextureAtlas atlas = mTextureManager.getTextureAtlas(String name);
// -- ... do atlas stuff ...
// -- create texture
TextureConfig config = new TextureConfig();
config.setAtlas(atlas);
config.setAtlasTextureName(textureName);
mTextureManager.addTexture(config); This way we can hide a lot of the implementation details from the user. Just thinking out loud here, you're welcome to shoot it down 👍 |
Sorry, I know the difference. Unfortunately the GitHub Android app does not have pop-up tagging so sometimes my spell correction gets in the way if I don't pay attention. If we can go with what @MasDennis presented, it would help in integrating to the task queue to make sure nothing funky happened to the developer when trying to create the new atlas. |
@MasDennis Oh yeah packing via So, with regards to the UV transformation, the logic in |
Yes,
The packing code will still be in the |
Brilliant, that makes good sense. Thanks for the direction help. I'm going to put some ground work for this together over the next couple of days. |
I have run into a question already, and I am hoping theres a good solution. As I mentiond before I'd like packing of textures to happen once at the start up of a given app. Packing consistes of four primary stages: Read in image assets, sort by size, draw images to the atlas, return the complete atlas + info. Currently this is how I am pulling in files: /*
* Retrieve asset names from "assets/atlas"
*/
AssetManager am = context.getAssets();
String[] fileList;
try {
fileList = am.list("atlas");
} catch (Exception e) {
throw new RuntimeException(e);
}
/*
* Pull atlas assets and convert to bitmaps for processing
*/
Bitmap[] atlasTiles = new Bitmap[fileList.length];
for(int i = 0; i < fileList.length; i ++){
try {
System.out.println(fileList[i]);
InputStream is = context.getAssets().open("atlas/"+fileList[i]);
atlasTiles[i] = BitmapFactory.decodeStream(is);
} catch (Exception e) {
throw new RuntimeException(e);
}
} As you can see I have opted to put a subdirectory in "assets", and I am pulling those files via |
Actually I think I might have found what I needed in
|
@Davhed Sorry, I was out at lunch. Yes that is the ideal solution. |
@jwoolston Hey no worries thank you for the confirmation! |
@Davhed I just remembered this annoying tidbit from Andorid Developers Website: http://developer.android.com/tools/projects/index.html
I am not certain how you were utilizing the assets folder, but something to think about before you get too far. |
@jwoolston What I am thinking is that the Side note: I figure that |
Unfortunately this limitation seems to either clutter resource folders or cause us to have to take round about solutions. By As for your side note, I personally would put both in |
That makes sense. I am already decoding |
@Davhed you could do all three even, I know I will use loading from assets and it would be nice to not have to write that a bunch of times. You could simply put in the docs that they need to have that folder in their app if they use it. |
Since I am not an official contributor to Rajawali I have posted my progress to my own fork. It's very much WIP... currently reads in files and stores their data. Insight and feedback is always welcome. https://github.com/Davhed/Rajawali/blob/texture_packing/src/rajawali/materials/TexturePacker.java https://github.com/Davhed/Rajawali/blob/texture_packing/src/rajawali/materials/TextureAtlas.java |
I agree with the I just glanced through your code and it looks great so far. A very clean API 👍 I have a question about Line 75 in |
I tried reading the thread but maybe I missed it, what is wrong with using res/drawable-nodpi? In other projects assets is used instead of resources for cross OS reasons. As this is not the case for Rajawali it seems at first glance res/drawable-nodpi is the best location for image resources as the files are guaranteed to be there. |
I agree with Dennis...if they use too large of a bitmap we should just use it. Maybe @ToxicBakery I believe the consensus of the correct way to move forward was in line with using |
This is awesome! Thank you all for your insights. Automatically reducing a large bitmap is smart. I'm learning so much from this, and i truly appreciate the guidance. |
@Davhed it goes both ways so thankyou 👍 You're questions are helping me refresh Android tidbits I learned in passing a while ago. One other consideration I just remembered which you may or may not be aware of and may or may not effect you. @MasDennis since you are working with new texture management it may impact you as well...
|
Oh, and its probably fastest to use |
Thanks for the update :) Good to see you're making progress! Such a good feature to have for the framework. So |
So you basically had too much energy drink is what you're saying? 😆 |
Awesome!!! 👍 |
Just look at that beautiful texture atlas 😂 Great job @Davhed! |
@Davhed I must say you picked an interesting range of beers there.....I highly approve of your first entry to the atlas though. Getting close! |
The This is how it is currently used: TextureAtlas mAtlas = new TexturePacker(mContext).packTexturesFromAssets("AwesomeAtlas", 1024, 1024, 0, false, "atlas");
Plane mPlane = new Plane (2,2,1,1);
mPlane.setMaterial(new SimpleMaterial());
mPlane.addTexture(mTextureManager.addTexture(mAtlas.getTile("becks").getPage()));
addChild(mPlane); As you can see the "addTexture" portion is not ready... in fact that's where I'm a bit stuck. @MasDennis would like to see a single-step solution for passing in a texture, but I'm not sure how to approach it. What I am thinking is that the developer should be able to simply pass the name of the texture they would like to add, and behind the scenes a few things need to happen.
All the data needed is stored in the And just for fun here's another packed atlas showing a wide range of texture sizes: |
@Davhed Great work! Sorry it took so long to get a look at this. I have a few suggestions which may simplify all this but we should take into consideration the work @MasDennis is doing to revamp the
mTextureManager.packTexturesFromAssets("AwesomeAtlas", 1024, 1024, 0, false, "atlas");
//Which then calls something like this internally
TextureAtlas mAtlas = new TexturePacker(mContext).packTexturesFromAssets("AwesomeAtlas", 1024, 1024, 0, false, "atlas"); This process would need to be worked into the task queue but we need to figure out how the texture stuff in general is handled there first.
Then when you wanted to texture an object your call could look like this: BaseObject3D.addTexture(mTextureManager.getTexture(String atlasName, String tileName)); This would essentially pass the What do you think? |
Ah yes, clever. I appreciate the seamless approach here. Adding this implementation is the right way to go IMO.
Also makes sense, although I don't know how to accomplish this yet. I really love the idea of I like! Thanks @jwoolston! I would really like to hear any thoughts from @ToxicBakery @AndrewJo @jayschwa too. I know you guys are all busy, so please take your time. |
@Davhed here is the public void addTexture(TextureInfo textureInfo) {
if (mMaterial == null) {
RajLog.e("[" + getClass().getName() + "] Material is null. Please add a material before adding a texture.");
throw new RuntimeException("Material is null. Please add a material first.");
}
if (mLights.size() > 0 && textureInfo.getTextureType() != TextureType.SPHERE_MAP) {
mMaterial.setUseColor(false);
}
mMaterial.addTexture(textureInfo);
} |
Actually I really don't like that you can add textures via BaseObject3D. This is frankly misleading and does not convey what is really going on in my opinion. Textures should really only be added to the materials. Additionally I would prefer setMaterial(AMaterial material, boolean copyTextures) be replaced with either a static or instance method that permits copying textures from one material to another. Just my thoughts, these would likely be breaking changes and they might exist for reasons unknown to me so I'm not sure if it makes sense to actually remove those or if anyone even agrees with me. |
OK so ideally this would happen in
What would be the link back to the |
I share this sentiment actually, so if people agree with removing it, lets do it. We have broken just about everything else, if it improves things, now is the time to do it. Hypothetically speaking, if we removed the call on
What does this method do? I haven't been able to figure it out. |
the copyTextures flag just permits copying any textures on the currently set material to the material that is about to be set. Its just a convenience method but I think it belongs on AMaterial and not BaseObject3D. |
Ah, ok that makes more sense. |
Can you pull this change in and apply it liberally. Make sure you let it soak in for 30 minutes before going outside. |
clutzblock SPF 50 has been applied, I will add further checks in the |
Seems like a "Texas 2-step" solution is going to be the best bet based on this discussion #600
|
@MasDennis I'm sorry... I couldn't help myself. I added I have also modified So, it is now working in a pretty simple 2-step process: TextureAtlas mAtlas = new TexturePacker(mContext).packTexturesFromAssets(1024, 1024, 0, false, "atlas");
SimpleMaterial mSimpMat = new SimpleMaterial();
mSimpMat.addTexture(mTextureManager.addTexture(mAtlas, "newcastle"));
Plane mPlane = new Plane (2,2,1,1);
mPlane.setMaterial(mSimpMat);
mPlane.setAtlasTile(mAtlas, "newcastle");
addChild(mPlane); I still need to check my UV conversion algorithm with more complex models/atlases, but I hope I can get a little assistance with the battle testing. This is the updated branch: |
A method for compressing the atlas bitmaps should be included too. I almost forgot about that. |
I can add in the compression support when this is working first for regular uncompressed textures. |
Cool, it is to that point, but should get some peer review |
Actually it apparently needed some "beer" review... I just removed some hard coded references to Newcastle... it made me LOL |
Haven't forgotten about this @Davhed. Will pick this up after the skeletal animation task. Or you could submit a pull request with the way you see it working. Then we can all review it and merge it if its all good 🍻. |
As I was waiting for the texture atlas code to come online I jumped onto the AWD parsing. If anyone wants to knock out the font to texture support I wont take offense =) I am guessing @Davhed would know best as he already figured out the packing which was the next step to figure out in what I was working on. |
Closing this now since the pull request is posted #782 |
WORKING BRANCH
This post is so that I can layout my idea for how a texture atlas could/should work. Since this is on the challenging side for me I wanted to ensure I got some input from the gurus.
Concept
Texture atlas code has been written a thousand times over, and there is a lot of data that says to keep things simple. I am going to be adapting some code for mobile and Rajawali, the forked source can be found here.
Basically, a new class
TexturePacker.java
would be created and would handle the bulk of the work, and it would return a new object typeTextureAtlas
which can hold the data about each "tile" in the atlas as well as the atlasBitmaps
public TextureAtlas mTextureAtlas = TexturePacker(String atlasName, int atlasWidth, int altasHeight, int padding)
TextureAtlas
would contain the altasBitmaps
, and a list of file names and coordinates(X,Y,W,H) for each texture packed into the atlas.I am thinking there should be a getter to retrieve the image coordinates needed for a given object. Something like --
TextureAtlas.getCoords(String textureFileName)
. We then need a way to translate those coordinates into UVs.. this part is still hazy for me. Once the developer has the UVs they can simply get the appropriate atlasBitmap
by using another getter -- `TextureAtlas.getAtlas(String textureFileName).Scope
Loading
drawable-nodpi
, and append a prefix/suffix to each texturePacking
Bitmaps
into aCanvas
Bitmaps
as needed to accomodate all files in the target folderBitmaps
??TextureAtlas
will all collected data and atlasBitmaps
Retrieval
TextureAtlas
bitmap
based on file nameUncertainties
Compression support is possible, but I'm not sure it make sense. It seems that a
bitmap
could be returned and the "on-the-fly" compression could be implemented is the developer so desired. I don't think that this should support compressed textures on input.Is there a better way to collect the images besides a Canvas? Any prodding in the right direction is super helpful.
Please give me whatever feedback you can, I will do my best to learn whatever I need to to get this done properly. Thanks!!
The text was updated successfully, but these errors were encountered: