Baking dynamic lighting into static lighting?

Good afternoon,

Most of my light sources don’t move and don’t change in color and intensity. I cannot bake the light into my textures in blender because my scenes in the game are procedurally generated from pieces of walls and furniture, blender can’t know where the table will be relatively to the lamp.

Does Panda3d provide a way to bake the ambient and diffuse lighting into the textures, or into lightmaps?

Panda does not support ambient and diffuse maps at the moment (planned for a future release). You can emulate the effect, though.

A diffuse texture is equivalent to an ordinary MModulate texture, except that it will also change the colour of the specular highlight.

An ambient texture is equivalent to adding a second texture with the MAdd mode, except that you need to either manually multiply the texture with the colour of the ambient light, or use a more fancy combine mode.

Sorry, I just realised that you want to do the reverse - using Panda to generate ambient and diffuse maps instead of loading existing ambient and diffuse maps into Panda.

This is not possible out of the box, but it certainly can be done. You would need to transform the object into UV space, and render it there. One way this could be done quite efficiently is by using a shader that uses the UV coordinates of the model as final screen coordinates, but still uses normal lighting calculations, and then you can render the result into a texture. You would render three separate frames, one with the diffuse setting in the material set to white and the others set to black, one with only specular set, one with only ambient set.

Otherwise, you would have to create your own rasteriser code that draws triangles on an image by their UV coordinates, and you would calculate the lighting value of each pixel manually. It’s not exactly straightforward, but possible.

Don’t be too sorry, both your messages are enlightening :slight_smile:.

Unfortunately, this is still way beyond my skills. Furthermore, I can’t afford shaders; just turning them on divides my FPS by ten.

I think I understand the general idea though, and it teaches me a bit more how things work under the hood.

If there had been a node.bakeLights() method in Panda I would have toyed with it. Instead, I shall wait for the performance issues to actually show up in my game before worrying about this kind of things.

There’s this fake light thing - polyLight? Can’t remember the name… it’s not ‘real’ light just a (vertex) colour (scale?). Could that be used somehow to bake per-vertex lighting as vertex colour?

You would only run the shader for three frames or something, and it’d be a specialised shader, so it wouldn’t continuously eat up your frame time.

I’d create a sample, but unfortunately I’m swamped. :frowning:

I dug this out of my prototypes folder, from the first days of Cg.

All it does is render the mesh in UV space with the most basic lighting and everything hardcoded (even the light is just a node, instead of a light ;D), but it could be a good place to start. Putting an actual point light in there would probably be a good beginner Cg training :wink:.

You could dig more advanced lighting code from shaders dumped by Panda’s shader generator, but it wouldn’t be much of use – simple lightmaps can’t hold enough pixels for normal mapping.

from direct.directbase import DirectStart
from pandac.PandaModules import *

winProps = WindowProperties()
winProps.setSize(512, 512)
base.win.requestProperties(winProps)

model = loader.loadModel("../cube.egg")
model.reparentTo(render)
model.setPos(0, 0, -1)

base.cam.setPos(Vec3(0, -10, 0))
base.cam.lookAt(model)

light = NodePath("pointLight")
light.setPos(Vec3(0, 5, -5))

myShader = Shader.load("uv_render.sha")
model.setShader(myShader)
model.setShaderInput("pointLight0", light)

def turnModel(direction):
	model.setHpr(model, direction)
base.accept("w", turnModel, [Vec3(0, 10, 0)])

run()
//Cg

void vshader(
	// Input
	float4 vtx_position : POSITION,
	float2 vtx_texcoord0 : TEXCOORD0,
	
	float3 vtx_tangent0,
	float3 vtx_binormal0,
	float4 vtx_normal : NORMAL,
	
	// Input Uniform
	uniform float4x4 mat_modelproj,
	uniform float4x4 trans_model_to_world,
	
	// Output
	out float2 l_texcoord0 : TEXCOORD0,
	out float4 l_worldPosition : TEXCOORD6,
	out float4 l_normal : TEXCOORD7,
	
	//~ out float4 l_position : POSITION
	//~ // Texture render output
	out float2 l_positionUV : POSITION,
	out float4 l_position
	)
{
	l_texcoord0 = vtx_texcoord0;
	l_worldPosition = mul(trans_model_to_world, vtx_position);
	
	//~ l_position = mul(mat_modelproj, vtx_position);
	//~ // Texture render output
	l_position = mul(mat_modelproj, vtx_position);
	l_positionUV = vtx_texcoord0 * 2.0 - 1.0;
	
	l_normal = mul(trans_model_to_world, vtx_normal);
	l_normal = normalize(l_normal);
}

void fshader(
	// Input
	float4 l_position,
	float2 l_texcoord0 : TEXCOORD0,
	
	float4 l_worldPosition : TEXCOORD6,
	float4 l_normal : TEXCOORD7,
	
	// Input Uniform
	uniform float4 wspos_pointLight0,
	
	// Output
	out float4 o_color: COLOR
	)
{
	// BEGIN Test lighting
	float4 lightColor = float4(1, 1, 1, 1);
	float4 direction = l_worldPosition - wspos_pointLight0;
	float4 dirNormal = normalize(direction);
	float distance = length(direction);
	
	float4 att = float4(1.0, 0, 0, 0.001);
	float distAtt = 1.0 / (att[0] + att[1] + (att[2] * distance) + (att[3] * (distance * distance)));
	
	o_color = lightColor * abs(dot(dirNormal, l_normal)) * distAtt;
	// END Test lighting
	
	//~ o_color = (l_normal + 1) * 0.5;
	//~ o_color = (l_worldPosition + 1) * 0.5;
}