surface
gather_Cs(float samples = 64,
tint = 0.15,
blur = 15,
falloff = 5,
Kd = 0.8)
{
normal n = normalize(N);
// Simple use of the gather function
float spread = radians(blur);
color hitC = 0;
color totalC = 0;
float hits = 0;
float len = 0;
float totalLen = 0;
gather("illuminance", P, n, spread, samples,
"surface:Cs", hitC,
"ray:length", len)
{
hits = hits + 1;
totalC = totalC + hitC;
totalLen = totalLen + len;
}
// Average the colors we have gathered
color gColor = (totalC/hits) * tint;
float gLen = totalLen/hits;
gColor = gColor * (1 - smoothstep(0,falloff,gLen));
// Real simple lighting ??
color diffusecolor = diffuse(n) * Kd;
Oi = Os;
Ci = Oi * Cs * (diffusecolor + gColor);
}
|
We then approached the problem of using the same technique on a displacement shader. It was decided to use a point cloud to store the information about the accumulated displacements. However, some difficulties arose when trying to ascertain the distance from the displacing object to the displaced surface. Originally I was arbitrarily inputing the distance between these two objects because it seemed the only solution at the time, however many artifacts appear around the edges of the displacement: |
displacement
accumDisplace(float Km = -0.1, /* [-1 1] */
maxHump = 1, /* [0 5] */
spread = 0,
samples = 1;
string traceset = "";
string bakename = "")
{
normal n = normalize(N);
vector diff = n - normalize(Ng) ;
float hump = 0;
float blur = radians(spread);
float len = 0;
float totalLen = 0;
float hits = 0;
float gLen = 0;
float currDisp = 0;
point displaceP = 0;
float prevDisp = 0;
if(bakename != "")
if(texture3d(bakename, P, N, "_prevDisp", prevDisp) == 0) {
prevDisp = 0;
}
gather("illuminance", P, n, blur, samples,
"subset", traceset, "displacement:P", displaceP,
"ray:length", len)
{
float trueLen = distance(displaceP, P);
hits = hits + 1;
totalLen = totalLen + trueLen;
gLen = totalLen/hits;
gLen = gLen - max(gLen,maxHump);
}
else
{
gLen = 0;
}
currDisp = gLen;
if(abs(currDisp) < abs(prevDisp))
currDisp = prevDisp;
if(bakename != "")
bake3d(bakename, "_prevDisp", P, N, "interpolate", 0,
"_prevDisp", currDisp);
P = P - currDisp * n * Km;
N = normalize(calculatenormal(P)) + diff;
} |
Caveats
1) If the objects get too close to the displaced surface, the distance between the surface and the object is considered much higher than expected due to the gather ray firing in front of the object (say, inside the sphere for example).
2) Increased control would need to be given to the user within Maya to constrain the point cloud position to the movements of the displaced object.
3) Right now, the shader requires the objects to have a displacement attached. A modified version of the shader should include both options.
These caveats among others may be worth fixing if the time presents itself later in the quarter. |