AO and PRT bakes, using Blender and xNormal

4_views.jpg

Note:

It is assumed that, before starting on the bakings, a) your mesh is clean (no un-wanted non-manifold edges; everything is Set Smoot (smooth shading), with sharp edges marked sharp and the edge-split modifier on; object level scalings applied (with ctrl-A), Double-Sided is OFF, normals are right, no free-floating vertices or edges, etceteras) and b) that the mesh has been UV-unwrapped (without mirrorings or re-used areas of the texture or any other overlaps (except in the case of pitch black materials, which can be all piled up together and scaled down, since completely black materials don't interact with light, so AO and PRT values for them are irrelevant)). It is also assumed that you have scaled your mesh (or even better, worked on it from the start) such that one unit equals one meter. A 220 meter ship should measure 220 grid units in length, with the nose at Y = +110 and the back at Y = -110. The blender mesh object(s) center(s) should be at the origin.

Note: Blender uses the direct x coordinate system; it wants the nose of your ship in positive Y and the UP direction in positive Z. When you export .obj's you can tell the exporter to rotate the mesh, in which case front is positive z and up is positive y, and … I think … the x axis gets reversed. I'm always confused by these issues; forgive me; eventually I hope to clear up these matters to myself and update this tutorial. The Vegastrike engine definitely uses the OpenGL standard, with z in front, y up; –and I'm not sure if positive x is to port or starboard…

Intro

What's AO?

“AO” is an acronym for “Ambient Occlusion”. If you had a perfectly distributed light source around a model, and the model was painted white, the more exposed parts would look brighter; the less exposed parts would look darker. Ambient Occlusion is sometimes computed per vertex, sometimes per-texel. There are various tools that can produce it and which use different techniques, or “philosophies”. Blender does a sort of per-vertex AO with texel interpolation, with uniform distribution. xNormal does a per-texel AO, and has a setting for cosine distribution. CineMut will use two AO's: Blender's uniform, and xNormal's cosine (abbreviated UAO and CAO, for Uniform AO and Cosine AO). The two kinds of AO look similar but are mathematically different and serve two distinct purposes.

How's AO used?

Wrongly, most of the time; –i.e.: modulating the diffuse texture by it, to make recessed areas seem darker. Many texturers do this. Recessed areas do look darker, but, dynamically (as the model moves, turns), the darkness looks like painted-on, or like smoked. Why? Because if a recessed area is facing a light directly, it should look bright no matter that it is recessed or shaded from abient light. A more correct way of using AO would be to leave the diffuse texture alone, but modulate a copy of it by the AO, and blend the result into the glow texture, at a low alpha value, like 10%, barely visible. This would amount to a pre-computed ambient light contribution baked into the glow map. It looks better, but this assumes a fixed amount (and color) of ambient light. If the sky is a red nebula, ambient light should be red… So CineMut does something better –er.. MUCH better; but I digress…

How is AO computed?

Hundreds, –or even thousands– of “rays” are projected from each point on the surface of a model, and tested for collision against any other parts of the model. If a ray escapes without colliding with anything, it is considered un-occluded; occluded otherwise. The more unoccluded rays, the brighter the point will be colored. The more occluded rays, the darker it will be colored. Needless to say, baking an AO can take hours, or even days of computer time, depending on the number of rays, texture size, and other settings. The beauty of it is that the resulting AO has “highly concentrated information” that the shader can then use to get more realistic graphics in real-time.

What does Uniform and Cosine stand for?

With uniform distribution, all rays projected from a point are considered equal. With cosine distribution, each ray's contribution is multiplied, or “weighted”, by the cosine of the angle it forms with the surface normal. The results are similar, yet different. The 'meaning' is also different: What's particular about the cosine of the angle is that it is the formula for diffuse reflectivity. In other words, uniform AO quantifies incoming light, whereas cosine AO quantifies outgoing or diffusely reflected ambient light.

Here's a shot of cosine AO:

cao_shot.jpg

And here's a shot of uniform AO:

uao_shot.jpg

Similar, yet different…

Which is better?

Neither. Both are useful; rather indispensable. Per-light-ray occlusion computations in the shader absolutely need uniform ao to yield correct values (for direct shadows and specular occlusion). Ambient lighting modulation absolutely needs cosine distribution AO; –there's no way it can deduce its value from uniform AO. Therefore, both AO's are needed for “correct” lighting; and this is why CineMut requires both of them.

What about PRT's? What are those?

Imagine you have your model painted white, but in a dark room. Looks black.

Now put a red light in the direction of the positive X axis. You'll get the right side (from cockpit view, or starboard side) of the ship looking red.

Now put a green light in the direction of the positive Y axis. Your ship's right side still looks red, and now the top side looks green; and some parts in-between look yellowish.

Now add a third light, blue, in the direction of the positive z-axis. Now the front of the ship looks blue. Parts facing partially the front and partially the right side will look purple. And so on…

If you save this baking to a texture, that's your (raw) PRTP; and of course you can load the texture on your model to see what it looks like.

Here's a shot of a PRTP. Notice that red light is coming from the far side, so it's hardly noticeable.

prtp_shot.jpg

The reverse of that –red light in the negative x axis, green light below; blue light behind your ship–, that's your PRTN.

prtn_shot.jpg

It's actually more complicated than this, because point-like light sources wouldn't be very useful. The distribution of the light sources for PRT's vary as the cosine-squared of the angle to the axis. So, they are sort of “semi-diffuse” light sources. Long story; the good news is that xNormal takes care of the math for you.

What are PRT's used for?

The purpose of the PRT's is to tell the shader not just how much ambient light is reaching a texel, but where is it coming from.

Ambient Occlusion alone only tells the shader that, say, 30 % of the ambient light reaches a given texel. PRT's can tell the shader “there's 30% of ambient light reaching this texel, AND this 30% is composed of 15% coming roughly from above the ship, 10% from the front side, and 5% coming from the right side”.

This is good for three things:

1) Instead using a generic color for ambient light, the shader can actually look at the sky (cube map) in the direction that light actually comes from and use that color and brightness for the final ambient light contribution.

2) If the direction the PRT's say most light comes from is too far out of alignment with a light source, the shader can assume that point is in shadow. This yields pretty realistic, dynamic shadows.

