Tuesday, 17 December 2013

Tuesday Got IMPOSTERS!!

And Phew!

At long last, today I saw my first peek at the working technology of true imposters within my static batching and occlusion system.

Impressive I know!  So what are you looking at?  Well the blue square is the background color of the camera and nothing to get excited about. The red square is our quad imposter which has been calculated automatically based on the position of the camera and the target object. The building in the center is the target object and it is being rendered via the imposter pixel for pixel exactly where the real model would have been rendered. Instead of hundreds of polygons, there are now just two.

Shadows About To Get Fast

The reason I show you a view from above is that this is the perspective the shadow light sees objects from. By using imposters when rendering the shadow objects, we will vastly accelerate the entire shadow drawing cycle too. Not forgetting the reflection views and light ray cameras!

Signing Off

I still have to do some finishing off and house-keeping, and of course add multiple target objects per communal texture, and then get it integrated into the main engine, but the crazy math part has been done, which is a big relief for me.  The immediate goal for Wednesday is to stop the popping effect currently vexing the Reloaded community, but the side effect of solving that should be some additional performance improvements.  That, together with the shader panel, might be enough performance to allow us to shift the percentage over to some non PPP work, such as player damage, enemy strengths and some improving tweaks.


  1. Great progress Lee,its been very interesting reading this blod and watching Reloaded as it grows.

  2. So I'm confused. That image shows a quad rendering the relative direction of a three dimensional building as a two dimensional image? Or is the building in that image still the 3D object. Because you could certainly have fooled me.

  3. It truly is just two polygons ;) Once the 3D model is rendered to the texture and the quad vertices aligned, it only remains for the quad to be drawn until the relative angle of the render changes. It's like one 3D model render every 240 cycles, instead of EVERY cycle!

  4. Looking good! Now we should see a difference in looks and, I imagine performance!

  5. Curious, will this work with dynamic entities too that are at a great distance?

  6. In reading the expanded version of this blog post in the January newsletter - you mentioned there large cities with millions of polygons, and how skip the unnecessary processing for every frame - and hence your solution is to use imposters. There is an different solution to this that I recently implemented in DarkGDK that tripled my frame-rate (more for larger maps). There's no reason why it couldn't be used along side imposters to get the summed performance boost of both!!

    It works by hiding off-screen objects (such as those behind visible objects). With some precomputation, this can be done with virtually no overhead during run-time. I talked about how I did it here:

    In my experience, it seems that no game out there that I've played, whatever the company, uses a technique like this. And it's enormously effective!

    1. Bottom line - with this technique implemented, frame-rate performance is based only on what is currently visible on the screen each frame. The largeness and complexity of the rest of your map is no longer a factor in performance.

      I just had a thought as well - if you have any imposters that could be pre-computed before run-time, you could switch them in and out as the player changes grid blocks, as I discussed in the forum.

      And you may already be doing this, but you could layer imposters. If you pre-computed a set of imposters for a given single object - that is created images taken from the camera of a single, non-animated object in isolation, from multiple angles, using transparency as a background, then using these as imposters, closer objects would still block further-away objects, and those objects' imposters would be independent of the background scenery, and thus portable, such as for movable objects that don't animate, or multiple instances.

  7. A great idea. It is a technique often used in racing games where the track splines are known, and as you say provides an insane performance boost :) My initial reaction was how much memory it would consume given that the Reloaded terrain is 25,000 x 25,000 units, so a grid of 250x250, each holding a potential list of 200 items would require a memory block of 50MB, which is not too bad. My second reaction was the processing time to calculate the visibility of every object from ever grid position 250*250*5000=312 million tests for a large level. Probably each 'test game' press too. Still, despite these minor grey areas, I think your idea has real merit for performance and no doubt I will be visiting this optimization technique in 2014 ;) Thanks again!

    1. Ahh! It's nice to hear someone's been using it then! :)

      My first thought was about the memory requirement too, but once I adopted your idea of quantized grid blocks, as you said it really doesn't take that much memory after all, even with storing all visible objects each block as I did. With 200 objects per block, it sounds like that's how you figured it too. But all that would be needed is the differences between a particular grid block and its neighbors (which would be way more efficient), and unless the blocks were huge, the quantity of differences would be pretty tiny. How much would really change from one segment block to another? This in the context of each item being a single mesh. Individual polygons would be another story, but even doable I think, if you're just storing differences. There would be even less memory than with storing mesh pointers to just store what other blocks are visible from a given block (which would be friendly to dynamic objects) - where each block has a list of objects intersecting it. I don't think it would need to be anywhere near 50MB. And of course this is system memory, not video memory. So its fast and plentiful!

      There isn't just 250x250, there's also different levels - did you say in another post 100? I didn't even think about the Y levels when I did it. Since the number of differences would be tiny from block to block, you could make the blocks 4 times bigger than your creation segment blocks, as an example. This would increase the differences from block to block (and thus cost some effectiveness), but it would reduce your block count by a factor of 16.

      When you're dealing with 250x250x(whatever), the addressing of the blocks is going to take more memory than the lists themselves - assuming most blocks are unpopulated. So there are different ways of organizing or consolidating to fit your needs.

      With 250x250x100, just the storing of list pointers alone would be 24MB (or <2MB if you combined the xz blocks by 4s for this purpose). But the lists themselves, I think would total much less (again all sharing the same allocation, and no need to reserve memory that doesn't get used). How many maps are going to populate every block available?

      For the list generation precomputations - no doubt that doing the 3D maths directly would be a million times faster than all the camera rendering I did. I just didn't want to take the design time to do the math at this stage, as I wanted to complete it within a day. If you populated the list with visible blocks from a given block (instead of with object/mesh pointers), computation would be far faster yet. In any event, this precomputation phase can be done before the map is even distributed - stored in a file associated with the map (or integrated into the map's file format). Call it part of the map compilation/optimization process. Doing the 3D maths directly would probably not take more than a few seconds for a large map, but if it really did add noticeable time to prerun-time, such as in the "test-game" scenario, you could do an abbreviated version for test games.