Bending light in Cycles

In today’s tuto­r­i­al we’ll break the laws of physics, and prove we can abuse nodes to make Cycles do any­thing we want

I post­ed about this effect on Twitter some time ago as a “use­less exper­i­ment”. People were inter­est­ed in it, so I’ve gone back to look deep­er into it. The trick is fair­ly sim­ple: make an object look like it’s being lit from the oppo­site side using only a Cycles material.

As you can see, there’s only one light in the scene, a Sun lamp. You can actu­al­ly make the light come from any direc­tion, since it’s con­trolled by a nor­mal node.

I’m using the vec­tor math node to push the nor­mals around. To do that I grabbed the nor­mals com­ing out of the Geometry node and the out­put of the Normal node. The Separate XYZ sec­tion helps push the coords in the right place and smooth a the shad­ing a lit­tle more.

Here’s the noo­dle for Suzanne’s mate­r­i­al (the oth­ers have the default material).

So, how does it work?

It’s a lit­tle hard to say since you can’t see what nor­mals look like inside Cycles. My guess is that nor­mals are being pushed inside the mesh. The nor­mals of the faces close to the light become near oppo­site to it, while the far­ther faces point clos­er to the light source.

Normals are vec­tors (think of them as lines) per­pen­dic­u­lar to faces and ver­tices. Normals are used for a num­ber of things, one of which is to cal­cu­late how light­ing hits and illu­mi­nates a mesh. As far as I know only face nor­mals are avail­able in the Geometry node, so those are the ones that con­cern us.

The dif­fuse com­po­nent of a mesh’s light­ing is cal­cu­lat­ed accord­ing to Lambert’s Cosine Law . To cal­cu­late how much a point in the mesh is illu­mi­nat­ed by a ray of light, we mul­ti­ply the amount of light in the ray by the cosine of the angle between the nor­mal and the ray.

  • A ray of light com­ing at a 90º angle to the nor­mal results in a cosine of 1. That face would receive all the light from the ray, becom­ing very bright.

  • Angles between 0º and 90º result in cosines between 0–1. Less light is applied the clos­er to zero, it looks like the light enery is “spread” through the mesh.

  • Ray lights com­ing at 0º result in a cosine of zero. Since the light amount is mul­ti­plied it, this angle pro­duces no light.

  • Obtuse angles (between 90º-180º) pro­duce neg­a­tive cosines which gets clamped to zero, also pro­duc­ing no light at all.

So how does this explain the bend­ing light effect? If the nor­mals close to the light point away from it, the angle they pro­duce becomes obtuse. As we’ve seen that means they receive zero light. On the oth­er hand, nor­mals far­ther away start point­ing towards the light pro­duc­ing acute angles and cosines in the range 0–1. That means they receive light. You could think of it as light pass­ing through the object, rather than bend­ing around it.

Note that Lambert’s Cosine Law uses the term “direct­ly pro­por­tion­al”. I haven’t looked at Cycles’ code, so I don’t real­ly know if it’s direct­ly mul­ti­pling or using a dif­fer­ent formula.

I’m not much of a math guy myself, but if you’re inter­est­ed in learn­ing more about this you can start with the 8th Chapter of the OpenGL tuto­r­i­al and Scratchapixel.

Smoothing it up

Of course once you start muck­ing around with nor­mals like this, you also kill smooth shad­ing (since face nor­mals are inter­po­lat­ed from ver­tex normals).

To fix that we need two things:

  • First, work with a high­ly sub­di­vid­ed mesh. If you’re using the sub­surf mod­i­fi­er, you need to apply it. Otherwise the geom­e­try node will use the unsub­di­vid­ed mesh data.

  • Use a tweaked nor­mal as a col­or input to give them a smoother appere­ance. I used a nor­mal node to shift them to the cor­rect posi­tion and a mul­ti­ply node to bump the brigthness.

Bonus! Try some textures with it

While play­ing around with this idea, I also found some inter­est­ing effects when mix­ing nor­mals and textures.

One of them is Plasma-ish noise! I’ve want­ed to make plas­ma like effects in Blender for a while, they look so demoscene.

To make this hap­pen I took the object’s coor­di­nates, sub­stract­ed from with a noise tex­ture then added to the result with anoth­er noise tex­ture. The nois­es have dif­fer­ent scales so they cre­ate sorts of ridges and islands in the coor­di­nates. Finally I sub­stract­ed a val­ue to off­set the coor­di­nates (which I can ani­mate) and fed it into the final noise texture.

The oth­er effect is a rep­til­ian-ish skin using the mag­ic tex­ture. This is dou­ble cool because it’s hon­est­ly the first good use I’ve found for that node.

The effect is gen­er­at­ed from nor­mals so you can use the col­or sock­et for more details or a dif­fer­ent tex­ture. You can tweak it too by mov­ing around the nor­mal node orb.

Stay foolish, stay hungry…

I think the most inter­est­ing part of all this tricks isn’t the actu­al effects (which you’ll rarely use), but how far you can go with nodes. Always keep in mind that if some­thing can’t be done in an obvi­ous way, it can sure­ly be hacked togeth­er with nodes. So, keep an open mind! Spend some qual­i­ty time try­ing stu­pid com­bi­na­tions and study­ing how the engine works.

All the posts you can read
TutorialsBlender, Cycles03.09.2018