/* surface shader: brick_shiny_building creator: Nick Meshes, DePaul University description: Based on loosely screen.sl and shiny.sl Makes a surface that looks like an office building with reflective windows. Walls look plastic-like though. parameters: Ka, Kd, Ks, roughness, specularcolor - work just like the plastic shader wallcolor and windowcolor window width and height set parts between windows set as well. up - x=0, y=1, z=2, building is square in this algorithm widthoffset will be between 0 and (windowwidth + wallwidth) heightoffset will be between 0 and (windowheight + wallheight) ceiling - top where no more windows exist floor - bottom where no more windows exist */ #include "rayserver.h" #include "raytrace.h" #include "noises.h" #include "patterns.h" surface brick_shiny_building (float Ka = .8, Kd = 0.75, Ks = 0.2, roughness = 0.2; color specularcolor = 1; color wallcolor = Cs; color windowcolor = color(1, .75, 0); float up = 2; float ceiling = 100, floor = -100; float windowwidth = 1, wallwidth = 1; float windowheight = 1, wallheight = 1; float widthoffset = 0, heightoffset = 0; float Kr = 0.5, blur = 0; /* brick features */ float samples = 1; color brickcolor = color "rgb" (.6,.1,.1); color mortarcolor = color "rgb" (.6,.6,.6); float raggedamp = 0.04, raggedfreq = 12; float jagged = 0.006, brickvary = 0.3; float brickwidth = .28, brickheight = .07; float mortarthickness = .014; float rowvary = .5; float pitting = 0.01; float pockfrequency = 10, groovedepth = 0.01; ) { normal Nf = faceforward(normalize(N),I); vector IN = normalize(I);; float xpart, ypart, zpart; float sum = 0; color ev = 0; if (up == 0){ xpart = abs(ycomp(P)); ypart = abs(zcomp(P)); zpart = abs(zcomp(P)); } else if (up == 1){ xpart = abs(zcomp(P)); ypart = abs(xcomp(P)); zpart = abs(ycomp(P)); } else{ xpart = abs(xcomp(P)); ypart = abs(ycomp(P)); zpart = abs(zcomp(P)); } Cs = wallcolor; xpart = mod((xpart + widthoffset), (windowwidth + wallwidth)); ypart = mod((ypart + widthoffset), (windowwidth + wallwidth)); zpart = mod((zpart + heightoffset), (windowheight + wallheight)); if (zpart <= floor) sum = 1; if (zpart >= ceiling) sum = 1; if (xpart > (wallwidth/2)) if (xpart < (windowwidth + (wallwidth/2))) sum = sum + 1; if (ypart > (wallwidth/2)) if (ypart < (windowwidth + (wallwidth/2))) sum = sum + 1; if (zpart > (wallheight/2)) if (zpart < (windowheight + (wallheight/2))) sum = sum + 1; if (sum == 0){ if (Kr > 0.001) { vector Rdir = normalize (reflect (IN, Nf)); ev = Kr * RayTrace (P, Rdir, blur, 1, samples); Cs = windowcolor; } }else{ /* * * inwallspace * */ #define sqr(x) ((x)*(x)) color bcolor, Ct; normal Nf; float sbrick, tbrick, w, h; float ss, tt; float swidth, twidth; uniform float BMWIDTH = (brickwidth+mortarthickness); uniform float BMHEIGHT = (brickheight+mortarthickness); uniform float MWF = (mortarthickness*0.5/BMWIDTH); uniform float MHF = (mortarthickness*0.5/BMHEIGHT); float whichbrick; float fact, disp; /* Determine how wide in s-t space one pixel projects to, relative * the the width and height of a brick. Overestimate the filter * size by a bit -- it makes the transitions between brick and mortar * a bit smoother. */ swidth = 1.5 * max (filterwidth(s), MINFILTWIDTH) / BMWIDTH; twidth = 1.5 * max (filterwidth(t), MINFILTWIDTH) / BMHEIGHT; basictile (s, t, BMWIDTH, BMHEIGHT, 0.5, 0.2, 1, jagged, sbrick, tbrick, ss, tt); /* Make the edges ragged, but different for each brick */ whichbrick = 103*sbrick + tbrick; ss += raggedamp * snoisexy ((s+tbrick*5.15)*raggedfreq, (t+sbrick*23.8)*raggedfreq); tt += raggedamp * snoisexy ((s+tbrick*11.4)*raggedfreq, (t+sbrick*7.2)*raggedfreq); ss += raggedamp/2 * snoisexy ((s+tbrick*5.15)*raggedfreq*2, (t+sbrick*23.8)*raggedfreq*2); tt += raggedamp/2 * snoisexy ((s+tbrick*11.4)*raggedfreq*2, (t+sbrick*7.2)*raggedfreq*2); /* Choose a color for the surface */ if (swidth >= 1) w = 1 - 2*MWF; else w = clamp (filteredpulse (MWF, 1-MWF, ss, swidth), max(1-MWF/swidth,0), 1); if (twidth >= 1) h = 1 - 2*MHF; else h = clamp (filteredpulse (MHF, 1-MHF, tt, twidth), max(1-MHF/twidth,0), 1); fact = 1; disp = 0; if (tt < MHF) { /* We're in the top horizontal groove */ disp = groovedepth * (sqr((tt)/MHF) - 1); } else if (tt > (1.0-MHF)) { /* Bottom horizontal groove */ disp = groovedepth * (sqr((1-tt)/MHF) - 1); } if (ss < MWF) { disp = min (disp, 0.85 * groovedepth * (sqr(ss/MWF) - 1)); } else if (ss > (1.0-MWF)) { disp = min (disp, 0.85 * groovedepth * (sqr((1-ss)/MWF) - 1)); } fact = smoothstep (0, 1.3*MHF, tt) - smoothstep (1.0-1.3*MHF, 1, tt); fact *= (smoothstep (0, 1.3*MWF, ss) - smoothstep (1.0-1.3*MWF, 1, ss)); fact = pitting * (0.5 * fact + 0.5); disp -= fact * pow(noise ((ss+sbrick)*pockfrequency/BMHEIGHT, (tt+tbrick)*pockfrequency/BMWIDTH), 0.25); P += disp * normalize(N); N = calculatenormal (P); Nf = faceforward (normalize(N),I); /* Choose a brick color that varies from brick to brick */ bcolor = brickcolor * (1 + (brickvary * snoise (whichbrick+0.5))); Cs = mix (mortarcolor, bcolor, w*h); } Ci = Cs * (Ka*ambient() + Kd*diffuse(Nf)) + specularcolor * (ev + Ks*specular(Nf,-IN,roughness)); Oi = Os; Ci *= Oi; }