Home       About Me       Contact       Downloads       Part 20    Part 22   

Part 21: Light and Shadow

May 24, 2011

I decided months ago that I wasn't going to mess with lighting models until I finished building the world. It's another bottomless pit of complicated graphics techniques, and I'm not looking forward to it. Plus it didn't seem like a good idea to spend a lot of time implementing lighting in my static cube world, only to add polygonal terrain and moving objects later.

On the other hand, I knew that lighting would be important when building the world. Objects and landscapes look completely different when properly lit. Since I am building asteroids with lots of cave areas inside, it seemed even more important to know how much shadow there would be.

My solution to this was the ray tracer I built in parts 6 and 7. I would implement the world without lighting. To see it lit properly, I would export the scene from the demo into a file and render it with the ray tracer. Since I'm getting back into world-building after this long detour into multi-platform and performance tuning, I needed the ray tracer to work again. I had let the code that writes the triangles to a file drop out of the demo.

But then I wondered how hard it would be to do something like Minecraft lighting. Notch's original version just lit a whole face of a cube with one of 16 levels. I think the current version lights the corner vertexes, although I'm not sure. A search on "Minecraft lighting model" doesn't turn up much of use. What is there seems to be very specific to his block world. I wanted something that would handle my new polygonal terrain as well.

To start with, I decided I could fit another four bits of intensity information into my encoded vertexes. I also enlarged the in-memory version of the Octree to hold the intensity for the full 24 vertexes (6 faces times 4 corners) of a cube. Doing this gives me control of the lighting in the PC code, rather than doing it in the shaders.

I read up a bit on "ambient occlusion" and knew I would need to cast rays to implement that. Since I already had the ray tracing code, I decided to just use that. My thought was that I would hit a key, calculate the lighting for each vertex of all the loaded chunks of scenery, then be able to wander around and look at it. This would be easier to use than exporting it to the ray tracer and creating a movie.

Setting light at the vertexes means I'm not going to get real shadows. If a shadow falls somewhere within a cube face, I can only fiddle with the corners. This will produce some odd effects. See Figure 1.

Fig 1: A single dark vertex

Supposing that the bottom inside corner you see in the figure is in shadow, and the other two corners are in the light, the best I can do with vertex lighting is what you see -- an odd shadow coming out of the corner. I'm going to get effects like this wherever I draw light and shadow. So this will only be an approximation of what I'd get with the ray tracer.

I started by simply tracing a ray from the corner vertex to the sun. If there are no blocks hit, the face is lit by the sun using the usual lighting calculation (angle with the face plane.) If a block is hit, I leave it at background lighting. This produced an interesting result, shown in Figure 2.

Fig 2: With rays cast to the sun

The edges of the shadows are a bit odd as I expected. I'm not handling transparency, so things like leaves and the floating cubes are treated as opaque rather than casting fainter shadows. I made a stab a handling lights, but it still isn't right.

Unfortunately, stepping through the octrees along each ray, and then picking up the ray in the octree of the next chunk when it crosses chunks, is a pain in the neck. The code has some very odd bugs and I'm still tracking it down. It's also much too slow to use whenever a chunk is updated by adding or removing a cube.

I'm going to fiddle with this a bit more, but if there's no progress, I'll go back to asteroid building. I'll keep you posted.

Home       About Me       Contact       Downloads       Part 20    Part 22   

blog comments powered by Disqus