3) If the direction the PRT's say most light comes from is too far out of alignment with the reflection vector (view vector reflected around the surface normal), the shader can assume that environmental reflections are occluded. This yields pretty realistic specular occlusion.

Note that, at least for now, the two prt's (PRTN and PRTP) will be combined together with the uniform AO, all into a single RGBA texture, using a special blender noodle. We've been (Klauss and I) swinging back and forth whether to use combined or separate PRT's, for a while now; and it seems that, until videocard memory sizes and bandwidths get a lot higher, it's better to stick to a unified PRT. The shader internally reconstructs the PRTP and PRTN from the PRT+UAO combo. This reconstruction is lossy, not perfect; but not too bad at all. Almost 95% right, or whereabouts.

Where to get...

Setting up a High Poly mesh for bakings

Why set up a high-poly mesh?

To get smooth results. Although both Blender and xNormal apply different types of interpolation to achieve smoothness, linear interpolations don't even compare to the smoothness you get by baking from a high poly mesh using Catmul Clark, 3D interpolation. Furthermore, this high poly mesh will be useful for baking a corrective normalmap, which will make your model seem as smooth as if it were using half a million polygons or more, without actually doing so.

When?

It doesn't matter, really; but the best time, in my opinion, is as soon as you start working on a model. Creasing edges (see below) can be a big job to do all at once; but it's a reasonably light burden if done progressively, as you work on the mesh.

How?

