Imitating the Canvas Engine (1): Basic Shading Effects

Previous Post:
Imitating the Canvas Engine (0): Overview - Memories of Melon Pan

Now I'm coming to realize, I already made a post about basic cel shading and how I used it.

Giving Haku a little light - Memories of Melon Pan

The version used in my imitation Canvas shader makes use of the toon gradient shader on basic Lambertian shading, but it really hasn't changed much besides the numbers I use.

At first, I tried doing lighting in postprocessing, at the same time I did shadow mapping. If I did it this way, the preprocess shader would be really simple - just straight pass-through of the model's diffuse color. However, I was running into some of the common problems with shadow maps, which was making all that shading look weird in dark but colorful ways. There is stuff you can do to fine tune shadow mapping... in fact, there's a lot of little adjustments you can make to the basic algorithm, but I eventually wondered: in my original attempt at this, I wasn't seeing anything odd with my shadows. Why?

Because my shadows were being drawn so that these little discrepancies could be ignored. My shadows aren't coloring pixels, they're blending a separate texture into the scene, so I wasn't seeing too many artifacts in the final scene. Also, I changed my model from a bald soldier-looking dude to Haku, who has hair in front of her face. That will cause shadows unless there's some way you can tell that the vertex you've hit is hair or face, and thus should use a different shading model. I didn't have such a luxury, and Haku's face jumped from shadowed to not, then back pretty abruptly. It looked pretty bad, and so I went back to the preprocessor to do some of the shading.

LightAmount = (dot(Normal, -LightDirection) + 1.0) / 2.0

  • LightAmount [0.0, 0.575) → Intensity 0.85
  • LightAmount [0.575, 0.625) → (lerp between 0.6 ± 0.025)
  • LightAmount [0.625, 0.7) → Intensity 0.9
  • LightAmount [0.7, 0.8) → (lerp between 0.75 ± 0.05)
  • LightAmount [0.8, 0.875) → Intensity 0.95
  • LightAmount [0.875, 0.925) → (lerp between 0.9 ± 0.025)
  • LightAmount [0.925, 1.0) → Intensity 1.05

So, my basic preprocessing shader had to do some shading, but it didn't need to do shadows, since I was still going to do them postprocessing. That meant all needed to be done in preprocessing was convey volume, which is why my color intensities didn't dip below 0.85.

Next Post:
Imitating the Canvas Engine (2): Normal Maps and Depth Blur - Memories of Melon Pan