Using a texture atlas with a display list? [SOLVED!]

UPDATE: This has now been solved! A video showing the new code in action can be seen here: http://www.youtube.com/watch?v=q4S664yizGo

Hi all,

I’ve hit another rather annoying roadblock with my level editor / engine, and this one seems to have fairly serious implications for the way I’m doing things.

Here’s a screenshot of the editor running to give you some context for the issue:

(Please ignore the red / blue highlights - they’re markers to help me orient my UV coordinates)

So here’s the deal. The level is made up of segments that look like this:

A segment is made up of 5 potential textures - a floor, ceiling, inner wall, upper wall and lower wall texture. The upper and lower wall textures are used for segments that have overhangs or steps, such as in the following image:

The problem I have is that, up until the previous iteration of the editor I had been drawing all of this geometry using immediate mode (glBegin()… glEnd()), this was combined with a texture atlas and modified UV texture coordinates to give me a decent render speed (to save repeated texture binds).

This was the original texture atlas:

However, after upgrading my geometry to display lists - which has given me an incredible 500fps boost - I can now no longer manipulate the texture coordinates of each group of quads once they’ve been compiled into the display list. It has to bind to a unique texture each time it needs to draw a different group of quads.

As you can see from the UI output data in the screenshot, I have a terrible, terrible number of texture binds.

I’m using around 4 different display lists to make up the segment - a floor / ceiling list, a wall list, and a list for both the upper and lower overhangs. Altogether they give me amazing performance benefits over immediate mode, but this problem has now left me questioning whether this was, in fact, the right way to do it.

If anybody else has managed to solve this problem, I’d be most grateful for some input.

Many thanks!

ummm…use a VBO? :smiley:

As I have learned from opiop65, Display Lists are better for this kind of thing. I was strictly useing VBO’s for my game, but DIsplay Lists are working better. Reason: At massive amounts of chunks (group of blocks) just making the VBO will take to much time and RAM.

With the Display List, when you change the texture, re compile the list.

Thanks, zFollette.

This would mean, by extension, that I can’t use just 4 display lists to generate the entire map’s geometry - since you should be allowed to apply different textures to the walls / floors etc. Doing so would change textures for all geometry parts generated by that display list.

What a pickle :frowning:

You should 1) have a chunk system, 2) have a display list for each chunk and 3) only re compile one chunk when you change the texture.

See my thread, there are a lot of good optimization ideas for you: http://www.java-gaming.org/topics/efficient-chunk-loading/31820/view.html

Would chunks be relevant for what I’m making? Obviously I’m not saying doing A is more correct than doing B, but I’d like to think that what I’m doing is much more lightweight than the typical ‘voxel builder’ type of game.

Consider this: the typical level in this game will look a little something like this layout:

That’s a 50x50 region of space, subdivided into 1x1 individual XZ tiles. Each tile, or Segment, can have a variable floor / ceiling space (I guess a little bit like Doom’s line-defs).

Breaking up this level into chunks seems like overkill.

Even textured, this region of geometry gives over 155 FPS - but obviously I want to improve this since I’m running this on a fairly modern iMac (last 3 years), and I want better legacy support.

As a final point, this is a worst case scenario - I have a line-of-sight algorithm (which is perfect for the corridor-style nature of this type of level design) which effectively culls 80-90% or more of the geometry on show. This will ease the load, but I will still have that nagging thought in the back of my head that I’m doing all of this in a really dirty way at the moment!

zFollette, I’ve come up with a solution that was inspired by a comment you’d made on one of your threads.

I’m writing a GeometryAtlas that can take a texture atlas, and initialises itself into an array of display list handles, where each handle represents a quad UV mapped to specific sub-texture from the atlas.

The first part - creating an atlas to use for the single patch (one quad) wasn’t too difficult. I’ll have to extend this to the other parts of the Segment’s geometry, but it shouldn’t be too difficult.

I’ll report my progress back here so that other people can learn from this as well.

Thanks for your help!

No problem, I would be glad to see how this turns out.

I’ve finished implementing the changes - I’m really chuffed with the results.

I’m just uploading a video showing the performance improvement, and I’ll write up a brief explanation of how I solved this in a moment.

The solution:

I broke up the segment’s geometry into two main components - the horizontal quads (floor / ceiling) and the wall quads (for both inner and upper / lower step walls).

Since the display list for each bit of geometry can only accommodate one set of texture coordinates, I decided to make a Geometry Atlas, which is just a fancy-pants way of saying that I mapped a texture atlas to a display list array.

So I know that my texture atlas contains 8 x 8 texture tiles:

Therefore, I know that I’ll need an 8 x 8 array of display list handles (for a total of 64) - one for each uniquely textured quad.

All I do therefore, is run a loop that creates a new display list for each XY tile coordinate in the texture atlas - which contains the glBegin… glEnd instructions for creating a uniquely textured quad based on its respective XY texture tile.

At runtime, when I create the segments, I simply tell the Geometry Atlas to return me the right display list handle for whatever XY texture I need. The work done earlier on creating the lists make this a one-line call.

The result is a much faster scene render. The great thing is that this is still not fully optimised - I’m not running my line-of-sight code here, which will vastly speed up performance beyond what is shown here.

A video showing it running with this new code can be seen here:

Your video is private! :frowning:

Whoops! Not any more :slight_smile:

If you need anyone to thank, thank opiop65.

Cool, glad you got it working! I’m impressed, it seems like a really useful tool!