Previous Blog Next Blog
Prev/Next Blog
by date

Resource: Ambient Occlusion for TGEA Interiors

Resource: Ambient Occlusion for TGEA Interiors
Name:Ryan Mounts 
Date Posted:Jul 16, 2008
Rating:5.0 out of 5
Public:YES
Comments:YES
RSS Feed:GarageGames Blog feedor Subscribe with .
Profile Page:View profile page for Ryan Mounts

Blog post
NOTICE: Resource updated 8/4/08.

Link to TGEA AO Resource

Well, as I figured, the ambient occlusion code was very simple to port over from TGE, but the lightmap persistence and caching took a little more work. Hopefully everyone will find this useful. This is a feature that I've been wanting to see in Torque for a long time, so I'm pretty excited to see it coming together.

For those of you who have already looked at the TGE version of this resource, I suggest at least reading over the Persistence and Caching section again, because the TGEA version behaves slightly differently.

As before, if anyone finds/fixes any bugs, enhances performance, or makes interesting modifications to this resource, please share!

Pics: Side-by-side comparisons of two identical interiors, one with AO and one without. In the first pic, there are two small boxes in the Cornell box on the right, I promise! :) You just can't see them because the ambient light is constant and the textures are a single color. This just illustrates how much visual "pop" AO can add to an interior.





(Church dif created by Benjamin Naulls, of course)

Recent Blog Posts
List:07/16/08 - Resource: Ambient Occlusion for TGEA Interiors
07/11/08 - Resource: Ambient Occlusion for TGE Interiors
06/25/08 - Native Ambient Occlusion for Interiors in TGE
06/17/08 - Custom Lightmaps for TGEA Interiors
04/03/08 - Add Custom Lightmaps to Interiors
01/24/08 - Update: Max2Ctor 1.0.1
01/10/08 - Tutorial: Export 3dsmax directly to Constructor
01/09/08 - Free Resource for 3dsmax Users

Submit ResourceSubmit your own resources!

Ryan Mounts   (Jul 16, 2008 at 17:27 GMT)
Check to make sure you downloaded the .ZIP file and not just the .PDF... I had the wrong link for a bit.

James Ford   (Jul 16, 2008 at 17:27 GMT)   Resource Rating: 5
Wow, thats really impressive. What kindof performance hit does this entail?

Now all we need is AO for dts and players '-)

Taylor Petrick   (Jul 16, 2008 at 17:35 GMT)   Resource Rating: 5
Congratulation Ryan! You just made my day! Thanks for sharing such an awsome resource.

Edit: I believe congratz is spelt with a t, not a d...
Edited on Jul 16, 2008 17:42 GMT

Ryan Mounts   (Jul 16, 2008 at 17:35 GMT)
@ James

There is no performance hit in-game because the AO is baked into the interior's lightmap. All calculations are done "offline," so to speak, during the scene relight.

Eric Forhan   (Jul 16, 2008 at 17:54 GMT)   Resource Rating: 5
We tested the TGE version yesterday. It looks nice, but I'm concerned about the sheer length of time it takes to light the first time.

Is there any way to include pre-compiled AO cache files? Or move a lot of the calculations over into map2DIF?

Thanks for your hard work... I've been wanting AO for quite some time!

Taylor Petrick   (Jul 16, 2008 at 18:47 GMT)   Resource Rating: 5
@Eric

Yeah, I too noticed that the re-light time drastically increases. I'm gonna try it on my 3GB RAM / quad core tomorrow, just to see how long it would take to relight on a map with every difs on high. What I plan to do is, before release, render the final lightmap and then remove the scene lighter from the mission download. That way no players will accidenally end up waiting an eternity for their game to load.

Morrock   (Jul 16, 2008 at 18:48 GMT)   Resource Rating: 5
Very cool that this you have made this for TGEA too. You can expect some modifications to this from me soon, I love looking at these things and seeing how they work :-)

