/* S. Kirk Bowers */ /* Patriotic surface shader with plastic illumination. */ /* This really isn't a political statement. I wanted to stop with stars and stripes, but a third level is required. So for lack of any better idea, the third level is dollar signs. Someone else suggested it to me! Don't blame me! There are three layers to this shader. - Wavy stripes are placed on top of the original surface color. This effect is accomplished with a sine function skewed in the s direction (see skew_x definition below). - Stars are added. The stars are not generated with polar coordinates as some other people have done it in the past. Instead they are made with purely smoothstep, rotate2d, and boolean operations. The only drawback is that the inner convex angles accumulate a lot of fuzz. If the star is large enough, the fuzz can be noticeable. - Dollar signs are added. They are made of two rings that are cut with boolean difference functions, and two lines. The two rings did not quite line up, so there is a little artificial tweak to make sure they do. */ /* Last modified 4-15-96 */ #include #define skew_x(x, y, angle) (x + y * angle) surface patriotic ( /*======= Illumination parameters =========*/ color specularcolor = 1; float Ka = 0.5, Kd = 0.5, Ks = 1.0, roughness = 0.1, fuzz = 0.02; /*=========== stripe parameters ===========*/ float wave_angle = 1.5, wave_sfreq = 7, wave_tfreq = 3; color stripe_color = color (1, 0, 0); /*=========== Star parameters =============*/ float star_width = 0.15, /* distance from center to inner points */ star_sfreq = 8, star_tfreq = 7, num_points = 5, /* number of outer points, do 6 for David's */ star_opac = 0.3; color star_color = color (0, 0, 1); string star_pattern = "staggered"; /* Only one choice has an effect: "staggered" shifts every other row. Any other choice is regular tiling */ /*=========== dollar parameters ===========*/ float dollar_sfreq = 5, dollar_tfreq = 3, dollar_opac = 0.5; color dollar_color = color (0, 1, 0); ) { float ss, tt, sss, ttt; color surface_color, layer_color; float layer_opac; point Nf, V; float row, col; float this_opac, this_star_point; float x, y; float wave_start; float ring, cut, dollar_thick, radius, d, just_off; point p1, p2, center; /*----------------------- layer 0 -----------------------*/ surface_color = Cs; /* Background color is object color */ /*----------------------- layer 1 -----------------------*/ /* Creation of wavy stripes. This is done by skewing a sine wave */ layer_color = stripe_color; ss = skew_x(s, t, wave_angle); ss = repeat(ss, wave_sfreq); tt = repeat(t, wave_tfreq); wave_start = sin(tt * radians(360)) * 0.20; layer_opac = pulse(0.25 - wave_start, 0.75 - wave_start, fuzz, ss); surface_color = mix(surface_color, layer_color, layer_opac); /*----------------------- Layer 2 -----------------------*/ /* Add the stars */ sss = repeat(s, star_sfreq); ttt = repeat(t, star_tfreq); row = whichtile(t, star_tfreq); if (odd(row) && star_pattern == "staggered") sss = mod(sss + 0.5, 1.0); layer_color = star_color; layer_opac = 1; /* First make the inner shape. For 5 point star, this is a pentagon */ for (x = 0; x < num_points; x = x + 1) { rotate2d(sss, ttt, radians(x * (360 / num_points)), 0.5, 0.5, ss, tt); this_opac = smoothstep(0.5 - star_width, 0.5 - star_width + fuzz, tt); layer_opac = intersection(layer_opac, this_opac); } /* Next make each of the points, basically tack on triangles to the inner shape. */ for (x = 0; x < num_points; x = x + 1) { this_star_point = 1; for (y = x - 1; y < x + 2; y += 1) { rotate2d(sss, ttt, radians(y * (360 / num_points)), 0.5, 0.5, ss, tt); this_opac = smoothstep(0.5 - star_width + fuzz, 0.5 - star_width + fuzz, tt); if (y == x) this_opac = complement(this_opac); this_star_point = intersection(this_star_point, this_opac); } layer_opac = union(layer_opac, this_star_point); } layer_opac = layer_opac * star_opac; surface_color = mix(surface_color, layer_color, layer_opac); /*----------------------- layer 3 -----------------------*/ /* Dollar signs */ /* For some reason the rings did not quite line up */ /* just_off is a little tweak to get the rings in the right place. */ just_off = 0.01; layer_color = dollar_color; ss = repeat(s, dollar_sfreq); tt = repeat(t, dollar_tfreq); dollar_thick = 0.05; radius = 0.2; center = (0.5 + just_off, 0.3 + just_off, 0); d = distance(center, (ss, tt, 0)); ring = pulse(radius - dollar_thick, radius + dollar_thick, fuzz, d); cut = intersection( smoothstep(xcomp(center) - fuzz / 2, xcomp(center) + fuzz / 2, ss), smoothstep(ycomp(center) - fuzz / 2, ycomp(center) + fuzz / 2, tt)); layer_opac = difference(ring, cut); surface_color = mix(surface_color, layer_color, layer_opac * dollar_opac); center = (0.5 - just_off, 0.7 - just_off, 0); d = distance(center, (ss, tt, 0)); ring = pulse(radius - dollar_thick, radius + dollar_thick, fuzz, d); cut = intersection( complement( smoothstep(xcomp(center) - fuzz / 2, xcomp(center) + fuzz / 2, ss)), complement( smoothstep(ycomp(center) - fuzz / 2, ycomp(center) + fuzz / 2, tt))); layer_opac = difference(ring, cut); surface_color = mix(surface_color, layer_color, layer_opac * dollar_opac); p1 = (0.43, 0.05, 0); p2 = (0.43, 0.95, 0); d = ptlined(p1, p2, (ss, tt, 0)); layer_opac = 1 - smoothstep(dollar_thick - fuzz, dollar_thick, d); surface_color = mix(surface_color, layer_color, layer_opac * dollar_opac); p1 = (0.57, 0.05, 0); p2 = (0.57, 0.95, 0); d = ptlined(p1, p2, (ss, tt, 0)); layer_opac = 1 - smoothstep(dollar_thick - fuzz, dollar_thick, d); surface_color = mix(surface_color, layer_color, layer_opac * dollar_opac); /*----------------------- Illumination ---------------------------*/ /* Initialize vectors for plastic illumination */ Nf = faceforward(normalize(N), I); V = normalize(-I); Oi = Os; Ci = Os * (surface_color * (Ka * ambient() + Kd * diffuse(Nf)) + specularcolor * Ks * specular(Nf, V, roughness)); }