/* S. Kirk Bowers */ /* Generic stained glass light source shader */ /* This just basically the stained_glass surface shader copied with a solar statement wrapped around it to make it a light source shader. The trick with the dot products is taken from the window light source in the Upstill book, but modified slightly to suit my purposes. */ /* 5-4-96 */ #include light stained_glass_light ( /* Positional info */ point top_left = point "world" (-1, 1, 0), bot_left = point "world" (-1, -1, 0), top_right = point "world" (1, 1, 0), from = point "world" (1, 1, -1), to = point "world" (0, 0, 0); float intensity = 3, ambient_falloff_rate = 5; color darkcolor = color (0.07, 0.02, 0.075), outsidecolor = 1; /* Tiling info */ float sfreq = 3, tfreq = 3, fuzz = 0.01, max_offset = 0.45; /* Divider displacement */ float divider_width = 0.1; ) { float ss, tt; float row, col; float x, y; float layer_opac, pane_color, on_border; color layer_color, surface_color; float topleft_s, topleft_t, topright_s, topright_t; float botleft_s, botleft_t, botright_s, botright_t; float thisline; point p1, p2, sstt; point down, in, right; point PtoC, PtoF, path; float down_dist, right_dist; float toff, soff; float ambient_falloff, this_falloff; float outside; path = (from - to); down = bot_left - top_left; down_dist = length(down); down = normalize(down); right = top_right - top_left; right_dist = length(right); right = normalize(right); in = normalize(right ^ down); solar(-path, 0.0) { PtoC = top_left - Ps; /* The Upstill window shader floods the outside with light. I copied this effect at first, but noticed that it suffers from aliasing if the window is in the scene. A crack forms between the window and the floor through which light leaks in. So for now it is disabled because I have no real use for it. Perhaps I will add a smoothstep to it some day... */ outside = complement(smoothstep(- fuzz, 0, in . PtoC)); { PtoF = path * (PtoC . in) / (path . in); toff = ((PtoF - PtoC) . down) / down_dist; soff = ((PtoF - PtoC) . right) / right_dist; ss = repeat(soff, sfreq); tt = repeat(toff, tfreq); col = whichtile(soff, sfreq); row = whichtile(toff, tfreq); surface_color = darkcolor; on_border = 0; ambient_falloff = 1; if (soff >= 0 && soff <= 1 && toff >=0 && toff <= 1) { for(x = -1; x <= 1; x += 1) { for (y = -1; y <= 1; y += 1) { layer_opac = 1; pane_color = udn(sfreq * (x + col) + y + row + 0.75, 0, 4); if (pane_color < 1) layer_color = color (1, 0, 0); else if (pane_color < 2) layer_color = color (0, 1, 0); else if (pane_color < 3) layer_color = color (0, 0, 1); else layer_color = color (1, 1, 0); if (col + x > 0 && col + x < sfreq) topleft_s = udn2(col + x - 0.5 + sfreq, row + y - 0.5, -max_offset, max_offset) + x; else topleft_s = x; if (row + y > 0 && row + y < tfreq) topleft_t = udn2(col + x - 0.5, row + y - 0.5 + tfreq, -max_offset, max_offset) + y; else topleft_t = y; if (col + x + 1 > 0 && col + x + 1 < sfreq) topright_s = udn2(col + x + 0.5 + sfreq, row + y - 0.5, -max_offset, max_offset) + x + 1; else topright_s = x + 1; if (row + y > 0 && row + y < tfreq) topright_t = udn2(col + x + 0.5, row + y - 0.5 + tfreq, -max_offset, max_offset) + y; else topright_t = y; if (col + x > 0 && col + x < sfreq) botleft_s = udn2(col + x - 0.5 + sfreq, row + y + 0.5, -max_offset, max_offset) + x; else botleft_s = x; if (row + y + 1 > 0 && row + y + 1 < tfreq) botleft_t = udn2(col + x - 0.5, row + y + 0.5 + tfreq, -max_offset, max_offset) + y + 1; else botleft_t = y + 1; if (col + x + 1 > 0 && col + x + 1 < sfreq) botright_s = udn2(col + x + 0.5 + sfreq, row + y + 0.5, -max_offset, max_offset) + x + 1; else botright_s = x + 1; if (row + y + 1 > 0 && row + y + 1 < tfreq) botright_t = udn2(col + x + 0.5, row + y + 0.5 + tfreq, -max_offset, max_offset) + y + 1; else botright_t = y + 1; sstt = point (ss, tt, 0); thisline = (tt - botleft_t) * (topleft_s - botleft_s) / (topleft_t - botleft_t) + botleft_s; layer_opac = intersection(layer_opac, smoothstep(thisline, thisline + fuzz, ss)); p1 = point (botleft_s, botleft_t, 0); p2 = point (topleft_s, topleft_t, 0); on_border = union(on_border, complement(smoothstep(divider_width, divider_width + fuzz, ptlined(p1, p2, sstt)))); thisline = (ss - topleft_s) * (topright_t - topleft_t) / (topright_s - topleft_s) + topleft_t; layer_opac = intersection(layer_opac, smoothstep(thisline, thisline + fuzz, tt)); p1 = point (topleft_s, topleft_t, 0); p2 = point (topright_s, topright_t, 0); on_border = union(on_border, complement(smoothstep(divider_width, divider_width + fuzz, ptlined(p1, p2, sstt)))); thisline = (tt - botright_t) * (topright_s - botright_s) / (topright_t - botright_t) + botright_s; layer_opac = intersection(layer_opac, complement(smoothstep(thisline, thisline + fuzz, ss))); p1 = point (botright_s, botright_t, 0); p2 = point (topright_s, topright_t, 0); on_border = union(on_border, complement(smoothstep(divider_width - fuzz, divider_width, ptlined(p1, p2, sstt)))); thisline = (ss - botleft_s) * (botright_t - botleft_t) / (botright_s - botleft_s) + botleft_t; layer_opac = intersection(layer_opac, complement(smoothstep(thisline, thisline + fuzz, tt))); p1 = point (botleft_s, botleft_t, 0); p2 = point (botright_s, botright_t, 0); on_border = union(on_border, complement(smoothstep(divider_width - fuzz, divider_width, ptlined(p1, p2, sstt)))); surface_color = blend(surface_color, layer_color, layer_opac); } } surface_color = surface_color / (PtoF . PtoF + 1); } /* If within the window */ else { if (s < 0 || s > 1) { this_falloff = (abs(s - 0.5) - 0.5) * ambient_falloff_rate; ambient_falloff += this_falloff * this_falloff; } if (t < 0 || t > 1) { this_falloff = (abs(t - 0.5) - 0.5) * 3; ambient_falloff += this_falloff * ambient_falloff_rate; } } } /* solar */ } /* If not outside */ /* Start off surface color with ambient from window with fall off depending on distance from window */ layer_color = darkcolor / ambient_falloff; /* Take into account the border cross bars */ surface_color = blend(surface_color, 0, on_border) + layer_color; /* Set the outgoing color */ /* printf("PtoC . PtoC = %d\n", PtoC . PtoC); */ Cl = intensity * surface_color; }