Ryan Mounts   (Jul 16, 2008 at 18:54 GMT)
@Eric

Yeah, it would be nice to be able to bake the AO at dif creation time if you were going to drop dozens of the same interior into a scene and didn't really care if the AO interacted with objects in the world. Then you'd only have to do the calculation once.

I don't remember what the lightmap code looks like in map2dif, but it's probably similar enough to the engine that the AO code could be dropped in there. I'll look into it when I get a chance. It'd be nice if it could be added to Constructor where you could tweak the AO and see it before export... plus you could use the internal exporter. Maybe Jaimi would be up for that! ;)

Also, relight times will be affected by the "light_geometry_scale" (it basically controls the resolution of your lightmap) and the number of LODs, since AO will get calculated for each LOD. Unless you have REALLY high resolution lightmaps or an annoyingly splotchy area, you shouldn't really need to go above Low quality. A good method for adding AO to a scene with many interiors is to use the filtered relight instead of the full. Don't worry, once an AO enabled interior is out of range of the filtered relight, it will still keep its lightmap. This way you can update only one or two interiors at a time, allowing for quicker feedback.
Edited on Jul 16, 2008 19:22 GMT

Eric Forhan   (Jul 16, 2008 at 19:58 GMT)   Resource Rating: 5
Thanks Ryan. I didn't realize that "Low" may work well enough. Indeed, anything would probably be better than nothing.
I'm sure using only DIF-baked lights instead of sgLights would probably speed it up some too. They don't seem to be taken account of anyway, so it may as well be done in the DIF.

Do you think could take a snapshot of either of those same scenes from the same angle with the AO settings reversed? Just for a better comparison?

Apparatus   (Jul 16, 2008 at 20:15 GMT)   Resource Rating: 5
Rated 5. Great resource.

Ryan Mounts   (Jul 16, 2008 at 20:38 GMT)
Here's the top pic with AO settings reversed (Distance = 3, Quality = Low, Multiplier = 1).



ando   (Jul 16, 2008 at 21:09 GMT)
Awsome work Ryan, can some kind person provide this on a clean 1.7.1 for a none coding artist like myself. I would love to toy with it :)

James Brad Barnette   (Jul 16, 2008 at 21:37 GMT)
Ryan You are the man!

is it me or is the quality of the effect better in TGEA? At least that is the way it looks from the screen shots
Edited on Jul 16, 2008 21:38 GMT

Brian \\\"Cybore\\\" Smith   (Jul 16, 2008 at 22:59 GMT)
Ryan, You are the man x2!

Ryan Mounts   (Jul 17, 2008 at 04:09 GMT)
Please see the new notice at the top!

@Ando - Here is a clean build + AO mod.

And thanks for the encouraging comments everyone... :)
Edited on Jul 21, 2008 22:03 GMT

J.C. Smith   (Jul 17, 2008 at 13:34 GMT)   Resource Rating: 5
Just wanted to give you some kudos on this. Nice addition.

ando   (Jul 17, 2008 at 18:00 GMT)
Thanks for the clean build Ryan, I have tested this a few times, it works great and looks fantastic, it is a massive improvement.

The only snag is it seems to favor having ambient shadows going up instead of going down, it just looks a bit odd.

Orion Elenzil   (Jul 17, 2008 at 18:16 GMT)
> it seems to favor having ambient shadows going up instead of going down
Ando,
could you elaborate on that a bit ? Maybe a screenshot ?

ando   (Jul 17, 2008 at 19:02 GMT)
If the darker shade was below the extruded trim it would look fine but...


Edited on Jul 17, 2008 19:24 GMT

Morrock   (Jul 17, 2008 at 19:45 GMT)   Resource Rating: 5
That is pretty strange, I don't see any reason that the AO would do that...

edit: Never mind, just tried this out for myself with several relights and different settings, it is definately darker on top.
Edited on Jul 17, 2008 19:58 GMT

