Showing posts with label light vector. Show all posts
Showing posts with label light vector. Show all posts

Rayleigh scattering in Cycles

Prompted by a question in a comment by Joakim Poromaa Helger I came up with this approach to emulate Rayleigh scattering (the effect that turns the sky blue and the sun red at the same time) in Cycles: by combining a transparent and a glass shader.


In the picture above there is a bright white sun on the right. In a material that exhibits Rayleigh scattering (like air) blue light is scattered more than red light. That means that light traveling from a lightsource through such material will be tinted red because blue light is scattered to all sides. In a direction away from the direct path of the light we see just this scattered blue light and not (or much less) the direct light.

Now if we combine a red(ish) transparent shader with a blue(ish) glass shader, the transparent shader will cause some of the light to be passed through the object without regard for index of refraction and give it a redish hue, while the glass shader will pass some (refracted) blue light through and reflect some. (In the sample picture I have turned off caustics because that takes forever to give a good quality render but also because in this setup caustics exhibit a blue color while it should be redish as well). The node setup looks like this:

With some extra trickery we can correct the color for any caustics as well:

(Note that this image took 10,000 samples and the caustics are still very noisy. Clearly caustics is not Cycles strong point. The light/shadow inside the orb are due to the fact I placed it slightly below the ground but am to lazy to fix it).

We achive the caustic coloring by arranging that the camera sees the blue glass shader while any object receiving diffuse light (like the floor) sees a red glass shader, a distinction we can make with help of the light path node:
Now obiously the effect here is exagerated for demonstration purposes and arguably it is not a real simulation of Rayleigh scattering but for artistic purposes this might be a good start.



A phong ramp (car paint?) OSL shader for Cycles

A phong ramp closure has been available for quite some time in Blenders OSL implementation (see the commit log) but this hasn't been exposed as a shader node yet. That is quite simple to do and in this post I present a bare bones implementation of such a shader node

I don't know much about car paint shaders, may be the reflection color changes as well with the view angle and not just the diffuse color but this might be a start for people wanting to implement such a fancy shader. This shader might be useful as well to implement soap bubble irridescence in a different way. (you might want to check the dicussion on Blender Artists).

surface phong_ramp(
 float Exp = 1,

 color C1=color(1,0,0),
 color C2=color(.8,.2,0),
 color C3=color(.6,0.4,0),
 color C4=color(.4,0.4,0.2),
 color C5=color(.2,0.4,0.4),
 color C6=color(0,0.4,0.6),
 color C7=color(0,0.2,0.8),
 color C8=color(0,0,1),
 
 output closure color Cout = 0
){
 color colors[8] = {C1,C2,C3,C4,C5,C6,C7,C8};
 Cout = phong_ramp(N, Exp, colors);
}
As you can see, all there is to this code is transfering the input values to the arguments of the built-in function. The function takes an array of eight colors so we have created eight input color sockets. I admit that it lacks elegance but it works.

Example node setup

the sphere in the example image was created with the following node setup:

Getting a Light vector in OSL for Blender

OSL works with closures and closures are effectively summed over all lights in the scene. If you would like to alter for example the color based on some completely non physical interaction with a certain light as you do for some toon shaders you still might want to access a light object anyway. This article shows how this might be achieved.
Unfortunately what is described below does not work. Whether this is a bug or not I don't know, but getattribute("Lamp","object:location",L) does not get the location of the object named Lamp but the location of the object being shaded ... So no cel shading until this is fixed ...

The code below determines the light vector L by getting the object:location attribute from an object called Lamp and subtracting the point being shaded P. In Blender getting the location attribute in OSL only seems to work for real objects, not for actual lamps! (Maybe because a lamp has no node shader attached.)
shader oink(
color Color = 1,
output color Cout = Color
){
    vector L;
    getattribute("Lamp","object:location",L);
    P=transform("object","world",P);
    float cost=abs(dot(normalize(L-P),N));
    Cout = color(cost,1-cost,.2);  
}
Note that when we plug this calculated color for example into a diffuse shader, normal lighting calculations will still be performed, so in the example image we have a pinkish color on the side of the light object and a greenish color on the sides perpendicular to the light vector (including the side facing the camera). These colors are then diffusely lit by the same Lamp object (a bit too bright in this example :-)

Example node setup