custom shading functions
|
Basic idea:
|
fig. 1
color my_rim ( normal Nf; vector V; float rim_width )
{
float facing = 1 - Nf.V;
color C = smoothstep(1.0 - rim_width, 1.0, facing);
return C;
}
float facing sets the inverse of the facing ratio, otherwise
it will be black on the edges.
smoothstep takes 3 values that will use a user variable
rim_width to calculate how large the fake rim is.
|
Humble beginings:
|
fig.2 Ci = Oi * (Cs * (Ka * ambient() + Kd*my_rim(Nf,V,rim_width)) * rim_strength) my_rim is multiplied by rim_strength, also a rim_width user variable is plugged into the fig.2 function, which exists in shading.h, a header file. |
Plain english version:
|
fig.3
Ci = Oi * (Cs * (Ka * ambient() + Kd*my_rim(Nf,V,rim_width)) * rim_strength)
* (Kd * my_diffuse(N))
The combined rim is multiplied by my_diffuse, which attatches
a lighting model to it.
my_diffuse looks as such:
color my_diffuse ( normal N )
{
color C = 0;
illuminance( P, N, PI/2 )
C += Cl * normalize(L).N;
return C;
}
an illuminance loop defines how the surface reacts to light.
Diffuse is calculated by the dot product of N.L
normalize simply makes it fall between 0 and 1.
|
More user control:
|
fig.4 Ci = Oi * (Cs * (Ka * ambient() + Kd*my_rim(Nf,V,rim_width)) * rim_strength) * (Kd * my_diffuse(N) + ((-my_diffuse(N) + rim_ambient) * rim_ambient_strength)) rim_ambient and rim_ambient_strength user variables are introduced the non illuminated diffuse sides (-my_diffuse) of the object are mixed with the variables, and added to the shader to give control over an overall rim. |
Specular:
|
fig.5
Ci = Oi * (Cs * (Ka * ambient() + Kd*my_rim(Nf,V,rim_width)) * rim_strength)
* (Kd * my_diffuse(N) + ((-my_diffuse(N) + rim_ambient) * rim_ambient_strength))
+ specularcolor * Ks * glossy_specular(Nf,V,roughness, glossiness)
Finally, a glossy specular is added over it all.
//Based on Larry Gritz's glossy spec.//
//Additional thanks to Virginia Wissler//
color glossy_specular (normal Nn; vector V; float roughness, sharpness_glossyspec)
{
extern point P;
color C = 0;
float w = 0.5 * (1 - sharpness_glossyspec);
illuminance (P, Nn, PI/2) {
vector H = normalize (normalize(L) + V);
C += (smoothstep (.5-w, .5+w, pow (max (0, Nn.H), 1/roughness))) * Cl;
}
return C;
}
|
In action:
|
fig.6 Ci = Oi * (Cs * (Ka * ambient() + Kd*my_rim(Nf,V,rim_width)) * rim_strength) * (Kd * my_diffuse(N) + ((-my_diffuse(N) + rim_ambient) * rim_ambient_strength)) + (Kd * (my_diffuse(N)) + specularcolor * Ks * glossy_specular(Nf,V,roughness, glossiness) Finally, the actual diffuse of the surface (not the rim) is added. |
Default Settings, no light. |
|
Default Settings, 1 key light. |
rim_strength 2.2 rim_ambient 1.4 rim_ambient_strength 0.08 rim_width 0.7 |
Wide, softer rim, lower ambient, 1 key light. |
rim_strength 2 rim_ambient .741 rim_ambient_strength 0.08 rim_width 0.98 |
Focused, higher ambient + rim strength, 1 key light. |
rim_strength 2.761 rim_ambient 1.016 rim_ambient_strength 0.17 rim_width 0.59 |
Very low light, high rim + ambient rim |
rim_strength 3.278 rim_ambient 1.949 rim_ambient_strength 0.14 rim_width 0.78 |
| Conclusion:
The use of functions to call upon is quite powerful, it allows
|
|