Ryan Mounts   (Jul 17, 2008 at 20:59 GMT)
Yeah, I just tried it out too with different lightmap resolutions and AO parameter combinations in both TGE and TGEA, and they all appear darker "on top". Good catch, Ando. Here's the interesting thing, though... no matter what orientation you put the interior, it's always slightly darker "on top," even when the "top" is pointing down. So this leads me to believe that it's probably not a bug in the AO algorithm, because it produces consistent results regardless of orientation, but rather it is linked to the actual lightmap somehow (maybe the lexel locations?). I'll try to figure out a way to track this down. If anyone else wants to help tackle this, feel free to put in your two cents. :)

Orion Elenzil   (Jul 17, 2008 at 21:21 GMT)
Ryan,
if there is a bug in the underlying LM technique, the AO code might present an opportunity for accounting for it. eg, you could orient the hemisphere slightly towards "down", which would shoot more rays "down" and tend to make that side a bit darker, i think.

Morrock   (Jul 17, 2008 at 21:43 GMT)   Resource Rating: 5
This fixes it fairly well. in lightingSystem/synapseGaming/interior/sgPlanarMap.cpp, change

// Generate a random vector between (-1,-1,-1) and (1,1,1)
randPt.set(gRandGen.randF(-1.0f,1.0f),
gRandGen.randF(-1.0f,1.0f),
gRandGen.randF(-1.0f,1.0f));

to

// Generate a random vector between (0,0,0) and (1,1,1)
randPt.set(gRandGen.randF(0.0f,1.0f),
gRandGen.randF(0.0f,1.0f),
gRandGen.randF(0.0f,1.0f));

You obviously don't have to change the values in the comments, that mainly for keeping track of it. What this does is instead of generating a random normal from negatives to positive, it just generates it from 0 to postive. Actually, you could probably just change the z random for this to work, lemme check...

Well, that screenshot doesn't show it off too well, but it definately feels more balanced. I'd be up for helping to track down the lightmapping problem however, real solution > angling hack.

Edited on Jul 17, 2008 22:00 GMT

ando   (Jul 17, 2008 at 22:06 GMT)
Nice one Morrock, can you provide the fix for the none coder :)

Also could it be related to the normal map bug? http://www.garagegames.com/mg/forums/result.thread.php?qt=76412

Morrock   (Jul 17, 2008 at 22:15 GMT)   Resource Rating: 5
Sorry ando, I just relight my entire scene of AO to bad results. Even though it fixes the top is darker bug, it makes the AO in general much much worse. The top image was done with AO: quality: low, distance: 3, multiplier: 1. The bottom image is quality: medium, distance: 3, multiplier: 1. So no different quality or setting is going to help it, it looks pretty much the same at all detail levels.


Edited on Jul 17, 2008 22:21 GMT

Kory James   (Jul 18, 2008 at 04:05 GMT)
I was wondering if they have a Ambient Occlusion code for DTS that could work for building model and player model that would shade the normal map and give the DTS models a more realistic look?

Edward Smith   (Jul 18, 2008 at 11:47 GMT)
Thats some improvement!

ando   (Jul 18, 2008 at 11:48 GMT)
It could be tied to the nasty lightmap borders which have reapeared in recent map2dif builds like the new tgea build... http://www.garagegames.com/mg/forums/result.thread.php?qt=30047

Be great to get rid of the nasty border lines in map2dif

Ryan Mounts   (Jul 18, 2008 at 14:25 GMT)
@Morrock

