Radiosity baking in Blender (HOWTO)

Need help testing contributed art or code or having trouble getting your newest additions into game compatible format? Confused by changes to data formats? Reading through source and wondering what the developers were thinking when they wrote something? Need "how-to" style guidance for messing with VS internals? This is probably the right forum.
Post Reply
tiny paintings
Bounty Hunter
Bounty Hunter
Posts: 214
Joined: Mon Jun 27, 2005 7:35 pm
Location: Stockholm, Sweden
Contact:

Radiosity baking in Blender (HOWTO)

Post by tiny paintings »

EDIT: OUTDATED! A more recent, improved version is in the wiki. (special thanks to pontiac for transfering the original text!)

Prelude:
As I promised (quite) some time ago here's a little howto for baking radiosity in blender. I tried making it easy for non-blenderheads to use it too but a bit of know how of blender is good (look at http://download.blender.org/documentation/htmlI/ if you need something to get you started). The method described here was developed and tested with 2.37, and may be incomplete or incorrect.

Also, I tried to make a wiki page for this... unfortunately my wiki-editing skills weren't quite sufficient :S Feel free to transfer this post to the wiki.
Okay, here we go:

Our goal

There is no such thing as the ambient lighting most 3D applications and games use, period. An exposed part of the model will receive more ambient light than parts hidden deep beneath pipes and plates. Since we can't simulate this in real-time (at the moment, at least) putting this information in the texture is the way to go. How you ask? The most straight forward method is guessing and painting by hand, but it is also very time consuming and not to mention getting good results is hard.

Compare the following two pictures:
Image

Even though I used two slightly different meshes they should illustrate the difference, clearly the lighting on the latter picture looks more natural.

Image

In the end, this should slightly alleviate the texturing process and make for promising results.

Our weapon of choice: Radiosity

As I mentioned above our goal is to calculate some kind of ambient light dependent on the geometry, which we'll use radiosity for. If you don't know what radiosity is, please visit the link above to find out.
All right! Just follow these steps:

1) Load your UV-mapped object into Blender and put it on layer 1. Make sure it is UV-mapped! Also get rid of any lamps lingering in the scene.
2.1) Add an icosphere with its center roughly in the middle of your model (SPACE->Add->Mesh->Icosphere). This will be our ambient light source. Higher subdivision yeilds better results (you need a higher value for a mesh with many polygons, play around!) but longer calculation times, 4 should be sufficient.
2.2) Scale up (S) the ico-sphere to encompass your entire model.
2.3) In edit mode (TAB) select all the faces (A) and flip the normals (W, 9). Turn on normal drawing and make sure they're really pointing inward the sphere (F9 and enable "Draw normals").
2.4) Go to the material buttons (F5) and add a new material to the sphere. Choose the desired light color (white, normally) and give the material some emission, you have to experiment with the emit value but 0.02 should be a good starting point.

You're now ready to start calculating the radiosity. But before you start you might want to subdivide your mesh a few times, to get better results. Do it, say, twice (W, 1 and repeat).

3.1) Go to the shading context (F5) and then the radiosity buttons. Select both the meshes and press "Collect meshes". Switch from "Solid" to "Gourad".
3.2) IMPORTANT: Set MaxEl (not ElMax!) to 1. This will ensure that Blender doesn't alter the mesh in any way.
3.3) Hit "Go" and lean back. Press ESC when you're happy with what you see or wait until it finishes. It shouldn't be all black, if it is something went wrong.
3.4) This is optional but if your results are a little spotty or have artifacts you might want to perform "Face filter" or "Element filter", or both.
3.5) Save the radiosity information in a new mesh by pressing "Make new mesh". Move it to layer 2 (M, 2).

Now it's time for a little cleaning up before we can bake the radiosity information to a texture. Remove the icosphere from the newly created mesh with the radiosity information. If you're not comfortable with blender, here's how you do it (if your mesh is one solid mesh!):
4.1) Go to layer 2 (2). Select the mesh and enter edit mode (TAB). Split the meshes by pressing P, 2. Leave edit mode (TAB) and delete the sphere.

Now, since using the radio tool erases all UV-information from the baked mesh we'll need to transfer the vertex color information from it to our original mesh somehow. After trying various methods for doing this, none of which worked, I hacked together a small little script in python to do it (you have to pardon my python n00bness, this is all I could come up with. Feel free to improve it!):

Code: Select all

import Blender