Simply tab to object mode if necessary, select your mesh objects in Blender, one at a time, press F9, Add Attribute and select Subsurf. You need Catmul Clark subdivision, Level 1 for Edit mode and Level 2 for renders. These are the defaults, anyways, so nothing to change, really. What you do want to change is the box at the far right of those three little boxes, to turn off showing the sub-surf mesh in Edit mode, as it may interfere with your ability to see parts of the geometry. To see the subsurf mesh, you simply tab to object mode. Never hit the [Apply] button!

Also, if you already have other modifiers, such as edge-split or mirror, make sure that the subsurf modifier is below the mirror modifier, but above the edge-split modifier. Click on the little UP triangle in the sub-surf modifier until it is above edge-split. With a big mesh, it may take as much as 30 seconds to respond, so if it seems that Blender didn't register your click, just wait…

Subsurf has wrecked my beautiful ship!!!!

No, it hasn't; don't panic. Yes, it looks like a wreck, but your model is intact (unless you hit [Apply]…). If you tab back to Edit mode, you'll see your model is not changed at all. But the sub-surf mesh IS a wreck; and the reason is that we haven't creased our edges yet.

What's “creasing”?

Creasing is marking an edge “sharp” for the benefit of the sub-surf modifier. Generally, all your sharp edges will have to be creased. You might ask, why doesn't sub-surf simply look at whether edges are marked sharp? Good question. Creasing is a lot more than marking edges sharp, though; and once you gain experience with it, there will be rare cases in which you'll want to crease an edge without marking it sharp, and viceversa. Also, creasing is not an all or nothing thing; you can semi-crease an edge. But let's keep this tutorial simple: In 99% of the cases, any edge you mark sharp you want to also fully crease. So, select all your edges marked sharp and crease them. Also, select all edges that make up mesh boundaries and crease them. A quick way to do the latter is to go to edge selection mode, press A a couple of times to make sure that nothing is selected, then go to the menu Select→Non-Manifold. Then crease them.

How do I crease?

It's similar to when you “mark sharp”. Instead of Ctrl-E, though, you hit Shift-E. When you hit Shift-E, you can control the amount of creasing by moving your mouse, but you rarely want to use the mouse. Just hit the [2] key, followed by [Enter]. Why 2? Well, could be 1, or 3; doesn't matter. Maximal creasing is 1.0; and if you enter 2 or 3 or 7 it will just be maxed out at 1.0 anyways. When you want to UN-crease an edge, hit Shift-E and enter ”-1” (minus one), then Enter. Again, could be -7; doesn't matter; it will just put the creasing value to 0.0. I think there's a bug or that there used to be one, that entering zero would not work; I'm not sure. I just enter -1 to be safe.

Now tab back to object mode, to take a look. Better?

But it's still not perfect…

Indeed not. Creasing is a bit of a black art. Sharp corners often get pulled-in, cob-webbed, even after creasing all edges marked sharp. When this happens, often the solution is to crease additional, non-sharp edges connected to the problematic corner.

Does it have to be perfect?

Unfortunately, yes. If it doesn't look perfect, it won't look perfect in-game. In fact, you'll need to spend a good amount of time checking your mesh bit by bit at high zoom level, to try and find any and every subsurf artifact, and fix it, before you proceed to the bakings.

Any other tips/recommendations?

Yes:

* Once you're done with the modeling, you might want to switch the subsurf level from 1 to 2, then 3, or 4 perhaps, and make sure you don't get snafus at the higher levels of subdivision. I don't have a magical number for what level of subdivision you should use for export. Just look at the resulting polygon count at the top of the screen: Anything above about 1/4 million polygons is probably good. A big carrier or space station might take more to yield good results. The reason we use only level 1 subsurf during editing is that using a higher number can cause blender to appear to freeze for a long time every time you try to tab to object mode; and most subsurf problems will be apparent with level 1, anyways; but level 1 is probably not good enough for bakings.