I'm not quite sure how you generated that bottom pic... changing the random vector bounds doesn't really affect anything. You could change the random vector to a constant vector if you wanted (it just can't be the same direction as your surface normal), and the only visual difference will be some shadow banding that is related to the gaps between the ray dome vectors. Randomizing the lexel basis helps to smooth this banding effect.

@Ando

My hunch is that it has something to do with the lexel creation code... I remember looking at that code once and noticing something interesting. The lexels overhang the surface borders by about half a lexel all the way around (I believe this is what leads to light leaks, when the overlap is big enough to reach underneath a wall to the other side). But if the lexels overhang more on one side than another, that would definitely either cause the AO to be darker on that side, or cause a "light leak" if the lexel was inside a wall 'cause the ray casts wouldn't hit anything and it'd appear unoccluded. Anyway, this is kinda tough to track down...

Morrock   (Jul 18, 2008 at 15:27 GMT)   Resource Rating: 5
@Ryan
You were right, I left in a few lines of code from when I tried messing with the algorithm (I do this way too much). Now I'm not sure how I got that first screenshot of the extrusion being darker on the bottom...

@Kory
The problem with ambient occlusion for those non-static objects (animated objects, physics objects, players) is that in this AO algorithm, it determines occlusion by doing raycasts in all directions to check how occluded the space around it is. It bakes it into the lightmap, so no calculation is done in-game. But with non-static objects, the space around them may become more/less occluded as they move around, or as other objects interact with them; so it would need to be calculated and shaded in real-time. This method takes far to long to do real-time calculation. I would love to try to tackle something like real-time "ambient occlusion", but right now I don't know enough shader language to write most methods (like SSAO) or know how Torque does shadows well enough if I were to try to do it in the engine.

Ryan Mounts   (Jul 18, 2008 at 16:55 GMT)
Well, this isn't rock solid proof, but it definitely illustrates that my hunch is most likely correct. The pic shows each surface's outer lexels in red (this has nothing to do with AO, but rather how the lexels correspond to the surface in world space). You can see how some sides are more red than others, indicating that the lexels overhang the surface differing amounts on different sides. Notice how it is more red above the ledge than below... so what's happening is that above the ledge, the lexels' centers are outside the interior and the rays are performing their jobs properly. Below the ledge, the lexels' center are inside the interior and the rays are not occluded. The proper solution would be to redo the lexel generation code so that they get centered on the surface as expected. I'll look into this, but it may be a while because I'm going on vacation next week. :)


Edited on Jul 18, 2008 16:56 GMT

Morrock   (Jul 18, 2008 at 21:22 GMT)   Resource Rating: 5
Nice job, how do you get the outer lexels to show color like that? What is up with the outer lexels dividing the center of the extrusion?

Ryan Mounts   (Jul 18, 2008 at 22:46 GMT)
The lexels are already divided into "inner" and "outer" and lighting is processed inner first and then outer. Look above the AO code in sgCalculateLighting to the outermost for-loop and you'll see how to test if the lexel is inner or outer.


for(U32 i=0; i<sgPlanarLightMap::sglpCount; i++)
{
// set which list...
U32 templexelscount;
sgLexel *templexels;
if(i == sgPlanarLightMap::sglpInner)
{
templexelscount = sgInnerLexels.size();
templexels = sgInnerLexels.address();
}
else
{
templexelscount = sgOuterLexels.size();
templexels = sgOuterLexels.address();
}


So down where the texels get set, you can test if(i != sgPlanarLightMap::sglpInner) then make the texel red. Then I commented out the sgBlur line in sgMergeLighting so I could see the lexels clearly. Now why there is an outer lexel in the center of the ledge, the only thing I can think of that could cause that is if the lexel lied exactly on the center of that face. For a rectangular surface like that, the center happens to lie on the shared edge between the two tris that form the surface. All lexels on a tri edge are classified as outer. The AO doesn't depend on the inner/outer concept, so that shouldn't really matter.

As a side note, my hunch has shifted slightly, but I'll elaborate when I have more info.
Edited on Jul 18, 2008 23:01 GMT

Ryan Mounts   (Jul 19, 2008 at 17:31 GMT)
Okay, got this fixed now... I'll post pics and the fix when I get home. Thanks to those who helped look into this.

James Brad Barnette   (Jul 19, 2008 at 17:42 GMT)
Wow I really hope all of this gets fully integrated with the next release.

ando   (Jul 19, 2008 at 20:08 GMT)
Fixed, looking forward to it :)

Ryan Mounts   (Jul 21, 2008 at 14:58 GMT)
The resource link has been updated with the fix for the shadow bias. My hunch was correct that the lexel positions were the culprit, but not for the reason I thought. I had made a wrong assumption that lexel.worldpos was the center of the lexel when it is actually the lower left corner. So the rays were being projected from the corner of the lexel instead of the center, which biased the shadow to the bottom and left. To fix it, I simply calculate the center of the lexel and shoot rays from there. :) I'll try to post a clean build this evening.

