Controllable shadow intensity and color
Aug 6th, 2008 by admin
Usually the Blender development projects that I work on are a direct response to a production problem I’ve encountered. BlenderPeople created animation baking, the Floor Constraint, Visual Keying and Python API enhancements. The Beast birthed Sequencer and Action Editor selection method upgrades. One other problem I ran into during The Beast was shadow control, but didn’t have time to address it in the sources during production. Often, I would get my light placement and intensity just right only to discover that shadows were just too dark in one or two places. As the balance between materials and lamps is tricky to get just right, I was loathe to start adding lamps (the standard method of fixing too-shadowed areas) or altering lamp intensity.
Wouldn’t it be easier, and better for the overall shading and looked that you’ve struggled to craft, if you could just turn down the intensity of the shadow of the offending lamp?
Of course it would!
Now you can.
This patch allows you to assign an RGB color to a lamp’s shadow. Although this isn’t a feature support “in the real world,” the world of 3D is full of time saving tricks and tools that allow artists to bypass the restrictions of the physical world, ironically, in order to present a more realistic view of it in their work.
The technical stuff is first for “proof of functionality” review, followed by a couple of images for the artists, and to show its utility.
The Technical Side
This annotated image (click on all images for full size) shows a 5 x 3 array of spheres between shadowing spot lamps and a textured plane. The top row is default shadowing (RGB 0,0,0). The middle row is a shadow value set to RGB 0.5,0.5,0.5, or, half intensity. The bottom row is a very yellow shadow color, RGB 1,1,0.
The columns, from left to right, show:
- Two shadow lamps, classic buffered, light energy set to red and blue, respectively, offset and crossing.
- One shadow lamp, classic buffered, white light. Sphere has Alpha 0.5, with zTransp activated.
- One shadow lamp, classic buffered, white light. Sphere is set to OnlyCast.
- One shadow lamp, ray shadows, white light. Sphere has Alpha 0.5 with Ray Transp enabled.
- One shadow lamp, irregular buffer, white light. Sphere has Alpha 0.3 with ATrans enabled at 0.3.
The plane has a simple texture applied, as well as TraShad to receive true transparent shadows from the Irregular and Ray shadow lamps.
Points of interest in this figure:
- Half-intensity shadow further lightens that already attenuated shadow from the irregular buffer and ray transp examples, as it should.
- Yellow shadow shades the already blue shadow from the ray column toward green, as it should.
- Colored shadows mix properly with the colors of other lamp’s illumination as seen in the dual-lamp column.
- OnlyCast, the center column, appears at it should.
The default shadow density (RGB 0,0,0) should appear exactly as it did before this addition to the render code. Indeed it does. The following image (click for full size) shows both the sphere example from above and a reference image rendered in Blender 2.46 superimposed in Photoshop with the Difference algorithm. The contrast has been radically boosted in order to show even slight differences. As you can see, the top row of cast light is completely absent, indicating that the renders are identical between the reference and the new method.
The changes to the Blender sources to achieve this utility are minimal. I found that the shadow handling code was organized well enough that I only had to add any real calculations to two locations. There were a small number of places that gate logic had to be enhanced a bit, and of course the addition of the RGB variables to the lamp structure, but overall, changes were surprisingly minor. Here’s the real engine of the thing, stuck into the portion of the code where shadows are determined:
if (i_noshad>i && !(lashdw[0]==0 && lashdw[1]==0 && lashdw[2]==0)) {
add_to_diffuse(shr->shad, shi, is, lashdw[0]*(i_noshad-i)*lacol[0], lashdw[1]*(i_noshad-i)*lacol[1], lashdw[2]*(i_noshad-i)*lacol[2]);
}
Basically, this just says that if there is some shadow here and the shadow isn’t set to default conditions (0,0,0), add a little bit of light back onto the surface that corresponds to the shadow color. Where this code is placed, it works with irregular transparent shadows, ray transparency and even textured lamps.
Render times are nearly equivalent, with a very small bump seen in the test file that contained fifteen shadow casting lamps.
Render time of scene in 2.46, averaged over 5 renders: 24.34 seconds.
Render time of scene in patched, averaged over 5 renders: 24.54 seconds.
Both the 2.46 and the patched version were built on the same machine with the same compiling options, etc. The only difference between the binaries is the patched code.
The original renders and .BLEND for this exercise can be accessed here:
The Artistic Side
While I’m sure that people making psychedelic videos and other kinds of wacky things will get a kick out of the colored (and textured) shadows, the feature’s real usefulness lies in the lighting of scenes for production work. As I mentioned before, getting the right look to your renders is a balancing act between the shaders and options of your materials and the intensity, color and type of your lamps. It has often occurred in my work (and others’!) that I can get everything just right, with the exception of shadow density. The shading looks good, the overall intensity of lamps is perfect. But the shadows are just too dark. The addition of a hemi lamp, sphere lamps, an ambient value or even Ambient Occlusion, the usual fixes for this, will change the overall shading/lighting for the worse.
The beauty of this solution is that it accomplishes the desired effect — less density in shadows — without adding light to anything that is not within a cast shadow.
In the following three examples, you can see a production frame, a promotional shot, and a set render from The Beast. In both the promotional shot and the production frame, the previously mentioned problem was encountered: undesirable shadow density but otherwise good lighting.
In the case of the production frame, seen below, the eventual solution was to simply add a Sphere Point Lamp and carefully adjust it’s distance and intensity to light the deeply shadowed area. In the end, this worked well enough for the deadline I was on. However, the shot still suffered from another area of problem shadow that I did not have time to address, and too much light in the original problem area. The first image shows the problem. The second image shows the same frame rendered with the patch in place and the shadow set to a medium intensity blue. Time for that fix: 10 seconds and one re-render. Time to add an additional lamp that screwed things up: 10 seconds and ten re-renders to try to get it right.
The next example is from a promotional shot for my book. Even tweaking lighting for a still, the strands of the character’s hair cast a shadow that was just too deep on her face. For initial forays into this shot, I had to fall back on rendering two versions of the shot: one with shadows and without, then hand-combining them Photoshop for a realistic shadow density. I ended up having to re-render later and decided to try it with the colored shadow feature. I simply attenuated the shadowing of the main spot lamp and the result was a perfect out-of-the-box render that needed no special treatment or retouching. As it was, it saved me twenty minutes on a tight deadline, and, had it been part of an animation, would have made the impossible possible. The renders you see here are a recreated example, though, as those original high res renders are not available to me at the moment.
In the two preceding examples, it is important to note how this effect is different from simply upping an ambient value or adding another non-shadow spot lamp to fill in the dark areas. With this technique, all other shadows remain at their full value. Areas not touched by the lamp with a colored shadow do not have to “suffer” its effects. In fact, it’s almost like using a spot lamp as a local, directional ambient value. Notice in both examples how strong shadows which were created by arms close to bodies have been toned down.
Additionally, it becomes obvious that the best use of this feature is when dealing with objects or characters that are in close proximity. Often, one object will cast a strong shadow on the other, and this is a simple and quick way for the artist to mitigate their strength to something more realistic to the situation.
Finally, an interior shot. Because of the nature of the set’s mesh structure (lots of long thin faces), Approximate Ambient Occlusion did not work well, so the entire set had to be lit with carefully placed shadow lamps. The differences between the two renders are subtle, as I had already done a great deal of work to achieve a passable interior lighting feel. However, the “difference” image below shows the mathematical difference between the renders.
Conclusions
Colored shadows, though not physically accurate, have been included in professional 3D packages other than Blender for years for the simple fact that they are a useful tool for the production artist. They have already saved time and produced a better result for me in my own production work. If the user does not care about them, they are in no way bothered by the new feature, as its interface consists of a single RGB color picker on the Shadow panel of the lamp buttons. With no interaction, the feature defaults to black shadows, which is the functional and visual equivalent of Blender’s current shadowing procedure.
From a technical standpoint, the changes to the sources to achieve this functionality are rather minor, due to existing shadow code’s fairly clear and clever setup.
If you are in favor of seeing this feature included in the official distribution of Blender at some point, the best thing to do is to use a build with colored shadows in your production work flow, and to forward some of the result of that work onto Ton Roosendal, as well as a small testimonial on how colored shadows helped you/saved your dog from drowning/etc. This patch affects the main shading code, so Ton is the ultimate arbiter of whether or not this one makes it in.
Thanks for taking the time!
Link to patch in the patch tracker…
If you’d like to make a build and put it up on graphicall.org, please post a link in the comment!