* You might want to make your greebles a separate mesh. Depends on what kind of greebles they are. Or, perhaps a better way to put it is, any parts of the geometry that are meant to look flat-shaded, like ladders and scaffoldings and square boxes and stuff like that, you gain nothing by subsurfing them, and they increase your burden of work creasing their gazillions of sharp edges. So, you might want to just separate such parts of the ship (highlight them and press P), and leave them withouth a sub-surf modifier.

Exporting the high- and low-poly meshes to .obj

Theoretically, we should be able to export both .obj's from this same mesh, simply by having the Apply Modifiers button on/off during the two exports; but in my experience this is problematic. Bugs in the exporter, inability to selectively apply some modifiers but not others… So, what I do is SAVE FIRST, then copy my mesh to another layer; then… In one mesh I delete [X] the subsurf modifer and [Apply] the rest. In the other mesh I [Apply] all modifiers, including sub-surf. Always apply the first modifier first; which should be sub-surf, –unless you have the mirror modifier, which should be on top of sub-surf. IOW, the order of the modifiers should be mirror first (top) if used, then sub-surf, and last edge-split; and should be applied in the same order. (Well, come to think of it, you won't have mirror on, at this stage, because you've already unwrapped your mesh, and you're not re-using parts of the texture, right?)

For the low-poly mesh, you want to export plain normals. For the high-poly mesh, export High Quality Normals.

DON'T save your blender file. We've just applied modifiers, which is not good; and cannot be un-done if you quit after saving. If you want to save, save under a new name, like obj_export_temp.blend.

Also, if you did separate greebles or other geometry to leave them out of the subsurf step, now you might want to re-join the objects, in both the high- and low-poly meshes. And this is another reason for NOT saving. Consider this a temporary blender file for producing bakes and exports; though, like I said, you can save it under a different name; but in most cases, if you need to go back it's probably that you need to fix something; and you'll have to do that in the original .blend file, and then repeat the copying of the mesh and applying subsurf to one of them, etceteras, so it is rarely useful to save. I actually DO save, under a different name; but more out of paranoia of accidentally saving under the original name. Once you save under a new name, if you accidentally hit save it saves again under the new name without destroying the original file.

Baking a Uniform AO (from Blender)

Now that we have high poly mesh, it would be insane to use the low-poly mesh for ao baking; so be sure you're in the layer of the high poly mesh, and that your high poly mesh object is selected.

To bake an AO in Blender, first you need to “load a texture”. This can be tricky and un-intuitive, so pay attention: Blender allows you to load different textures to different parts of the mesh; and this is not good for baking. In edit mode, make sure you select ALL facets, and in a UV-Edit window go to menu Image→Load, and load a texture of the size you want to bake. It doesn't matter if it's a picture of your cat's great-grandmother, as long as it's the right size (power of two sized; 4 x the size of final texture; usually square; so if your final texture will be 512 x 512 (typical for a fighter) you want 2048 x 2048 for the AO bake); –you won't over-write it, unless you want to. This is how you tell blender how big an AO you want. Weird, eh?

If you go to textured mode in the 3D window, you'll see your cat's great-grandmother wrapped around your ship.

Now you can tab to object mode, and hit Render→Bake Render Meshes→Ambient Occlusion.