If you don't want to download the resource again, here are the code changes in bold. This is in the AO code in sgCalculateLighting...


 /// AO MOD LEXEL OCCLUSION START

if(sgInteriorInstance->mAO)
{
F32 sum = 0.0f;
F32 *rayDome;
F32 rayArea;
F32 AO;
F32 alpha;
U32 rayCount;
Point3F tangent, binormal, randPt, ray;
RayInfo info;

// Calculate the world position of the lexel center
Point3F sVec(sgLightMapSVector.x, sgLightMapSVector.y, sgLightMapSVector.z);
Point3F tVec(sgLightMapTVector.x, sgLightMapTVector.y, sgLightMapTVector.z);
Point3F lexelMid = lexel.worldPos + 0.5f*(sVec + tVec);



	// Cast a ray along the tranformed direction
if(gClientContainer.castRay(lexelMid, lexelMid + ray, mask, &info))
{
// Return ray to unit length before dot product
ray /= sgInteriorInstance->mAORadius;

// Sum up cos(angle between normal and ray) for all occluded rays
sum += mDot(lexel.normal, ray);
}



Edited on Jul 21, 2008 15:04 GMT

Ryan Mounts   (Jul 21, 2008 at 22:00 GMT)
Here's the updated executable.

ando   (Jul 22, 2008 at 00:32 GMT)
Tried and tested, all is good and works perfect, great stuff. Thankyou for providing the exe I really appreciate it, I will get you a few beers :) GG be daft not to pick this up and reward you in some way for your efforts.
Edited on Jul 22, 2008 00:33 GMT

Stefan *Shaderman* Greven   (Jul 22, 2008 at 13:29 GMT)   Resource Rating: 5
Thanks a lot for sharing Ryan!

Morrock   (Jul 22, 2008 at 16:24 GMT)   Resource Rating: 5
Ohh, so that's how it was doing that, great to know :-). Even greater that you found that fix!

Eric Forhan   (Jul 22, 2008 at 16:27 GMT)   Resource Rating: 5
So, was that only an AO fix? Or did that fix anything with Torque's lighting at all?

Orion Elenzil   (Jul 22, 2008 at 16:34 GMT)
Eric, based on Ryan's comment
I had made a wrong assumption that lexel.worldpos was the center of the lexel when it is actually the lower left corner. So the rays were being projected from the corner of the lexel instead of the center, which biased the shadow to the bottom and left. To fix it, I simply calculate the center of the lexel and shoot rays from there. :),
i would expect that stock lighting was already correct, and this fix only affects AO.

Eric Forhan   (Jul 22, 2008 at 16:46 GMT)   Resource Rating: 5
kk, thanks. I kind of suspected that myself. I was still hopeful it'd fix some lighting bugs. ;-)

Fleeky   (Aug 03, 2008 at 17:27 GMT)
first off this is a really awesome reasource and i hope im just doing something wrong.

our coder friend got this integrated into our tgea build and i used the ray length 3 quality poor multiplier 1 settings and this is what i got..







have any idea whats going on and how we could get this looking a bit better?
Edited on Aug 03, 2008 18:06 GMT

Eric Forhan   (Aug 03, 2008 at 20:22 GMT)   Resource Rating: 5
I got this too. Try slicing-up the geometry into smaller portions.