Standard shadows
Colored shadows




Wow, that looks pretty cool, hope to see that soon in next realease of blender.
Nick
This looks great. Rock on.
Thats great Harkyman! Great for simulation of reflected or incident light (and no raytracing required). I hope this makes it, it would be a terrific rendering shortcut.
Thankyou very much for your time too.
Thanks for this and all of the other wonderful things you have done for the Blender community. I wish I could help you out with a build
but unfortunately I was born brain dead when it comes to anything
dealing with code.
Thanks again.
Pimpmymonkey
another use:
very fast fake sss
Sounds great!!
very cool to see it looks like it made it into the trunk. congrats on the great work and contribution to the blender community.
great,i think this is a great addition, subtle color added to shadow will make warmer pictures, thx for this and all other things you coded for blender.
To Ton: Harkyman has really made the case for including this brilliant, useful tool/feature in all future releases of Blender. I am often leery to work with patches because, even if they get added into future versions, work done with the original patch inevitably only works correctly with the original patch. I experienced this with the Particles patch for 2.42a (which I’m very pleased to see was eventually incorporated into Blender proper, making future work a pleasantry).
So please please please do add this, Ton! *bats eyelashes* Pretty please with cherries on top. P.S. Dear Harkyman – *hugs* – thank you for your work and your very well-explained article on the usefulness and usage of Coloured Shadows. You rock!
Rachel
Wow… thanks so much for this. I have been wanting this feature for so long.
Very useful feature, will become nice for the next project
Sounds cool. Someone on blendernation suggested this could be used for simulating a TV image (”Wall-E” anyone?), but whne I look at the pictures here, I just don’t see that…
Great job !
Needed that feature a few times….now we have it !
Thanks
awesome roland! i love this “embracing of artifice”. especially if it helps you get the job done! and heck all of movie making is about cheating and faking anyway so this is just another great tool in the arsenal. pixar themselves frequently have a policy of raytracing as little as possible and faking whenever possible so you’re in good company at least. as for colored shadows, i think it was in the renderman book that says that they are indeed somewhat blue outdoors because the parts of the scene not hit but the sun are being illuminated by the SKY so it’s not entirely unrealistic either… if it needed to be justified… anyway, awesome work and rock on.
Haha tof!
Nice and easy. I dont like difficult difficult physics and radiosity, using them you should be an engineer, Thank you!
Hi harkyman,
Usually I’ve translated Blender release notes for Japanese people and put it to blender.jp website. So I want to translate this article as a part of Release note of Blender 2.48 and put it with your nice images too. May I do it?
Thanks,
yamyam — Please feel free!
Thank you for quick reply and permission to translation!
…May I ask you a favor once again?
On September 29th, we will have a party for blender users. (http://blenderartists.org/forum/showthread.php?p=1231188)
Also I noticed that your great movie, The Beast is available after posting my previous comment. I watched it and It’s really nice!
So I want to show it at the party.
Unlike the Blender Conference, It’s a small party, but I think it’s a great showcase of Blender’s features, and of course, a good pubcity for you and your book. Could I show your work?
Regards,