But wait! First you want to set up the parameters for the bake. Hit F8 and look at the Ambient Occlusion panel. Turn ON Ambient Occlusion, if it's off. For the final bake you want to max-out the samples to 32; but this will take hours to bake, so I'd recommend about 11 to 16 for tests. The number of rays projected from each point is this Samples number squared. So, 11 is 121 rays; 16 is 256 rays; 32 is 1024 rays. 1024 rays is not really too many. I've used up to 16,000 rays in xNormal; but Blender doesn't allow higher numbers :(

You also want to set the mode to Raytrace, constant QMC, without jitter (I'd use jitter if I could set it for 4k rays, but at 1024 it produces too much noise). Limit ray distance to the maximum distance across your model. Don't use attenuation. Plain. Add.

Then hit F10, and look at the Render Bake panel. Make sure Ambient Occlusion is on, max-out margin, and be really sure that Normalized is ON.

If you want to watch the rendering (not recommended) set the texture area to fit nicely in the UV edit window, and hit Bake. If you get a message “no images to bake to”, it means you didn't load an image like I told you to. Remember: It's not enough to just load an image in object mode; you have to be in Edit mode, with ALL facets selected, and load an image.

NOTE: In my version of Blender, which as of this writing is not the latest, sometimes nothing shows during rendering, as if nothing was happening; but then all shows at once, once the baking is finished. Sometimes not. Just so you know. And it may take hours, so do go for a nice, big capuccino. A watched pot never boils. But if you want to minimize Blender and do other things with your computer, while it's rendering, I'd recommend you (in windows XP at least this works) hit Ctrl-Alt-Del, to get the processes window, right-click on blender, and set priority to below normal or low. Otherwise your machine will be really slow at doing anything else.

Once the baking is done you'll know it because the cursor comes back. Just before Blender crashes, hit Image→Save As, in the UV-Edit window, and save with a good name, like myship_UAO (for Uniform AO). Well, first you want to pick a good format… For test bakes, you want PNG, or even JPG. But for the final AO, be sure to select Open EXR. What's Open EXR? It's a newer format, saves a file “myship_UAO.exr”, which encodes colors at 32-bit (optionally 16-bit) precision per channel. MUCH higher precision than PNG (8-bits per channel). This is important because we'll use this AO bake to do corrections to the PRT's using a Blender noodle, using full precision so we don't get banding artifacts. Beware that a 2k by 2k texture in .exr format typically takes up over 100 megabytes of disk space. Gimp cannot open .exr's yet, AFAIK, but blender can load them. But you might want to Save As again, and save in .png format, for a version of the image you can look at with Gimp or Photoshop or Paint.

Then, in object mode, with textured mode, you can look at what the AO looks like on your ship (by going to edit mode, selecting all, and in the UV Edit window Image→Load the the baked texture, like we did before). It will never be right the first time; and you'll probably find artifacts that require editing of the mesh and/or the UV layout. Just warning you so you don't get unrealistic expectations. That's why I said, use 11 to 16 samples for test bakes, –because it may take several iterations of fixing things before it is right. One of the most common problems is with islands being too close or touching, in which case you may get bleeds from one to the other. Always make sure you have at least a few texels worth of space between islands.

Automatic unwrappers typically put no space between islands. Well, automatic unwrappers are hell, period. But if you succumb to the temptation to use them, you might have to scale the whole unwrap to about 90% and manually space the islands so they don't touch. Anyways, this is not an unwrapping tutorial.

Baking cosine AO (from xNormal)

Fire-up xNormal. Click on the top-right button, High definition meshes. You can right-click on the first line and get a context menu from which you can load your high mesh. Set scale at 16. Magical number. Well, xNormal uses some pretty high, absolute bias values, so you have to make the mesh bigger to avoid artifacts due to ray hits being missed because of the occluding geometry being too close. Just stick 16 there.

Notice at the bottom of the window there's a slider. Move it to the right, to be able to access the rest of the settings. Ignore per vertex AO and use exported normals. I suppose you exported high quality normas for the high mesh; yes?

Hit the second button, Low definition meshes, and load the low mesh. Set both frontal and rear ray distances to 0.1. This is for how far away the high mesh is allowed to be from the low mesh, at any point. If this is a huge space station you may need a much bigger number. 0.1 is good enough for a fighter.

Around the middle of the line, set it to use exported normals. No cages. No batch protection.

At the far right end of the line, mesh scale to 16, and match UV's.

Then we push the Baking options button. Enter a file-name for the output texture. Give it a .png extension if it's just for testing; otherwise a .exr extension, to have 16-bit precision. Turn off discard backface hits, if it's on. Turn on closest hit if ray fails. Max-out padding. Bucket size of 64 is just a guess; not sure what is best here; I'd have to run many ao bakes with different bucket sizes to see which yields the fastest results, and it probably depends on your cpu. My cpu is an old Athlon 64 working in 32-bit mode, so my results would be different from yours. I think 64 is a good starting bet. Check the Ambient occlusion line's check-box, and uncheck any others that are checked by default.

Then you hit the square icon with the ellipsis […] in line with Ambient occlusion, and set it up for Cosine, no attenuation, no jitter unless you're using more than 1024 rays, and no Allow 100% occlusion. Be sure that the occluded color is really black: click on it and ensure the r,g,b numbers bottom right are all zero. Make sure the white color is also really white: all r,g,b numbers at 255. Max out spread angle (179.50).

Before you start baking, you might want to save your settings so you don't lose them if xNormal crashes.

Now hit the round blue button, Generate Maps, and sit back, and sip a margarita, while watching the fireworks.

Well, as when baking a uniform AO from Blender, I would recommend that you start by baking a low quality test, like 256 rays, no antialiasing. Once you've verified there are no problems (by loading the bake as a texture in blender and looking around at the ship in textured mode), then you can proceed to bake a final; perhaps 1024 rays at 2x antialiasing with jitter. I've gone as high as 1024 rays and 4x antialiasing, which works out to 16k rays per texel. It took 3 days on my computer (for a 2048 texture), so I don't recommend it unless you're as crazy as I am ;-). Well, xNormal also has a GPU-accelerated “Simple Ambient Occlusion Generator” that works per-vertex and is much faster; but I don't even know how to work it yet; and I'll have to run a few tests before recommending it here. Stay tuned…

Baking PRT's (from xNormal)

Baking PRT's is as easy as baking AO's. You just select PRT's in the main settings page. Everything else is the same. In the PRT settings pannel (from the […] button), set rays to 256 for test, or 1024 for final. Bias of 0.001, threshold of 0.005, color normalize, and jitter on for final; off for test.

What are bias and threshold?

Bias is a small distance over which ray intersections are not considered. It prevents small rounding errors causing a ray to be accidentally collided with the same polygon from which it is being projected. Long story. 0.001 works ;-)