Fleeky   (Aug 04, 2008 at 02:11 GMT)
anyone have any idea why larger geometry sets would be messing stuff up and if the problem could be rectified rather than having to slice up geometry? slicing up and placing certain level elements would prove to be quit difficult with some of the structures my level designers have made.

if you can point in the right direction atleast i may be able to get our engine coder to look at it as well?

Ryan Mounts   (Aug 04, 2008 at 03:14 GMT)
You're probably not doing anything wrong. I've seen this too (not quite to that extent) but have been too busy to look into it. I'll see what I can do, but it may take a while.

Ryan Mounts   (Aug 05, 2008 at 00:43 GMT)
Okay, got this one fixed. Thankfully it was very simple. In the case where areas are solid black, the ray casts were hitting their own surface and so all rays were being occluded. This is probably due to rounding errors associated with floating point precision. To fix this, simply offset the lexel center slightly in the direction of the lexel normal (new code in bold).


	// Calculate the world position of the lexel center
Point3F sVec(sgLightMapSVector.x, sgLightMapSVector.y, sgLightMapSVector.z);
Point3F tVec(sgLightMapTVector.x, sgLightMapTVector.y, sgLightMapTVector.z);
Point3F lexelMid = lexel.worldPos + 0.5f*(sVec + tVec) + 0.005f*lexel.normal;


I used an offset of 0.005, but this number is not set in stone. If you still run into patches of black, just increase this value in small increments until they're gone. I'll try to update the resource link in a minute. Please let me know if this fixes your problems. Since I only had one interior that exhibited this behavior in a small area, I can't be sure it addresses all cases.

Fleeky   (Aug 10, 2008 at 06:23 GMT)
so what would be a good increment to increase by ? we tried the 0.005 and that did indeed improve , but the problem still arises somewhat.

heres a shot showing it off



thanks for for the help !! the ao looks better and better..
Edited on Aug 10, 2008 07:05 GMT

Ryan Mounts   (Aug 11, 2008 at 03:31 GMT)
You can make the offset any size you want, but obviously you want to make it as small as possible without getting any black patches. I'd probably just increment it by 0.001 (equivalent to 1 mm in Torque units) until all the black goes away. Just be aware that as the offset increases, the physical accuracy of the AO decreases.

Fleeky   (Sep 08, 2008 at 01:53 GMT)
anyone else still having problems with black areas ? tried messing with the lexel didnt improve much..

Ryan Mounts   (Sep 08, 2008 at 02:17 GMT)
If you want to email me the problem DIF file(s), I can take a look at it for you.

Lorne McIntosh   (Sep 10, 2008 at 01:52 GMT)
Hey guys,

I've just created a great Screen Space Ambient Occlusion Shader that would make a great addition to this light baking exporter. It creates real time ambient occlusion on anything in the scene: DIF, DTS, animated DTS, and players. I'm selling the shaders for a very reasonable price if you want to add it into your game and get some nice AO happening. www.ubiqvisuals.com

I've put a video on my website so you can see it with dif and animating dts models. www.ubiqvisuals.com/index.php?option=com_content&view=article&id=46%C2%A...


Edited on Sep 10, 2008 02:04 GMT

Petteri Huttunen   (Nov 13, 2008 at 13:02 GMT)
Great resource, but now the TGEA 1.7.1 crashes A LOT, it also broke the bloom ?

Ryan Mounts   (Nov 13, 2008 at 19:42 GMT)
Hey Petteri, if you're experiencing crashes during gameplay, I can pretty confidently say that it is not related to the proper addition of the AO resource. If it crashes upon relight, saving the mission, or mission loading, then there might be an issue with the lightmap persistence (the code in Appendix B). I haven't had any crashes due to the AO resource and haven't heard of anyone else having this problem (yet). As for the bloom, I'll have to check on that later. You might also try your game on a different machine to see if it behaves differently. Also, if you have other code changes or resources implemented, it might not be playing nicely with them. If so, you could add the AO resource to clean TGEA install to see if that fixes the problems.

You must be a member and be logged in to either append comments or rate this resource.