collinsmith / riiablo

Diablo II remade using Java and LibGDX
http://riiablo.com
Apache License 2.0
884 stars 101 forks source link

DT1 isometric tile storage optimization #7

Open collinsmith opened 5 years ago

collinsmith commented 5 years ago

I'll look into this more when loading speed improvements become more of a priority:

DT1 isometric tiles are stored as 160x80 (really 160x79) textures, however approximately 1/2 of that space is garbage due to the square textures containing a diamond/isometric texture. Two ideas I've had to far to improve this is to store the texture data as a rectangle texture and skew it somehow (idea 1) to render it correctly, or more probable (idea 2), use a static lookup texture 160x80/160x79 consisting of r,g as x,y formatted as the current textures are (rectangle containing isometric data) to a second rectangle texture containing the actual texture data. The second texture would be approx 1/2 the original size at about 80x80 and greatly ease the desire to pack all textures from a given DT1. Only 1 copy of the static texture is needed, so overhead is negligible.

I think idea 2 is doable and the performance overhead minimal for the space/loading time efficiency it will provide (1/2 the data). Additionally, some DT1s contain an upwards of 300+ tiles, thus an upwards of a 20x20 sheet goes from 3200x1600 to 1600x1600. This might require a second shader, so some of the features of the first will need to be ported or generalized an applied to some FBO post shader (namely gamma).

I don't know if this will be worth the trouble either, I'll need to benchmark exactly how much DT1 data is loaded in-game (looks to be 1.5MB per DT1 on the high end), and many DT1s contain both isometric and RLE tiles, so packing could become an issue, however it's plausible to optimize the RLE tiles as well and store them as a 32x32 grid atlas (?1 atlas for iso tiles, another for rle tiles?) with those tiles containing coords and offsets to the atlas positions they need (this could provide a nice storage efficiency improvement as well, since there's a lot of wasted space in some RLE tiles).

Total act 1 DT1s are only roughly 27.205 MB, so assume 32 MB of DT1 data per act. I'll also benchmark more when I look into streaming the data and optimize to avoid asset loading lockups. I think the MPQs/Asset Manager are the major data-access holdups right now (the data itself is all pretty tiny) - and Android is the only place where I think this DT1 change would have any notable effect.

collinsmith commented 5 years ago

I noticed that the DT1 loading algorithm sets each pixel invidually. I think this would benefit from writing the data to a byte array and uploading the data all at once.

collinsmith commented 4 years ago

I added a note in https://github.com/collinsmith/riiablo/commit/d43dcf4116e7b66c101f674ab86925a0c1d82640 about the map operations that are done to the tile size when loading. Should be looked into when this issue is being looked at.

collinsmith commented 4 years ago

I tried doing a really rough test of how much better it would be loading the DT1 isometric blocks as-is, and it looks to be about a 33-50% improvement. Definitely worth looking into when load times start becoming an issue. I think this will have a larger impact on mobile. It remains to be seen how much of a change in runtime performance this will have.

collinsmith commented 4 years ago

I had another thought that might fix some issues with spacing between tiles #62 using this method -- I can build in index duplication on the edges of the lookup table. In below picture example, blue are actual edges of tile, red are extra "padding" duplicate of their neighbor. I think this will work if it's 1px, but my only concern if this 1-2 px padding border would be noticeable.

Clipboard-6