Sign in to follow this  
spek

Lighting (ambient cubes and stuff)

Recommended Posts

Hi, Every time when I play HL2, my head is full of questions. Especially when it comes to the lighting. I know HL2 uses 3 lightmaps for the static environment. The normalMap tells how much to pick from each lightmap. I implemented that technique myself now, so I guess I understand how it works. But how about the dynamic parts? - Switching light on/off HL2 doesn't do much disco like Doom3, but there are scenes where the lighting can change. The best scene might be where flares go on one by one. How to lit the environment? Changing texture coordinates of affected surfaces so they pick another part of the lightmap? - Dynamic Objects... You can't use lightmaps for objects, but they need to integrate with the environment as well of course. As far as I can understand from the sheets, objects can use 2 "nearby" lights, a cubeMap, and a "ambientCube". If I understand it right, an ambientCube is a point somewhere where you measure the incoming light from 6 directions. But I think I'm missing something. In that case the ambientCube is basically the same as a cubeMap, but then with only 1 pixel per side. It's used for indirect lighting (just like the radiosity does for the static mesh). But... when I measure light from 6 directions on a certain part, it also takes the lightsources (and bright litten surfaces) if there are nearby. So when lighting an object there, it gets overbright. Probably I do something wrong, but my code is basically:
 color = decalMap * ambientCubeColor +
         decalMap * diffuseLight1+
         decalMap * diffuseLight2+
         < ambient / specular, etc. > 
The 2 diffuseLights are calculated just like you do normal lighting with "dot(L,N)". But now the ambientCube part is also included, which leads to too much light I guess, since the colors from that ambientCube have also measured those 2 nearby lightsources that were used for "diffuseLight 1/2". I'm confused... Another thing. How to determine which 2 lights/cubeMap/ambientCube to use? No I can place lights/etc./ entities into my map. When compiling the map, it makes a 3D cell grid. For each cell it checks which lights/cubeMap/ambientCube affects it. The closest/most powerfull entities are used, and in case of light it also checks if there's nothing between. When moving around a dynamic object, it uses the info from its current cell. It works, but its not really accurate, unless the resolution of that grid is extremely high. However, in HL2 the lighting seems to be pretty accurate. When you carry a box and move into a small stripe of shadow, the box will be darker. How are they doing that? I guess I've asked enough for now :) Greetings, Rick

Share this post


Link to post
Share on other sites
We are using something similar to ambient cubes in our project (it's actually an ambient/specular cubemap), but we generate it by rendering a small cubemap from our scene during pre-processing time (usually 32x32, resolution can be changed on individual cube nodes). We use ATI's cubeMapGen lib to generate seamless mipmaps for the cubemap and then save it as DXT5 compressed files. It also does a gamma adjustement to the cubemap before saving.

Since it's a render of the scene, it'll contain light reflected by the scene and skybox information, not the lights themselves (that's what dotNL is for). It's very nice for providing reflected ambient and specular lighting, and by controlling the mip level the material can be made more shiny or diffuse.

Right now we pick the two cubemap nodes closest to the object and interpolate between the two based on distance, but it isn't a very good approach because there is a popping effect when switching cubemaps. It also makes objects pick wrong cubemaps sometimes (like from behind a wall or something).

I'm not sure how HL2 selects the cubemaps for each object, but I'm planning to make a different approach where each cubemap node is made of a bounding box area and a movable sample point. The sample point tells where the cubemap is rendered from, and objects inside the bounding box are affected by that cubemap. Two cubemaps will only be used during transition: the old cubemap interpolates to the new cubemap over time when the object changes to a different cubemap area.

Also, maybe HL2 is doing the old trick of sampling the lightmap intensity right below the character, to darken an object when it steps on a shadow.

Share this post


Link to post
Share on other sites
I've read that paper, but the ambientCube thing remains a little mysterie. I think I'm adding the lights together the wrong way (see code in first post), which leads to an overbright result. The lightsources itself aren't rendered when getting making those ambientCubes, but the walls can be litten by the nearby lights, so light from that comes in the ambientCube anyway. I'm using HDR, so in some cases, the incoming light (reflected by walls) can be pretty intense, which makes it even more incorrect I think.

I was thinking about sampling the lightMap as well, but this is not how HL2 does it. I checked this by holding an object in front of me, behind a window where light comes through. When the object is too low/high, it won't catch the light from that window... so I suppose they are doing it differently.

Thanks for helping!
Rick

Share this post


Link to post
Share on other sites
Hard to tell, what is "too bright"? There certainly is a wide variance in brightness, since I use HDR. When creating the ambient cubes, I render the scene with the lightMap only (which is HDR as well)... but come to think of it... polygons that emit light are rendered too. I suppose that's not very smart to do. I should disable that.

That still leaves with that other question. How do objects in HL2 (or another game which uses lightmaps) decide what lights/ambientCubes/cubeMaps to use? Now my world is divided into cells from 0.5 x 0.5 metres (3D mensional). I could make those cells smaller, but it'g gonna take much memory then as well. In HL2 the world can be pretty large. so I don't think they use a real big grid or something. Or maybe they use a tree structure. Big cells for places that don't have much varying light, and smaller cells when the light is more varying... I don't know.

Greetings,
Rick

Share this post


Link to post
Share on other sites
When generating your ambient cube you should render LightMap * Albedo. That way, for example, if you have a white light and a red wall the reflected light will be red. This will also reduce the brightness of the reflected light.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this