Subscribe to the RSS Feed Add to Google

3D Engine - Material & Lighting

September 5, 2008

In some previous posts, I've talked about the indie 3D engine I'm making, and today, I'll be talking a bit about how I will handle materials and lighting. As with every part of this engine, I will  keep it simple, and focus on techniques that have a big visual impact with little added complexity.

Remember this figure from the entry on the basics?

Mesh Definition

I already talked about the vertices/indices bit, but didn't go into any detail about the material bit, apart from mentioning that we only have one material per mesh (and possibly multiple meshes in a model).

Lighting and materials are important concepts. As well as making things look nice, materials are important to distinguish between different types of objects and surfaces, and lighting and shadow helps define the shape and position of objects.

The first thing to keep in mind, is that there's no way we can simulate real-world lighting, where incomprehensible numbers of photons collide with as many molecules, and all sorts of physics magic happens. We're not going to come even close, and we're not even going to try.

What we will do (as with everything else to do with games and graphics programming), is to use an approximation . It's not a goal in itself though, to keep improving this approximation  - we're aiming for a workable trade-off between performance and visual result. For this engine, I won't touch any of the more recent shader-based effects, as it would not make a big enough difference to warrant the extra work and the added complexity. I want this engine to run on more primitive hardware too, so as to maximize the potential market for the games using it.

Static vs Dynamic

There's two basic concepts we need to keep separate when we discuss lighting: static and dynamic. In most games, most of the objects shown on screen are static, meaning they won't move around relative to the other objects. This is the level, or world, that the action takes place in. Others (and fewer) objects are dynamic, meaning they can move around freely in the world. Those are the enemies, things you can pick up, projectiles, the player character and so on.

We're also going to have lights in the world. The simplest case would be to just have one light source - the sun - but commonly we'll have multiple light sources, especially if the game takes place indoors. And lights can also be static (meaning they won't move around) or dynamic (meaning they can move freely).

Vertex Lighting

Most 3D hardware supports simple lighting, meaning we can set an ambient lighting level (which affects every surface in the scene equally) and add a few directional lights, point lights and spot lights to our scene, and have the 3D hardware handle it for us, by calculating lights for each vertex, and then interpolate the lighting values across the surface of each polygon, and it will do it in real-time, recalculating the lighting every frame, so it will work with both static and dynamic objects and lights.

This is certainly useful, but it's got some limitations. First of all, we might need more lights than the handful that are supported by the hardware, especially for larger levels.

There's ways around this, for example by doing more lights by rendering the scene more times,but that can slow things down quite a bit. Another problem is that it doesn't handle shadows, which are an essential part of lighting, so we are going to have to do some extra work to get shadows. All the shadow techniques are quite expensive in terms of performance though, and some can have an impact on the time it takes to create models for the game too. And yet another problem is that for large polygons, the fact that light is only calculated at the vertices and interpolated across the surface, might cause lighting to look wrong in places.

Lightmaps

There is a nice solution to some of these problems: lightmaps. Lightmapping is a technique where you take the scene (objects and lights) and run it through a lightmap generator program. This will calculate the total light value for every pixel of every surface in the scene, and store it in textures. These new textures, or lightmaps as they are properly called, are then used in the game, in combination with the standard textures, to give us a fully lit scene, without the need of making any lighting calculations at run-time (though it does incur a slight cost in terms of using two textures for every surface - but this overhead is low).

Comparison of a scene with vertex lighting (top) and with lightmaps (bottom).

The lighting calculations we use when we generate the lightmaps can be as simple or as complex as we like. We can easily generate shadows as part of it, or use advanced lighting techniques such as radiosity, and it won't affect the performance, as it is all done as a separate step, before we import it into the game.

Light maps can make a massive difference, at a low run-time cost: if you look at the image above (from Quake3 Arena), you can see a scene using plain vertex lighting (top) and the same scene using lightmaps (bottom). We can clearly see some of the limitations in vertex lighting here - the red ambience is dominating the image, and there's an obvious lack of shadows, making shapes blend together and distances hard to judge.

The obvious disadvantage of lightmaps is that it only works for static objects and static lights - as soon as any of them move, we'd have to re-generate the lightmaps (and that would be too slow to do at run-time). Fortunately, most things in a scene can be static, and we don't really need dynamic lights (but we could use one or two moving lights in addition to the lightmaps if we really needed to, though they wouldn't cast shadows). So we will be using lightmaps for lighting the level/world, and vertex lighting for dynamic objects, and stay away from moving lights altogether. Remember, keep it simple!

Environment map

Environment map for reflective/glossy surfaces

There's one more thing I'll be adding to the light/material model: Environment maps. Environment maps are not necessary by any means - all they really do is make things look shiny. But they are quite easy to implement, works well even on older hardware, and you can easily disable them without causing any disruptions to gameplay, or even cause things to look wrong. They can be used both to make reflective surfaces (like chrome) and to add specular highlights, for glossy materials, so we'll be adding support for them, but making sure it is easy to toggle the on and off.

The Material

Material Definition

So, to sum things up, a material will consist of a basemap (so we can have things look like wood, stone, grass etc), a lightmap, and an environment map. All the maps will be optional, so we'll handle all combinations. Additionally, we'll be able to set the color of a material, which can be useful if we want to reuse the same basemap texture for differently colored objects.

All in all this makes for a fairly simple material, which will still allow for great visual impact. We'll get into more details when we come to implementing this, so consider this more of a statement of intent :-)


   Digg this Digg this    submit to reddit Add to reddit

<< Blur and Bleed: Running Games on a TV
RetroBox - Internals & Memory Map >>


Comments

There are no comments on this blog entry.

Write a comment








Video Games BlogRankers.com Video Games blogs Directory of Video Games Blogs Blog directory Game Blogs - BlogCatalog Blog Directory Free Page Rank Tool Bloggtoppen.se Blogg om Bloggar.Topplista.se - topplistan med de bästa bloggarna - lägg till din blogg du också! My Zimbio DigNow.net

© Copyright Mattias Gustavsson 2008. All Rights Reserved. Reproduction/republishing of any material on this site without permission is strictly prohibited.