# WHAT DOES IT DO?
# This script copies the vertex color information from one mesh
# to another, and does so correctly assuming the meshes have the
# same geometry, vertex-wise.

# IMPORTANT: Assumes meshes with exactly equal geometry, vertex-wise.

fromObj = "Mesh"  # Set this to the resulting mesh from radio calcuation
toObj = "Fuselage_default" # Set this to the name of your original, UV-mapped mesh.

me_from = Blender.Object.Get(fromObj).getData()
me_to = Blender.Object.Get(toObj).getData()

if not me_to and not me_from:
	print "ERROR: Source/destination object does not exist"

elif len(me_to.verts) != len(me_from.verts)
	print "ERROR: Source and destination objects must have the same number of vertices"
	
else:
	# make two lists sorted on coordinates,
	# containing a face and vertex index i and j respectively
	
	l_to = []
	l_from = []
	
	# format: [ (x,y,z, face index, vertex index), ... ]
	
	for i in range(len(me_to.faces)):
		for j in range(len(me_to.faces[i].v)):
			vert = me_to.faces[i].v[j].co
			l_to.append((vert[0], vert[1], vert[2], i, j))
			
		for j in range(len(me_from.faces[i].v)):
			vert = me_from.faces[i].v[j].co
			l_from.append((vert[0], vert[1], vert[2], i, j))
		
	# Sort the lists after vertex coordinates
	l_to.sort()	
	l_from.sort()
	
	for i in range(len(l_to)):
		to_f = l_to[i][3]
		from_f = l_from[i][3]
		to_v = l_to[i][4]
		from_v = l_from[i][4]
		
		me_to.faces[to_f].col[to_v] = me_from.faces[from_f].col[from_v]
			

	me_to.update()
	print "Copied vertex color information from object "+fromObj+" to object "+toObj+"."
Load it, change the mesh names at the top of the file, run it and voila! For the blender impaired here's what you do:

5) Shift-F11 to bring up the text editor, load the script from the menu or paste it and then press Alt-P to run it.

Your original, UV-mapped, mesh should now have all the shading information stored safely in the color of each vertex. You should be able to verify this if you set your viewport shading to "Shaded" (make sure VCol Light is enabled for your material).
The final step is to bake the vertex color information to texture using your favorite baking script.

6) Enable "VCol Paint" and "Shadeless". Run "Texture baker" (found under Scripts->UV and included with Blender). If it doesn't work the first time make sure your mesh is indeed on layer 1 and try again.

That's it!

You can do even more...

Using the same technique you can do even more nifty stuff, such as baking glowmaps:
Image




ENJOY!
And if you have some time to spare I'd rellay appreciate to have this transfered (and improved upon) to the wiki as mentioned above.
It's 3:40 AM so typos and various inconsistancies are likely... :)

EDIT: Maybe I should have posted this in the artwork forum? Oh well...
Last edited by tiny paintings on Thu Sep 22, 2005 5:36 pm, edited 2 times in total.
Guest

Re: Radiosity baking in Blender (HOWTO)

Post by Guest »

tiny paintings wrote:Also, I tried to make a wiki page for this... unfortunately my wiki-editing skills weren't quite sufficient :S Feel free to transfer this post to the wiki.
Done. May need some tweaks tough ;)

Cool tutorial btw 8)

Pontiac
tiny paintings
Bounty Hunter
Bounty Hunter
Posts: 214
Joined: Mon Jun 27, 2005 7:35 pm
Location: Stockholm, Sweden
Contact:

Post by tiny paintings »

Cool beans. Thanks!

We'll see if anyone is brave enough to try it out :) (and report all the troubles they will have hehe)
CoffeeBot
Intrepid Venturer
Intrepid Venturer
Posts: 676
Joined: Wed Jul 06, 2005 5:25 am
Location: On the counter by the toaster
Contact:

Post by CoffeeBot »

you betcha ima try it out.

and expect a lot of questions and complaints in the process :D

this will help out a lot with some of the stuff chuck wants me to do with the space elevator.

and maybe one day, i'll start using caps.
tiny paintings
Bounty Hunter
Bounty Hunter
Posts: 214
Joined: Mon Jun 27, 2005 7:35 pm
Location: Stockholm, Sweden
Contact:

Post by tiny paintings »

