/* S. Kirk Bowers */ /* Generic stained glass surface (and displacement) shader */ /* The pattern is simply a grid, actually just a tiled solid color. For each of the tiles, the color is chosen stochastically. For the borders of each of the tiles, the corners are bombed, that is moved up to max_offset away in both the s and t direction from their normal position. The shader considers all of the adjascent tiles, since both the borders and the panes can be moved outside the boundaries of the tile. For now the displacement portion of the shader is disabled. I have yet to be successful getting color transitions to line up with displacement transitions. I wanted to have the iron cross bars raised off the surface of the glass, but it did not look right. There is a corresponding light source shader, stained_glass_light */ /* 5-4-96 */ #include surface stained_glass ( /* Illumination params */ float Ka = 0.5, Kd = 0.5, Ks = 1.0, roughness = 0.1, intensity = 1; /* should match light source shader's */ color specularcolor = 1; /* Tiling info */ float sfreq = 3, tfreq = 3, glass_opac = 0.5, fuzz = 0.01, max_offset = 0.45; /* Divider displacement */ float Km = 0.0, 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 Nf, V; point p1, p2, sstt; ss = repeat(s, sfreq); tt = repeat(t, tfreq); col = whichtile(s, sfreq); row = whichtile(t, tfreq); surface_color = 0; on_border = 0; 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); } } /* Initialize vectors for plastic illumination */ Nf = faceforward(normalize(N), I); V = normalize(-I); surface_color = blend(surface_color, 0.1, on_border); /* P += Km * on_border * Nf; N = calculatenormal(P); */ /*----------------------- Illumination ---------------------------*/ Oi = blend(glass_opac, 1, on_border); Ci = Os * (surface_color * (Ka * ambient() + intensity)); }