Threshold is a longer story. Long ago I requested a feature from Santiago Orgaz, the maintainer of xNormal, namely to consider fully occluded texels as background, rather than color them black; and let them be filled later by the margin algorithm. At the beginning he misunderstood my request and he set up a threshold. Later I was able to explain my requested feature better, namely that the threshold should depend on the number of rays (even if only one ray escapes, the texel should not be considered fully occluded) and he changed from a threshold to the “Allow 100% occlusion” checkbox we saw in the AO settings panel; but he never did the same for PRT's. I reminded him two or three times, but the Threshold is still there. Hopefully one of these days he'll get around to fixing that. In the meantime, having the threshold is infinitely better than not having it, and almost as good as the Allow 100% occlusion checkbox. If you want to set it scientifically, you could set it to about 1.5 / number of rays. So, at 1024 rays, the ideal threshold is 0.0015, rather than 0.005 (0.005 is about right for 256 rays), but this only makes a difference in the darkest of dark areas, so you probably won't notice it much. The only real advantage of having a “Allow 100% occlusion” checkbox –that we can dutifully leave OFF– is that it removes concern with having to set a seemingly arbitrary quantity that calls for a lot of explaining… for nothing.

Once the PRT's are baked, we'll need to normalize them.

Didn't we set the “PRT color normalize” flag?

Yes, we did, but it is not enough. Well, it's a very long story, but there are artifacts produced by the way xNormal interpolates. Actually, there are several options in xNormal: “Harden normals” uses the face normals to avoid artifacts; but this kills interpolation; so the bake looks as if your high poly mesh was flat-shaded. Without harden normals, the bake looks smoother, but there are artifacts such as obscuring of convex edges and lightening of concave ones. It could be that, by the time you read this, the problems have been resolved; but probably not. In any case, mathematically speaking, the sum of the values of red, blue and green of the PRTP and PRN textures for a given texel, all added together, should be 3.0 times the value of the uniform ambient occlusion at that texel. Knowing that, it is pretty trivial to design a blender noodle that reads in the PRTP and PRTN values, as well as the UAO we baked from Blender, and re-normalizes the PRT values to force them to be equal to UAO * 3.0.

