Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
66 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

Contents
 Introduction
 Advanced Topics
 Conclusion

 Printable version
 Discuss this article
 in the forums


Advanced Topics

Now things get difficult. Why? Because we're going to cel-shade textures - something that I have never actually seen done before (I've had to work out all the theory behind this section on my own). So, what you're getting now is 100% original.

Cel-Shading Textures

Now, there are 2 ways of doing this - multiple texturing and my way. Seeing as not every graphics card supports it (almost), we're going to do it my way :-). First, though, we need to revisit the Sharp Lighting map.

In this method, we are actually switching the roles of the texture and vertex color. Instead of the texture shading the color, the color is going to shade the texture.

Creating the Sharp Lighting Map

Remember that lovely little image featured previously in this article? If not, then here it is again:

Previously, we uploaded this texture to whatever API we are using. Now, we keep the values ourselves. Once we've loaded the texture, we have to create an array of floating point values (if you're storing the texture in byte format then just divide each pixel component by 255) and copy over the values. For the object itself, we need to change how we store the data. Here is a list of the data required:

  • Vertex positions.
  • Vertex normals.
  • Texture coordinates (proper ones, not the 1D Sharp Lighting map).
  • Sharp Map value (per vertex). This can be stored as an integer.

The only thing we've changed is the vertex colors, which have been replaced with texture coordinates. Now we have a locally stored Sharp Lighting map with object data. Time to do some software lighting.

Lighting Textures

This part hasn't changed much since the last time we discussed lighting. Directional and positional lighting still both work in exactly the same way, but the only difference is that when calculating the dot product of the directional vector and the vertex normal, we multiply it by however wide our Sharp Lighting map is (in this case 16) minus 1 (because the range is 0-15) and cast it into an integer. This integer represents an index in our light map, and will be turned into a color when rendering.

Rendering Cel-Shaded Textures

In DirectX and OpenGL, if you specify the color of the vertex along with the texture coordinate, the color of the texture will be modified to match the color of that vertex. Now, since we're using grayscale values, specifying the color of the texture will brighten/darken the vertex, but combined with Sharp Lighting, it looks cel-shaded. Pretty clever, eh?

So, we specify the color of the vertex. This is done by retrieving the Sharp Lighting value from the vertex structure, and looking up the value in the index map. This gives us a single value. Now, because we're using RGB (if you're not then you can work this bit out on your own), we simply use this value for all components of the RGB triplet. For example, if the lighting value was 0.4, then red would be 0.4, green would be 0.4, and blue would also be 0.4. We then specify the proper texture coordinates of the vertex and finally the position of the vertex. Remember to disable blending and lighting and enable texturing. You should then have a cel-shaded texture drawn onto your screen. If you're using a simple quad it will probably look a bit odd - try tesselating it more (4x4 or something), and it will look better. Highlighting is performed the same way as we discussed before.

Summary

Here's a brief summary:

  1. Load the Sharp Lighting map from file and store in an array (remember to convert values to a range of 0-1).
  2. Calculate the lighting as normal, but multiply the dot product by the width of the texture - 1 (remember 0-15), and cast it to an integer.
  3. When drawing, lookup the color to use in the Sharp Lighting map array, using the lighting value as the index.
  4. Use this value for the red, green and blue values of the vertex color.
  5. Render the object like you would normally, but remember to update the color for each vertex. Don't forget to disable lighting, etc.
  6. Draw the highlights (same as before).





Next : Conclusion