#include "rmannotes.sl" /* #define pulse(a,b,fuzz,x) (smoothstep((a)-0.5*(fuzz),(a)+0.5*(fuzz),(x)) - \ smoothstep((b)-0.5*(fuzz),(b)+0.5*(fuzz),(x))) */ surface tracksurface( float hfreq = 1, vfreq = 1; float rail_width = 0.02; color rail_color = color "hsv" (0.6805, 0.197, 0.697); float rail_Ka = 1, rail_Kd = 0.2, rail_Ks = 1, rail_roughness = 0.25; color tie_lightcolor = color "hsv" (0.075, 1.0, 0.348), tie_darkcolor = color "hsv" (0.0916, 1.0, 0.136); float tie_Ka = 0.2, tie_Kd = 0.4, tie_Ks = 0.6, tie_roughness = 0.1; float Ka = 1, Kd = 0.5) { point Nf, V; point PP; /* used by wood */ float y, z; /* used by wood */ color surface_color, layer0_color, layer1_color, layer2_color; float surface_opac, layer0_opac, layer1_opac, layer2_opac; float fuzz = 0.01; float ss, tt, freq; float row, col; float r, theta; float angle; float d, d0, d1; float straight = 0, curved = 0; float rail, ties; ss = repeat(s, hfreq); tt = repeat(t, vfreq); col = whichtile(s, hfreq); row = whichtile(t, vfreq); if (snoise2(row + 0.05, col + 0.05) > 0.0) straight = 1; else if (snoise2(row * 3 + 0.05, col * 7 + 0.05) > 0.0) curved = 1; /* railroad ties layer */ if (straight == 1) { /* straight ties */ d0 = intersection(pulse(0.33, 0.67, fuzz, ss), pulse(0.33, 0.67, fuzz, tt)); if (abs(0.5 - ss) > 0.2) { d1 = mod(abs(0.5 - ss) * 100.0 + 5.0, 10.0); d1 = intersection(complement(pulse(2.0 + 0.5 * fuzz, 8.0 - 0.5 * fuzz, fuzz, d1)), pulse(0.33 - 0.5 * fuzz, 0.67 + 0.5 * fuzz, fuzz, tt)); d0 = union(d0, d1); } if (abs(0.5 - tt) > 0.2) { d1 = mod(abs(0.5 - tt) * 100.0 + 5.0, 10.0); d1 = intersection(complement(pulse(2.0 + 0.5 * fuzz, 8.0 - 0.5 * fuzz, fuzz, d1)), pulse(0.33 - 0.5 * fuzz, 0.67 + 0.5 * fuzz, fuzz, ss)); d0 = union(d0, d1); } ties = d0; } else { if (curved == 1) { /* curved ties NW SE */ d0 = distance((0, 0, 0), (ss, tt, 0)); d1 = distance((1.0 - fuzz, 1.0 - fuzz, 0), (ss, tt, 0)); if (d0 <= d1) { d = d0; topolar2d(ss, tt, r, theta); } else { d = d1; topolar2d(1.0 - fuzz - ss, 1.0 - fuzz - tt, r, theta); } } else { /* curved ties NE SW */ d0 = distance((0, 1.0 - fuzz, 0), (ss, tt, 0)); d1 = distance((1.0 - fuzz, 0, 0), (ss, tt, 0)); if (d0 <= d1) { d = d0; topolar2d(ss, 1.0 - fuzz - tt, r, theta); } else { d = d1; topolar2d(1.0 - fuzz - ss, tt, r, theta); } } angle = mod(degrees(theta) + 365.0, 10.0); ties = intersection(complement(pulse(2.0 + 0.5 * fuzz, 8.0 - 0.5 * fuzz, fuzz, angle)), pulse(0.33 - 0.5 * fuzz, 0.67 + 0.5 * fuzz, fuzz, d)); } /* rail layer */ if (straight == 1) { /* straight rails */ d0 = union(pulse(0.4 - rail_width, 0.4 + rail_width, fuzz, ss), pulse(0.6 - rail_width, 0.6 + rail_width, fuzz, ss)); d1 = union(pulse(0.4 - rail_width, 0.4 + rail_width, fuzz, tt), pulse(0.6 - rail_width, 0.6 + rail_width, fuzz, tt)); rail = union(d0, d1); } else { /* curved rails */ if (curved == 1) { d0 = distance((0, 0, 0), (ss, tt, 0)); d1 = distance((1.0 - fuzz, 1.0 - fuzz, 0), (ss, tt, 0)); } else { d0 = distance((0, 1.0 - fuzz, 0), (ss, tt, 0)); d1 = distance((1.0 - fuzz, 0, 0), (ss, tt, 0)); } d = min(d0, d1); rail = union(pulse(0.4 - rail_width, 0.4 + rail_width, fuzz, d), pulse(0.6 - rail_width, 0.6 + rail_width, fuzz, d)); } /* illumination */ Nf = faceforward(normalize(N), I); V = normalize(-I); /* illumination for straight or curved railroad ties */ PP = P; if (straight == 1) { setxcomp(PP, xcomp(PP) + ss); setzcomp(PP, zcomp(PP) + tt); } else { setxcomp(PP, r); setycomp(PP, abs(5.0 - angle)); } PP = transform("shader", PP); PP += noise(PP); y = ycomp(PP); z = zcomp(PP); r = sqrt(y*y + z*z); r *= 10; r += abs(noise(r)); r -= floor(r); r = smoothstep(0, 0.8, r) - smoothstep(0.83, 1.0, r); layer0_color = mix(tie_lightcolor, tie_darkcolor, r); layer0_opac = ties; layer0_color = ties * layer0_color * (tie_Ka * ambient() + tie_Kd * diffuse(Nf)) + (0.3 * r + 0.7) * tie_Ks * specular(Nf, V, tie_roughness); /* illumination for rails (based upon metal(), Renderman Companion, p. 336) */ layer1_opac = rail; layer1_color = rail * rail_color * (rail_Ka * ambient() + rail_Kd * diffuse(Nf) + rail_Ks * specular(Nf, -I, rail_roughness)); /*** background layer ***/ surface_opac = max(1.0, union(layer0_opac, layer1_opac)); surface_color = Os * Cs * (Ka * ambient() + Kd * diffuse(Nf)); surface_color = blend(surface_color, layer0_color, layer0_opac); surface_color = blend(surface_color, layer1_color, layer1_opac); /* output */ Oi = surface_opac; Ci = surface_opac * surface_color; }