Well, things are always more complicated than we wish them to be; aren't they? Blender's AO baking algorithm has some artifacts of its own. It is actually less accurate than xNormal with harden normals; per vertex rather than per texel. Blender also doesn't have an “Allow 100% occlusion” checkbox. It allows 100% occlusion, period; which causes black texel corners to show along where planes cross. But Blender's AO looks smoother, which is terribly important too. But so, the PRT_normalizer.blend noodle does a little more thinking than just assuming that the PRT's are wrong and the UAO is right: At the dark end of things, it's the UAO that is corrected to match the PRT's, whereas PRT's are corrected to match the UAO at the bright end. That's why the noodle outputs new PRT's AND a new UAO. And there are other special situations the noodle considers. Pretty sophisticated noodle, if I may say so.

Here's where you get the PRT_normalizer.blend noodle. You can download it into your main folder, or create a “texturing” folder under the main folder. If you open it with blender, it will look sort of like,

prt_norm_noodl_sm.jpg

Here's a link to the full-sized image: http://wcjunction.com/tutorial/prt_norm_noodl.jpg

There won't be images shown when you first open the file. You need to go to each of those boxes (inputs on the left, outputs on the right) and fill in the right names. To do so, click in the little folder icon next to the rectangular box for the filename, click on the file you want, or enter a name and click the select dir box on the right twice. You might want to turn off the Use Noodles button until you're done setting up things; otherwise it starts recalculating the textures at every change you do. You can stop a recalculation by hitting Escape.

Note that near the right, just before the texture output boxes, there are two RGB decomposers connected to two RGB recombiners; and the blue channels are crossed. This is because I was getting the back of the ship blue in the PRTP, instead of the front. Probably I did something wrong during exports to .obj. This is an area where, as of this writing, I'm not sure what's going on. I believe it is NOT a bug with xNormal, but rather a problem with .obj exporting and all that jazz of OGL versus DX conventions with the axes of coordinates. If you get wrong results, try disconnecting the blue channels, and connecting them straight.

Be very careful to feed the UNIFORM AO (UAO) to this noodle; and not the Cosine AO (CAO), as doing the latter would be a disaster for shadow and specular occlusion computations. The cosine AO is for use with ambient lighting only.

And as we did with ambient occlusion bakes, PRT's even more so call for test bakes and thorough inspections. Here's a particularly horrible example of artifacts of every sort:

prt_artifact.jpg

There's too many ways artifacts can be produced to cover here. This is one topic where problem-solving experience alone can serve you. The most common problems are islands too close, and non-seamed, sharp folding lines that don't line up orthogonally in the UV map. Generally, you should consider having seams in all sharp edges; never fold them; unless you know for sure that the edge will be either horizontally or vertically aligned in the UV map, as well as snapped to a good texel line.

Here's a view of the same area after a lot of such fixing; still not perfect…

prt_artifixed.jpg

But even with some artifacts remaining, the prt_normalizer.blend noodle will help smooth over some of them.

prt_artifixed2.jpg

Baking a corrective normalmap (from xNormal)

The title is slightly obsolete, in the sense that xNormal has the feature of accepting a bump-map in addition to high and low meshes; which means that it bakes “the normalmap”, as opposed to just “a corrective normalmap”. There used to be a bug in xNormal that prevented doing so correctly; but that's history now. On the other hand, bumpmap information is of much lesser seriousness than curvature correction, and so I wanted to emphasize the latter in the title.


wc_info/modding/ao_and_prt_bakes.txt · Last modified: 2009/04/26 15:56 by monkhouse