CoffeeBot wrote:and maybe one day, i'll start using caps.
lol
CoffeeBot wrote:this will help out a lot with some of the stuff chuck wants me to do with the space elevator.
If 3D interiors ever comes true baking radiosity for them will rock :) You really need some kind of concavities to make it look interesting. How's the elevator coming along anyways? Updates, updates!! :D
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Great stuff, TP! I guess we're all gonna have to figure out Blender, now. I will definitely use this for your yatch for WCU. Right now it's in the backburner because I'm part working on autopilot code, part working on a WCU plot. And I loaded the ship into Wings, a week ago, hoping to add 2 launch bays underneath, but didn't even know where to start. That'll be perfect for radiosity to shine :). I guess I'll just have to go through the Blender tutorials, when I have time.

Nice ship, BTW!
pontiac
Elite
Elite
Posts: 1454
Joined: Sun Jan 12, 2003 6:24 pm
Location: Far out in the uncharted backwaters of the unfashionable end of the western spiral arm of the Galaxy
Contact:

Post by pontiac »

Ok, i tried the tutorial and documented my problems/questions here:

http://vegastrike.sourceforge.net/wiki/ ... ry_changes

Pontiac
pontiac
Elite
Elite
Posts: 1454
Joined: Sun Jan 12, 2003 6:24 pm
Location: Far out in the uncharted backwaters of the unfashionable end of the western spiral arm of the Galaxy
Contact:

Post by pontiac »

More user-friendly script is now in the wiki:

http://vegastrike.sourceforge.net/wiki/ ... der#Script

Pontiac
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Great! I'm dreaming, perhaps, that one of these days there might be a big retexturing campaign, EVERYBODY working on retexturing for 10 days and all ships get done... Using baked ambient self shadowing, baked self radiosity, proper specular and glow maps, and standardizing pixel size to 1x1 meters maximum... :D
I just put a thread suggesting having separate direct and ambient textures, to take advantage of radiosity baking to the max. It's here:
http://vegastrike.sourceforge.net/forum ... php?t=5385
tiny paintings
Bounty Hunter
Bounty Hunter
Posts: 214
Joined: Mon Jun 27, 2005 7:35 pm
Location: Stockholm, Sweden
Contact:

Post by tiny paintings »

chuck_starchaser wrote:Great! I'm dreaming, perhaps, that one of these days there might be a big retexturing campaign, EVERYBODY working on retexturing for 10 days and all ships get done... Using baked ambient self shadowing, baked self radiosity, proper specular and glow maps, and standardizing pixel size to 1x1 meters maximum... :D
I just put a thread suggesting having separate direct and ambient textures, to take advantage of radiosity baking to the max. It's here:
http://vegastrike.sourceforge.net/forum ... php?t=5385
Add normal maps to that list! We'll be able to use 'em after the ogre transition (ogre will bring us stuff like normal maps and shadows, for players with beefy video cards, for free! yay!!)
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

When used with moderation and subtlety, bump maps are wonderful. And shadows will be the ultimate. Shadow maps should be pretty easy to implement in a per-unit basis, I'm thinking. Just for self-shadowing. Traditionally, the problem with shadow maps is trying to cover a whole scene with them. Then, some simplistic projective shadow for between objects. Should also be easier than in most engines, since we only need parallel projection.
As soon as Ogre and GLSL shaders are in, let's organize a TEXTURATHON. :D
Did you see Strangelet's Gizmo?
http://vegastrike.sourceforge.net/forum ... php?t=5377
tiny paintings
Bounty Hunter
Bounty Hunter
Posts: 214
Joined: Mon Jun 27, 2005 7:35 pm
Location: Stockholm, Sweden
Contact:

Post by tiny paintings »

Thanks to pontiacs bug-testing there's been some very important changes to the script.
Everyone that downloaded the script should probably update it. And if you had troubles getting it working, an update just might be what you need!
chuck_starchaser wrote:When used with moderation and subtlety, bump maps are wonderful. And shadows will be the ultimate. Shadow maps should be pretty easy to implement in a per-unit basis, I'm thinking. Just for self-shadowing. Traditionally, the problem with shadow maps is trying to cover a whole scene with them. Then, some simplistic projective shadow for between objects. Should also be easier than in most engines, since we only need parallel projection.
As soon as Ogre and GLSL shaders are in, let's organize a TEXTURATHON. :D
Did you see Strangelet's Gizmo?
http://vegastrike.sourceforge.net/forum ... php?t=5377
Actually, normal maps are even more wonderful when they're applied all over the model: http://en.wikipedia.org/wiki/Image:Norm ... xample.png.

Yup I saw strangelets gizmo but it won't run on my linux box... requires some fancy schmancy plugin.
Post Reply