dopairb 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +41 -9
- data/lib/dopairb/cli.rb +4 -6
- data/lib/dopairb/config.rb +6 -4
- data/lib/dopairb/demo.rb +9 -2
- data/lib/dopairb/director.rb +35 -5
- data/lib/dopairb/fx.rb +23 -0
- data/lib/dopairb/gallery/impressionism.rb +818 -0
- data/lib/dopairb/gallery/japan.rb +693 -0
- data/lib/dopairb/gallery/modern_ancient.rb +774 -0
- data/lib/dopairb/gallery/renaissance.rb +829 -0
- data/lib/dopairb/gallery/romantic.rb +703 -0
- data/lib/dopairb/gallery.rb +349 -0
- data/lib/dopairb/game.rb +84 -7
- data/lib/dopairb/input_fx.rb +63 -9
- data/lib/dopairb/irb_adapter.rb +8 -0
- data/lib/dopairb/profile.rb +106 -0
- data/lib/dopairb/reline_adapter.rb +1 -0
- data/lib/dopairb/scene.rb +5 -0
- data/lib/dopairb/scenes/bonus.rb +279 -0
- data/lib/dopairb/scenes/failure.rb +1 -0
- data/lib/dopairb/scenes/finale.rb +42 -2
- data/lib/dopairb/scenes/session.rb +21 -3
- data/lib/dopairb/scenes/success.rb +11 -4
- data/lib/dopairb/session.rb +50 -6
- data/lib/dopairb/sound.rb +57 -2
- data/lib/dopairb/term.rb +3 -1
- data/lib/dopairb/tour.rb +89 -0
- data/lib/dopairb/version.rb +1 -1
- data/lib/dopairb.rb +57 -1
- data/spec.md +3 -3
- metadata +10 -1
|
@@ -0,0 +1,829 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dopairb
|
|
4
|
+
module Gallery
|
|
5
|
+
# Renaissance and Golden Age painters (helpers and painters use an rn_ prefix).
|
|
6
|
+
module Paint
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
# Distance from (u, v) to the segment (x1, y1)-(x2, y2); sx scales the u axis.
|
|
10
|
+
def rn_seg(u, v, x1, y1, x2, y2, sx = 1.0)
|
|
11
|
+
dx = (x2 - x1) * sx
|
|
12
|
+
dy = y2 - y1
|
|
13
|
+
px = (u - x1) * sx
|
|
14
|
+
py = v - y1
|
|
15
|
+
t = ((px * dx + py * dy) / (dx * dx + dy * dy + 1e-12)).clamp(0.0, 1.0)
|
|
16
|
+
Math.hypot(px - dx * t, py - dy * t)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# A simple standing (or seated) figure: :head, :body or nil.
|
|
20
|
+
# x: center u, top: v of the top of the head, h: height and w: width in v units,
|
|
21
|
+
# sx: the picture's aspect so heads stay round.
|
|
22
|
+
def rn_fig(u, v, x, top, h, w, sx)
|
|
23
|
+
hr = h * 0.08
|
|
24
|
+
return :head if (((u - x) * sx) / (hr * 0.85))**2 + ((v - top - hr) / hr)**2 < 1
|
|
25
|
+
t = (v - top - hr * 1.8) / (h - hr * 1.8)
|
|
26
|
+
return nil if t < 0 || t > 1
|
|
27
|
+
(u - x).abs * sx < w * 0.5 * (0.7 + 0.5 * t) ? :body : nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Botticelli, The Birth of Venus
|
|
31
|
+
def rn_birth_of_venus(u, v)
|
|
32
|
+
a = 1.58
|
|
33
|
+
skin = [238, 214, 190]
|
|
34
|
+
hair = [196, 128, 62]
|
|
35
|
+
# orange trees at the right edge
|
|
36
|
+
edge = 0.91 + 0.015 * Math.sin(v * 11)
|
|
37
|
+
if u > edge
|
|
38
|
+
return [92, 70, 45] if (u - 0.95).abs < 0.008 && v > 0.15
|
|
39
|
+
return noise((u * 70).floor, (v * 50).floor) > 0.9 ? [210, 150, 70] : jitter([45, 72, 50], u, v, 14)
|
|
40
|
+
end
|
|
41
|
+
# the green shore under the attendant
|
|
42
|
+
return jitter([96, 120, 70], u, v, 12) if v > 0.84 - (u - 0.7) * 0.35 && u > 0.68
|
|
43
|
+
# the scallop shell
|
|
44
|
+
su = 0.5
|
|
45
|
+
sv = 0.97
|
|
46
|
+
if ellipse(u, v, su, sv, 0.17, 0.2) < 1 && v < 0.94 && v > 0.78
|
|
47
|
+
ang = Math.atan2(v - sv, (u - su) * a)
|
|
48
|
+
return [170, 130, 85] if ellipse(u, v, su, sv, 0.17, 0.2) > 0.85
|
|
49
|
+
return Math.sin(ang * 26) > 0.3 ? [200, 165, 115] : [240, 220, 178]
|
|
50
|
+
end
|
|
51
|
+
# Venus: long golden-red hair over a pale S-shaped figure
|
|
52
|
+
return mix(hair, [150, 85, 40], 0.2) if ellipse(u, v, 0.5, 0.115, 0.03, 0.055) < 1 && v < 0.11
|
|
53
|
+
return skin if ellipse(u, v, 0.5, 0.135, 0.022, 0.05) < 1
|
|
54
|
+
# the long hair: down her left side and drawn across the hips, a few strands blowing right
|
|
55
|
+
lock = 0.47 - 0.012 * Math.sin(v * 14)
|
|
56
|
+
hair_px = (v > 0.1 && v < 0.6 && (u - lock).abs < 0.016 + (v - 0.1) * 0.03) ||
|
|
57
|
+
rn_seg(u, v, 0.465, 0.55, 0.505, 0.63, a) < 0.035 ||
|
|
58
|
+
rn_seg(u, v, 0.52, 0.1, 0.565, 0.24, a) < 0.016 || rn_seg(u, v, 0.53, 0.14, 0.555, 0.32, a) < 0.012
|
|
59
|
+
return Math.sin(v * 70 + u * 40) > 0.5 ? [228, 170, 92] : hair if hair_px
|
|
60
|
+
body = [[0.482, 0.18], [0.52, 0.18], [0.538, 0.3], [0.532, 0.46], [0.522, 0.6], [0.518, 0.8], [0.488, 0.8], [0.48, 0.6], [0.47, 0.46], [0.472, 0.3]]
|
|
61
|
+
return mix(skin, [205, 170, 140], smooth(0.49, 0.54, u)) if inside?(u, v, body)
|
|
62
|
+
# the attendant (Hora) with the pink cloak held out toward Venus
|
|
63
|
+
fig = rn_fig(u, v, 0.77, 0.16, 0.66, 0.11, a)
|
|
64
|
+
return [232, 200, 170] if fig == :head
|
|
65
|
+
cloak = [[0.735, 0.28], [0.65, 0.3], [0.6, 0.42], [0.61, 0.66], [0.64, 0.76], [0.71, 0.64], [0.74, 0.45]]
|
|
66
|
+
if inside?(u, v, cloak)
|
|
67
|
+
return noise((u * 60).floor, (v * 40).floor) > 0.88 ? [180, 60, 60] : jitter([230, 160, 160], u, v, 14)
|
|
68
|
+
end
|
|
69
|
+
if fig == :body
|
|
70
|
+
return noise((u * 70).floor, (v * 50).floor) > 0.85 ? [80, 110, 170] : jitter([236, 232, 214], u, v, 10)
|
|
71
|
+
end
|
|
72
|
+
# the winds flying in from the left
|
|
73
|
+
return [100, 140, 125] if rn_seg(u, v, 0.03, 0.15, 0.27, 0.27, a) < 0.07 # Zephyr's blue-green cloak
|
|
74
|
+
return skin if rn_seg(u, v, 0.05, 0.3, 0.27, 0.33, a) < 0.045 # Aura
|
|
75
|
+
return [232, 205, 180] if dist(u, v, 0.29, 0.27, a) < 0.04
|
|
76
|
+
return [215, 195, 170] if dist(u, v, 0.29, 0.34, a) < 0.035
|
|
77
|
+
return [120, 160, 140] if rn_seg(u, v, 0.08, 0.38, 0.22, 0.42, a) < 0.03 # trailing drapery
|
|
78
|
+
# falling roses
|
|
79
|
+
return [235, 150, 160] if u > 0.18 && u < 0.42 && v < 0.6 && noise((u * 50).floor, (v * 35).floor) > 0.94
|
|
80
|
+
horizon = 0.46
|
|
81
|
+
if v > horizon
|
|
82
|
+
chevron = Math.sin(v * 110 + Math.sin(u * 70).abs * 5)
|
|
83
|
+
sea = mix([150, 185, 170], [110, 150, 140], (v - horizon) / 0.5)
|
|
84
|
+
return chevron > 0.85 ? mix(sea, [240, 245, 235], 0.6) : sea
|
|
85
|
+
end
|
|
86
|
+
jitter(mix([150, 180, 175], [205, 218, 205], v / horizon), u, v, 8)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Botticelli, Primavera
|
|
90
|
+
def rn_primavera(u, v)
|
|
91
|
+
a = 1.55
|
|
92
|
+
# the figures, left to right: [u, top, height, width, gown color]
|
|
93
|
+
figs = [
|
|
94
|
+
[0.08, 0.17, 0.74, 0.12, [176, 40, 30]], # Mercury
|
|
95
|
+
[0.18, 0.18, 0.72, 0.1, [236, 232, 222]], # the three Graces
|
|
96
|
+
[0.245, 0.17, 0.73, 0.1, [228, 224, 214]],
|
|
97
|
+
[0.31, 0.19, 0.71, 0.1, [236, 230, 218]],
|
|
98
|
+
[0.5, 0.25, 0.64, 0.12, [190, 50, 40]], # Venus, red mantle
|
|
99
|
+
[0.655, 0.2, 0.7, 0.13, [240, 236, 222]], # Flora
|
|
100
|
+
[0.775, 0.19, 0.71, 0.1, [222, 222, 210]], # Chloris
|
|
101
|
+
[0.9, 0.08, 0.7, 0.12, [80, 115, 120]] # Zephyr
|
|
102
|
+
]
|
|
103
|
+
# Cupid hovering above Venus
|
|
104
|
+
return [200, 90, 70] if dist(u, v, 0.5, 0.11, a) < 0.035
|
|
105
|
+
return [230, 200, 170] if dist(u, v, 0.5, 0.07, a) < 0.022
|
|
106
|
+
figs.each_with_index do |(fx, ft, fh, fw, col), i|
|
|
107
|
+
fx2 = fx + (i == 7 ? (v - ft) * -0.12 : 0) # Zephyr leans in
|
|
108
|
+
part = rn_fig(u, v, fx2, ft, fh, fw, a)
|
|
109
|
+
next unless part
|
|
110
|
+
return [234, 208, 180] if part == :head
|
|
111
|
+
if i == 4 # Venus: white gown under the red mantle
|
|
112
|
+
return (u - 0.5).abs < 0.012 && v > 0.36 ? [236, 228, 214] : jitter(col, u, v, 12)
|
|
113
|
+
end
|
|
114
|
+
if i == 5 && noise((u * 70).floor + 7, (v * 50).floor) > 0.72 # Flora's flowered dress
|
|
115
|
+
return [[220, 70, 80], [90, 140, 200], [230, 200, 80]][(noise((u * 90).floor, (v * 60).floor) * 3).floor % 3]
|
|
116
|
+
end
|
|
117
|
+
return mix(col, [150, 140, 125], (u - fx2).abs * a * 6) # sheer gowns, shaded at the edges
|
|
118
|
+
end
|
|
119
|
+
# the flowery meadow
|
|
120
|
+
if v > 0.84
|
|
121
|
+
n = noise((u * 90).floor, (v * 70).floor)
|
|
122
|
+
return [235, 230, 210] if n > 0.9
|
|
123
|
+
return [210, 80, 80] if n > 0.85
|
|
124
|
+
return [90, 120, 190] if n > 0.82
|
|
125
|
+
return jitter([35, 55, 35], u, v, 10)
|
|
126
|
+
end
|
|
127
|
+
# the arch of trees around Venus opening onto pale sky
|
|
128
|
+
ae = ellipse(u, v, 0.5, 0.42, 0.075, 0.36)
|
|
129
|
+
return jitter([165, 175, 160], u, v, 14) if ae < 1 && ae > 0.55
|
|
130
|
+
# the dark orange grove
|
|
131
|
+
return [55, 40, 28] if Math.sin(u * 55) > 0.93 # trunks
|
|
132
|
+
return [228, 140, 50] if v < 0.62 && noise((u * 48).floor, (v * 34).floor) > 0.88 # oranges
|
|
133
|
+
return [135, 150, 140] if v < 0.55 && vnoise(u, v, 14) > 0.74 # sky between the leaves
|
|
134
|
+
jitter([30, 44, 30], u, v, 12, 50)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Leonardo da Vinci, The Last Supper
|
|
138
|
+
def rn_last_supper(u, v)
|
|
139
|
+
a = 1.9
|
|
140
|
+
vp_u = 0.5
|
|
141
|
+
vp_v = 0.4
|
|
142
|
+
# the long table
|
|
143
|
+
if v > 0.62 && v < 0.82 && u > 0.03 && u < 0.97
|
|
144
|
+
if v < 0.67
|
|
145
|
+
return [150, 120, 80] if v < 0.645 && noise((u * 70).floor, 3) > 0.8 # bread and plates
|
|
146
|
+
return [238, 235, 225]
|
|
147
|
+
end
|
|
148
|
+
return Math.sin(u * 120) > 0.85 ? [200, 200, 195] : [222, 220, 210] # cloth hanging down
|
|
149
|
+
end
|
|
150
|
+
# thirteen figures behind the table, in groups of three around Jesus
|
|
151
|
+
if v > 0.36 && v < 0.67
|
|
152
|
+
if inside?(u, v, [[0.5, 0.39], [0.565, 0.67], [0.435, 0.67]])
|
|
153
|
+
return [70, 50, 35] if dist(u, v, 0.5, 0.44, a) < 0.04 && v < 0.43
|
|
154
|
+
return [225, 185, 150] if dist(u, v, 0.5, 0.45, a) < 0.04
|
|
155
|
+
return u > 0.5 + (v - 0.45) * 0.1 ? [45, 70, 140] : [180, 40, 35]
|
|
156
|
+
end
|
|
157
|
+
cols = [[90, 120, 80], [180, 120, 60], [70, 90, 140], [160, 60, 50], [120, 110, 100], [200, 160, 90],
|
|
158
|
+
[80, 110, 150], [150, 70, 60], [110, 130, 90], [180, 100, 70], [90, 90, 120], [170, 150, 110]]
|
|
159
|
+
[0.08, 0.145, 0.205, 0.285, 0.345, 0.405, 0.595, 0.655, 0.72, 0.795, 0.855, 0.92].each_with_index do |fx, i|
|
|
160
|
+
top = 0.4 + noise(i, 1) * 0.06
|
|
161
|
+
lean = (noise(i, 2) - 0.5) * 0.03
|
|
162
|
+
part = rn_fig(u, v, fx + lean * (0.6 - v) * 4, top - 0.02, 0.5, 0.14, a)
|
|
163
|
+
next unless part
|
|
164
|
+
return part == :head ? [215, 170, 130] : cols[i]
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
# the room in one-point perspective
|
|
168
|
+
bw_r = 0.64
|
|
169
|
+
bw_t = 0.14
|
|
170
|
+
bw_b = 0.62
|
|
171
|
+
if (u - vp_u).abs < bw_r - vp_u && v > bw_t && v < bw_b
|
|
172
|
+
# three windows on the back wall, the middle one framing Jesus
|
|
173
|
+
[[0.5, 0.045, 0.2], [0.405, 0.022, 0.25], [0.595, 0.022, 0.25]].each do |wx, hw, wt|
|
|
174
|
+
next unless (u - wx).abs < hw && v > wt && v < 0.5
|
|
175
|
+
return v < 0.38 ? mix([215, 228, 230], [180, 200, 205], v * 2) : [120, 140, 110]
|
|
176
|
+
end
|
|
177
|
+
return [150, 130, 100] if (u - 0.5).abs < 0.06 && v > 0.17 && v < 0.2 # pediment
|
|
178
|
+
return jitter([150, 135, 105], u, v, 10)
|
|
179
|
+
end
|
|
180
|
+
s = (u - vp_u).abs / (bw_r - vp_u)
|
|
181
|
+
ceil_v = vp_v + (bw_t - vp_v) * s
|
|
182
|
+
floor_v = vp_v + (bw_b - vp_v) * s
|
|
183
|
+
if v < ceil_v
|
|
184
|
+
# coffered ceiling
|
|
185
|
+
depth = 1.0 / [(vp_v - v) / (vp_v - bw_t), 1.0].max
|
|
186
|
+
across = (u - vp_u) * depth
|
|
187
|
+
return Math.sin(depth * 22) > 0.6 || Math.sin(across * 40) > 0.8 ? [90, 70, 50] : [130, 105, 75]
|
|
188
|
+
end
|
|
189
|
+
if v < floor_v
|
|
190
|
+
# side walls with dark tapestries
|
|
191
|
+
depth = 1.0 / s
|
|
192
|
+
t = (v - ceil_v) / (floor_v - ceil_v)
|
|
193
|
+
panel = [[0.3, 0.42], [0.5, 0.62], [0.7, 0.8], [0.88, 0.96]].any? { |d0, d1| depth.between?(d0, d1) }
|
|
194
|
+
return Math.sin(t * 30) > 0.5 ? [55, 40, 30] : [35, 28, 22] if panel && t > 0.1 && t < 0.75
|
|
195
|
+
return jitter([130, 115, 90], u, v, 10)
|
|
196
|
+
end
|
|
197
|
+
jitter([75, 60, 45], u, v, 10)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Leonardo da Vinci, Lady with an Ermine
|
|
201
|
+
def rn_lady_with_ermine(u, v)
|
|
202
|
+
a = 0.74
|
|
203
|
+
skin = [238, 214, 188]
|
|
204
|
+
# her long hand stroking the ermine
|
|
205
|
+
return mix(skin, [195, 160, 130], (u - 0.5) * 4) if rn_seg(u, v, 0.7, 0.8, 0.52, 0.67, a) < 0.03
|
|
206
|
+
# the ermine, white, curled diagonally in her arms with its head to the right
|
|
207
|
+
return [40, 30, 25] if dist(u, v, 0.535, 0.515, a) < 0.011 # eye
|
|
208
|
+
ermine = [[0.3, 0.95], [0.27, 0.82], [0.33, 0.68], [0.41, 0.58], [0.47, 0.51], [0.5, 0.48], [0.535, 0.49], [0.6, 0.52],
|
|
209
|
+
[0.54, 0.55], [0.51, 0.61], [0.49, 0.72], [0.45, 0.86], [0.41, 0.97]]
|
|
210
|
+
if inside?(u, v, ermine)
|
|
211
|
+
back = rn_seg(u, v, 0.3, 0.9, 0.48, 0.52, a)
|
|
212
|
+
return mix([248, 244, 232], [175, 165, 150], smooth(0.02, 0.07, back) * 0.6 + smooth(0.5, 0.9, v) * 0.3)
|
|
213
|
+
end
|
|
214
|
+
# face, turned three-quarters toward the right
|
|
215
|
+
if ellipse(u, v, 0.565, 0.3, 0.115, 0.105) < 1 && v > 0.215
|
|
216
|
+
return [30, 22, 18] if (v - 0.23).abs < 0.008 # the fine band across the forehead
|
|
217
|
+
return [70, 45, 35] if ((v - 0.29).abs < 0.012) && ((u - 0.58).abs < 0.018 || (u - 0.65).abs < 0.016) # eyes
|
|
218
|
+
return [185, 105, 95] if (v - 0.365).abs < 0.007 && (u - 0.61).abs < 0.022 # lips
|
|
219
|
+
return mix(skin, [205, 170, 140], smooth(0.56, 0.68, u) * 0.6 + smooth(0.48, 0.45, u) * 0.4)
|
|
220
|
+
end
|
|
221
|
+
# smooth dark hair drawn down along the cheeks and under the chin
|
|
222
|
+
return [50, 36, 28] if ellipse(u, v, 0.55, 0.29, 0.14, 0.125) < 1 && v < 0.41
|
|
223
|
+
# neck and the black bead necklace
|
|
224
|
+
if (u - 0.56).abs < 0.06 && v > 0.36 && v < 0.52
|
|
225
|
+
return [30, 25, 22] if (v - (0.47 + (u - 0.56)**2 * 4)).abs < 0.01 && Math.sin(u * 200) > -0.3
|
|
226
|
+
return mix(skin, [205, 170, 140], (v - 0.36) * 4)
|
|
227
|
+
end
|
|
228
|
+
# dress: square neckline, blue mantle on her right shoulder, red sleeve on the left
|
|
229
|
+
shoulders = 0.52 + (u - 0.56).abs * 0.35
|
|
230
|
+
if v > shoulders && u > 0.1
|
|
231
|
+
return mix(skin, [210, 175, 145], 0.3) if (u - 0.56).abs < 0.11 && v < 0.61 && v > 0.52
|
|
232
|
+
return [170, 140, 70] if (u - 0.56).abs < 0.13 && v < 0.64
|
|
233
|
+
return jitter([60, 80, 120], u, v, 14) if u < 0.4
|
|
234
|
+
return jitter([170, 70, 50], u, v, 16) if u > 0.64
|
|
235
|
+
return jitter([150, 110, 70], u, v, 12)
|
|
236
|
+
end
|
|
237
|
+
jitter([22, 18, 16], u, v, 6)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Leonardo da Vinci, Vitruvian Man
|
|
241
|
+
def rn_vitruvian_man(u, v)
|
|
242
|
+
a = 0.73
|
|
243
|
+
paper = mix([232, 212, 170], [210, 185, 140], vnoise(u, v, 5) * 0.8)
|
|
244
|
+
ink = [95, 65, 40]
|
|
245
|
+
lw = 0.013
|
|
246
|
+
cx = 0.5
|
|
247
|
+
cy = 0.53
|
|
248
|
+
r = 0.27
|
|
249
|
+
# circle and square
|
|
250
|
+
return ink if (dist(u, v, cx, cy, a) - r).abs < lw
|
|
251
|
+
sq_b = cy + r
|
|
252
|
+
sq_t = sq_b - 0.47
|
|
253
|
+
sq_h = 0.235 / a
|
|
254
|
+
in_sq = (u - cx).abs < sq_h + lw / a && v > sq_t - lw && v < sq_b + lw
|
|
255
|
+
return ink if in_sq && (((u - cx).abs - sq_h).abs < lw / a || (v - sq_t).abs < lw || (v - sq_b).abs < lw)
|
|
256
|
+
# the man: arms and legs in two positions
|
|
257
|
+
body = mix(paper, ink, 0.55)
|
|
258
|
+
sh_v = sq_t + 0.11
|
|
259
|
+
hip_v = cy + 0.06
|
|
260
|
+
limbs = [
|
|
261
|
+
[cx, sh_v, cx - sq_h, sh_v], [cx, sh_v, cx + sq_h, sh_v],
|
|
262
|
+
[cx, sh_v, cx - r * 0.77 / a, cy - r * 0.64], [cx, sh_v, cx + r * 0.77 / a, cy - r * 0.64],
|
|
263
|
+
[cx - 0.02, hip_v, cx - 0.04, sq_b], [cx + 0.02, hip_v, cx + 0.04, sq_b],
|
|
264
|
+
[cx, hip_v, cx - r * 0.5 / a, cy + r * 0.87], [cx, hip_v, cx + r * 0.5 / a, cy + r * 0.87]
|
|
265
|
+
]
|
|
266
|
+
dh = dist(u, v, cx, sq_t + 0.05, a)
|
|
267
|
+
return ink if dh < 0.045 && dh > 0.045 - lw * 1.5
|
|
268
|
+
return body if dh < 0.045
|
|
269
|
+
return body if rn_seg(u, v, cx, sh_v, cx, hip_v, a) < 0.045
|
|
270
|
+
return body if limbs.any? { |x1, y1, x2, y2| rn_seg(u, v, x1, y1, x2, y2, a) < 0.016 }
|
|
271
|
+
# lines of mirror-script text above and below
|
|
272
|
+
if (v > 0.05 && v < 0.2) || (v > 0.86 && v < 0.96)
|
|
273
|
+
row = v * 34
|
|
274
|
+
return mix(paper, ink, 0.45) if (row - row.floor).between?(0.3, 0.75) && u > 0.07 && u < 0.93 && noise((u * 45).floor, row.floor) > 0.3
|
|
275
|
+
end
|
|
276
|
+
paper
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Michelangelo, The Creation of Adam
|
|
280
|
+
def rn_creation_of_adam(u, v)
|
|
281
|
+
a = 2.2
|
|
282
|
+
skin = [215, 168, 120]
|
|
283
|
+
# God's hand and Adam's hand, almost touching
|
|
284
|
+
return mix(skin, [240, 210, 170], 0.3) if rn_seg(u, v, 0.515, 0.44, 0.63, 0.41, a) < 0.032
|
|
285
|
+
return skin if rn_seg(u, v, 0.3, 0.5, 0.44, 0.455, a) < 0.03 || rn_seg(u, v, 0.44, 0.455, 0.455, 0.475, a) < 0.022
|
|
286
|
+
# Adam reclining on the hill
|
|
287
|
+
return [80, 55, 35] if dist(u, v, 0.105, 0.42, a) < 0.07 && v < 0.42 + (u - 0.1) * 1.5
|
|
288
|
+
return skin if dist(u, v, 0.11, 0.44, a) < 0.07
|
|
289
|
+
adam = [
|
|
290
|
+
[0.14, 0.53, 0.26, 0.64, 0.1], # torso
|
|
291
|
+
[0.26, 0.64, 0.33, 0.52, 0.055], # raised thigh
|
|
292
|
+
[0.33, 0.52, 0.36, 0.76, 0.045], # shin
|
|
293
|
+
[0.26, 0.65, 0.44, 0.82, 0.05], # extended leg
|
|
294
|
+
[0.15, 0.52, 0.3, 0.5, 0.042], # upper arm resting on the knee
|
|
295
|
+
[0.12, 0.55, 0.07, 0.7, 0.035] # the other arm propping him up
|
|
296
|
+
]
|
|
297
|
+
adam.each do |x1, y1, x2, y2, w|
|
|
298
|
+
d = rn_seg(u, v, x1, y1, x2, y2, a)
|
|
299
|
+
return mix(skin, [150, 105, 70], d / w * 0.6 + (v - 0.5)) if d < w
|
|
300
|
+
end
|
|
301
|
+
# God borne in the red cloak with angels
|
|
302
|
+
return [240, 236, 232] if dist(u, v, 0.61, 0.35, a) < 0.075 # white hair and beard
|
|
303
|
+
return [215, 190, 200] if rn_seg(u, v, 0.64, 0.41, 0.85, 0.5, a) < 0.11 # pale robe
|
|
304
|
+
return skin if rn_seg(u, v, 0.85, 0.5, 0.96, 0.58, a) < 0.05 # legs
|
|
305
|
+
god = ellipse(u, v, 0.75, 0.43, 0.18, 0.4)
|
|
306
|
+
if god < 1 && v < 0.82
|
|
307
|
+
return [205, 85, 60] if god > 0.8
|
|
308
|
+
[[0.7, 0.18], [0.77, 0.22], [0.84, 0.28], [0.72, 0.64], [0.8, 0.68], [0.68, 0.58], [0.87, 0.62]].each do |ax, ay|
|
|
309
|
+
d = dist(u, v, ax, ay, a)
|
|
310
|
+
return mix(skin, [180, 130, 90], d * 12) if d < 0.055
|
|
311
|
+
end
|
|
312
|
+
return jitter([140, 50, 40], u, v, 14)
|
|
313
|
+
end
|
|
314
|
+
return [90, 120, 90] if rn_seg(u, v, 0.86, 0.75, 0.99, 0.7, a) < 0.03 # green scarf
|
|
315
|
+
# the green-brown hill
|
|
316
|
+
hill = 0.62 + u * 0.55
|
|
317
|
+
return jitter(mix([110, 115, 80], [70, 75, 50], (v - hill) * 3), u, v, 12) if v > hill || v > 0.94
|
|
318
|
+
jitter(mix([205, 205, 195], [225, 220, 205], v), u, v, 8, 10)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# Raphael, The School of Athens
|
|
322
|
+
def rn_school_of_athens(u, v)
|
|
323
|
+
a = 1.54
|
|
324
|
+
x = (u - 0.5) * a
|
|
325
|
+
# the lunette frame
|
|
326
|
+
return [60, 50, 40] if v < 0.77 && Math.hypot(x, v - 0.77) > 0.765
|
|
327
|
+
# Plato (red) and Aristotle (blue) at the center of the steps
|
|
328
|
+
[[0.475, [190, 60, 50]], [0.525, [60, 90, 160]]].each do |fx, col|
|
|
329
|
+
part = rn_fig(u, v, fx, 0.42, 0.2, 0.05, a)
|
|
330
|
+
return part == :head ? [220, 190, 160] : col if part
|
|
331
|
+
end
|
|
332
|
+
# crowds on both sides
|
|
333
|
+
if v > 0.4 && v < 0.88
|
|
334
|
+
16.times do |i|
|
|
335
|
+
fx = 0.07 + i * 0.058
|
|
336
|
+
next if (fx - 0.5).abs < 0.06
|
|
337
|
+
[[0.43, 0.18], [0.62, 0.23]].each_with_index do |(top, h), row|
|
|
338
|
+
jx = fx + (noise(i, row) - 0.5) * 0.04 + row * 0.02
|
|
339
|
+
next if row == 1 && (jx - 0.5).abs < 0.12
|
|
340
|
+
part = rn_fig(u, v, jx, top + noise(i, row + 5) * 0.03, h, 0.05, a)
|
|
341
|
+
next unless part
|
|
342
|
+
return [215, 180, 145] if part == :head
|
|
343
|
+
return hsv(noise(i, row + 9) * 360, 0.45, 0.75)
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
# steps and floor
|
|
348
|
+
if v > 0.6
|
|
349
|
+
return Math.sin(v * 200) > 0.5 ? [180, 170, 150] : [210, 200, 180] if v < 0.7
|
|
350
|
+
return (((u - 0.5) * 12 / (v + 0.1)).floor + (v * 20).floor).even? ? [205, 190, 160] : [160, 140, 115]
|
|
351
|
+
end
|
|
352
|
+
# receding barrel-vaulted arches
|
|
353
|
+
arches = [[0.48, 0.5], [0.34, 0.47], [0.23, 0.45], [0.15, 0.44]]
|
|
354
|
+
arches.each_with_index do |(r, c), k|
|
|
355
|
+
open = v < c ? Math.hypot(x, v - c) < r : x.abs < r
|
|
356
|
+
next if open
|
|
357
|
+
if v < c
|
|
358
|
+
d = Math.hypot(x, v - c)
|
|
359
|
+
return [225, 215, 195] if d < r * 1.08
|
|
360
|
+
ang = Math.atan2(v - c, x)
|
|
361
|
+
return Math.sin(ang * 24) > 0.4 || Math.sin(d * 120) > 0.6 ? [150, 135, 110] : [185, 170, 145]
|
|
362
|
+
end
|
|
363
|
+
# piers, with dark statue niches on the outermost
|
|
364
|
+
return [70, 60, 50] if k.zero? && (x.abs - 0.62).abs < 0.04 && v > 0.3 && v < 0.55
|
|
365
|
+
prev_r = k.zero? ? 0.77 : arches[k - 1][0]
|
|
366
|
+
return mix([200, 185, 160], [150, 135, 115], (x.abs - r) / (prev_r - r))
|
|
367
|
+
end
|
|
368
|
+
# bright sky through the last arch
|
|
369
|
+
mix([150, 185, 215], [245, 245, 235], smooth(0.2, 0.55, v))
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
# Jan van Eyck, The Arnolfini Portrait
|
|
373
|
+
def rn_arnolfini_portrait(u, v)
|
|
374
|
+
a = 0.73
|
|
375
|
+
# the little dog
|
|
376
|
+
return [130, 95, 60] if ellipse(u, v, 0.5, 0.92, 0.07, 0.035) < 1
|
|
377
|
+
# the man: huge dark hat, pale face, dark fur coat
|
|
378
|
+
return [25, 18, 15] if ellipse(u, v, 0.33, 0.17, 0.11, 0.06) < 1 && v < 0.2
|
|
379
|
+
return [225, 190, 160] if ellipse(u, v, 0.33, 0.25, 0.05, 0.055) < 1
|
|
380
|
+
return [225, 190, 160] if dist(u, v, 0.43, 0.42, a) < 0.03 # raised hand
|
|
381
|
+
coat = [[0.27, 0.3], [0.39, 0.3], [0.47, 0.55], [0.47, 0.95], [0.18, 0.95], [0.2, 0.55]]
|
|
382
|
+
if inside?(u, v, coat)
|
|
383
|
+
return [95, 70, 45] if ((u - 0.18).abs < 0.03 || (u - 0.47).abs < 0.03) && v > 0.5 # fur trim
|
|
384
|
+
return jitter([55, 35, 45], u, v, 10)
|
|
385
|
+
end
|
|
386
|
+
# the woman in her green gown with white headdress
|
|
387
|
+
return [240, 238, 230] if ellipse(u, v, 0.67, 0.25, 0.075, 0.06) < 1 && v < 0.27
|
|
388
|
+
return [235, 205, 180] if ellipse(u, v, 0.66, 0.29, 0.045, 0.05) < 1
|
|
389
|
+
gown = [[0.6, 0.34], [0.72, 0.34], [0.78, 0.55], [0.86, 0.95], [0.5, 0.95], [0.55, 0.6]]
|
|
390
|
+
if inside?(u, v, gown)
|
|
391
|
+
return [60, 90, 160] if v > 0.4 && v < 0.5 && (u - 0.6).abs < 0.03 # blue sleeve
|
|
392
|
+
return mix([40, 110, 50], [20, 60, 30], Math.sin(u * 70 + v * 8) * 0.5 + 0.5)
|
|
393
|
+
end
|
|
394
|
+
return [235, 205, 180] if dist(u, v, 0.53, 0.43, a) < 0.03 # joined hands
|
|
395
|
+
# the chandelier
|
|
396
|
+
return [190, 150, 60] if v < 0.12 && ((u - 0.5).abs < 0.008 || (v > 0.06 && (u - 0.5).abs < 0.06 && Math.sin(u * 160) > 0.2))
|
|
397
|
+
# the convex mirror on the back wall
|
|
398
|
+
dm = dist(u, v, 0.5, 0.45, a)
|
|
399
|
+
return [60, 40, 25] if dm < 0.07 && dm > 0.055
|
|
400
|
+
return mix([170, 175, 165], [110, 100, 80], dm / 0.055) if dm < 0.055
|
|
401
|
+
# the red bed at the right
|
|
402
|
+
return jitter(Math.sin(u * 60) > 0.6 ? [130, 20, 20] : [170, 30, 30], u, v, 10) if u > 0.78 && v > 0.22
|
|
403
|
+
# the window at the left
|
|
404
|
+
if u < 0.15 && v > 0.08 && v < 0.55
|
|
405
|
+
return [70, 50, 30] if (u - 0.07).abs < 0.01 || (v - 0.3).abs < 0.01
|
|
406
|
+
return mix([220, 220, 200], [170, 175, 150], v)
|
|
407
|
+
end
|
|
408
|
+
return jitter([120, 85, 50], u, v, 12) if v > 0.82 # wooden floor
|
|
409
|
+
jitter(mix([110, 85, 55], [80, 60, 40], (u - 0.5).abs * 2), u, v, 8)
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
# fur for the hare: brown with fine light and dark hairs
|
|
413
|
+
def rn_fur(u, v, shade)
|
|
414
|
+
n = brush(u, v, angle: 1.1, freq: 70.0, wobble: 0.6)
|
|
415
|
+
base = mix([150, 115, 75], [85, 60, 40], shade)
|
|
416
|
+
return mix(base, [215, 195, 160], 0.35) if n > 0.5
|
|
417
|
+
n < -0.6 ? Color.scale(base, 0.7) : base
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
# Albrecht Dürer, Young Hare
|
|
421
|
+
def rn_young_hare(u, v)
|
|
422
|
+
a = 0.88
|
|
423
|
+
# ears up and slightly back
|
|
424
|
+
[[0.4, 0.37, 0.48, 0.08], [0.46, 0.38, 0.6, 0.1]].each_with_index do |(x1, y1, x2, y2), i|
|
|
425
|
+
d = rn_seg(u, v, x1, y1, x2, y2, a)
|
|
426
|
+
return rn_fur(u, v, 0.3 + i * 0.3) if d < 0.045 - 0.025 * Fx.clamp01((y1 - v) / (y1 - y2))
|
|
427
|
+
end
|
|
428
|
+
# head facing left
|
|
429
|
+
if ellipse(u, v, 0.37, 0.47, 0.13, 0.11) < 1
|
|
430
|
+
de = dist(u, v, 0.33, 0.44, a)
|
|
431
|
+
return [240, 240, 235] if de < 0.025 && dist(u, v, 0.325, 0.435, a) < 0.008
|
|
432
|
+
return [25, 20, 15] if de < 0.025
|
|
433
|
+
return [220, 205, 175] if ellipse(u, v, 0.26, 0.53, 0.04, 0.03) < 1 # muzzle
|
|
434
|
+
return rn_fur(u, v, 0.3)
|
|
435
|
+
end
|
|
436
|
+
# crouching body
|
|
437
|
+
if ellipse(u, v, 0.57, 0.66, 0.28, 0.23) < 1 || ellipse(u, v, 0.34, 0.8, 0.09, 0.1) < 1
|
|
438
|
+
return [225, 210, 180] if v > 0.78 && u < 0.45 && Math.sin(u * 90) > 0.6 # paws
|
|
439
|
+
return rn_fur(u, v, Fx.clamp01(0.2 + (u - 0.3) * 0.9 + (v - 0.5) * 0.3))
|
|
440
|
+
end
|
|
441
|
+
# soft shadow on the cream ground
|
|
442
|
+
return [205, 190, 160] if ellipse(u, v, 0.55, 0.9, 0.36, 0.05) < 1
|
|
443
|
+
jitter([238, 228, 205], u, v, 6, 6)
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
# Albrecht Dürer, Self-Portrait at Twenty-Eight
|
|
447
|
+
def rn_durer_self_portrait(u, v)
|
|
448
|
+
a = 0.73
|
|
449
|
+
skin = [220, 175, 135]
|
|
450
|
+
cx = 0.5
|
|
451
|
+
# face, frontal and symmetric
|
|
452
|
+
if ellipse(u, v, cx, 0.33, 0.15, 0.15) < 1 && v > 0.21
|
|
453
|
+
mx = (u - cx).abs
|
|
454
|
+
return [40, 30, 20] if (v - 0.3).abs < 0.012 && (mx - 0.06).abs < 0.03 # eyes
|
|
455
|
+
return [110, 70, 40] if v > 0.4 && mx < 0.11 - (v - 0.4) * 0.6 # beard and moustache
|
|
456
|
+
return mix(skin, [160, 115, 80], mx * 3)
|
|
457
|
+
end
|
|
458
|
+
# long curly hair to the shoulders
|
|
459
|
+
if ellipse(u, v, cx, 0.36, 0.3, 0.28) < 1 && v < 0.6
|
|
460
|
+
curl = Math.sin(dist(u, v, cx + (u > cx ? 0.2 : -0.2), 0.45, a) * 90 + v * 20)
|
|
461
|
+
return curl > 0.3 ? [175, 115, 60] : [120, 75, 40]
|
|
462
|
+
end
|
|
463
|
+
return [100, 65, 40] if v > 0.42 && v < 0.5 && (u - cx).abs < 0.08 # beard below the chin
|
|
464
|
+
# fur collar and dark coat
|
|
465
|
+
if v > 0.5 && (u - cx).abs < 0.15 + (v - 0.5) * 1.2
|
|
466
|
+
return skin if ellipse(u, v, 0.47, 0.88, 0.06, 0.07) < 1 # hand at the fur
|
|
467
|
+
if (u - cx).abs < 0.12 + (v - 0.5) * 0.3 || v < 0.6
|
|
468
|
+
return mix([130, 90, 55], [80, 55, 35], brush(u, v, angle: 1.2, freq: 50.0) * 0.5 + 0.5)
|
|
469
|
+
end
|
|
470
|
+
return jitter([50, 38, 28], u, v, 8)
|
|
471
|
+
end
|
|
472
|
+
# the gold inscriptions on the dark ground
|
|
473
|
+
return [190, 150, 70] if v.between?(0.3, 0.36) && u.between?(0.08, 0.16) && Math.sin(u * 200) > 0
|
|
474
|
+
if u.between?(0.82, 0.95) && v.between?(0.26, 0.4) && (v * 40 - (v * 40).floor) < 0.4 && noise((u * 60).floor, (v * 40).floor) > 0.3
|
|
475
|
+
return [180, 140, 65]
|
|
476
|
+
end
|
|
477
|
+
jitter([30, 22, 16], u, v, 6)
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
# Pieter Bruegel the Elder, Hunters in the Snow
|
|
481
|
+
def rn_hunters_in_the_snow(u, v)
|
|
482
|
+
a = 1.39
|
|
483
|
+
dark = [40, 30, 25]
|
|
484
|
+
# hunters with spears and their dogs trudging along the hill
|
|
485
|
+
[[0.14, 0.66], [0.22, 0.69], [0.3, 0.72]].each do |hx, hy|
|
|
486
|
+
return dark if (u - hx).abs < 0.016 && v > hy - 0.12 && v < hy
|
|
487
|
+
return dark if dist(u, v, hx, hy - 0.13, a) < 0.02
|
|
488
|
+
return dark if rn_seg(u, v, hx + 0.01, hy - 0.08, hx - 0.05, hy - 0.2, a) < 0.007 # spears
|
|
489
|
+
end
|
|
490
|
+
[[0.18, 0.72], [0.25, 0.75], [0.34, 0.77], [0.1, 0.7]].each do |dx, dy|
|
|
491
|
+
return dark if ellipse(u, v, dx, dy, 0.025, 0.015) < 1 # dogs
|
|
492
|
+
end
|
|
493
|
+
# tall bare trees in a row down the slope
|
|
494
|
+
hill = 0.5 + u * 0.6 + 0.015 * Math.sin(u * 25)
|
|
495
|
+
[0.06, 0.19, 0.31, 0.43, 0.54].each_with_index do |tx, i|
|
|
496
|
+
base = 0.55 + tx * 0.6
|
|
497
|
+
next unless v < base
|
|
498
|
+
x = u - tx - (base - v) * 0.03 * (i.even? ? 1 : -1)
|
|
499
|
+
return dark if x.abs < 0.005 + (v / base) * 0.005
|
|
500
|
+
return dark if v < base - 0.12 && Math.sin(v * 45 + x * 40 + i) > 0.93 && x.abs < 0.08 * (base - v)
|
|
501
|
+
end
|
|
502
|
+
if v > hill
|
|
503
|
+
return [200, 80, 40] if dist(u, v, 0.04, 0.6, a) < 0.03 # the inn's fire
|
|
504
|
+
return jitter(mix([190, 198, 200], [240, 240, 235], smooth(0.0, 0.08, v - hill)), u, v, 8)
|
|
505
|
+
end
|
|
506
|
+
# the valley: snow, frozen ponds with skaters, houses
|
|
507
|
+
if v > 0.42 + 0.03 * Math.sin(u * 10)
|
|
508
|
+
[[0.62, 0.75, 0.2, 0.1], [0.82, 0.62, 0.15, 0.06], [0.55, 0.6, 0.08, 0.04]].each do |px, py, rx, ry|
|
|
509
|
+
next unless ellipse(u, v, px, py, rx, ry) < 1
|
|
510
|
+
return dark if noise((u * 90).floor, (v * 70).floor) > 0.9
|
|
511
|
+
return [140, 160, 150]
|
|
512
|
+
end
|
|
513
|
+
return [110, 60, 45] if noise((u * 40).floor, (v * 30).floor) > 0.86 # houses
|
|
514
|
+
return mix([235, 238, 232], [200, 205, 200], v)
|
|
515
|
+
end
|
|
516
|
+
# jagged mountains at the right
|
|
517
|
+
peaks = 0.33 + 0.08 * Math.sin(u * 30).abs - (u - 0.5) * 0.25
|
|
518
|
+
return mix([235, 240, 238], [150, 165, 160], (v - peaks) * 8) if u > 0.5 && v > peaks
|
|
519
|
+
return dark if dist(u, v, 0.62, 0.22, a) < 0.012 # the crow
|
|
520
|
+
mix([160, 185, 175], [200, 210, 200], v * 2)
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
# Pieter Bruegel the Elder, The Tower of Babel
|
|
524
|
+
def rn_tower_of_babel(u, v)
|
|
525
|
+
cx = 0.47
|
|
526
|
+
base_v = 0.78
|
|
527
|
+
top_v = 0.12
|
|
528
|
+
if v > top_v && v < base_v
|
|
529
|
+
t = (base_v - v) / (base_v - top_v) # 0 at the bottom, 1 at the top
|
|
530
|
+
hw = 0.36 * (1 - t * 0.78)
|
|
531
|
+
# the unfinished top: a ragged crown with red brick exposed on the right
|
|
532
|
+
hw *= 0.85 + 0.15 * Math.sin(u * 40) if t > 0.85
|
|
533
|
+
if (u - cx).abs < hw
|
|
534
|
+
band = t * 7.0
|
|
535
|
+
f = band - band.floor
|
|
536
|
+
sx = (u - cx) / hw # -1..1 across the cone
|
|
537
|
+
light = 1.0 - 0.45 * Fx.clamp01(sx + 0.3)
|
|
538
|
+
return Color.scale([160, 80, 60], light) if t > 0.7 && sx > 0.2 # raw brick
|
|
539
|
+
return Color.scale([225, 210, 175], light) if f > 0.82 # ledge
|
|
540
|
+
arch = Math.sin(Math.asin(sx.clamp(-1.0, 1.0)) * (22 - band * 2))
|
|
541
|
+
return Color.scale([70, 55, 45], light) if f < 0.55 && f > 0.15 && arch > 0.2
|
|
542
|
+
return jitter(Color.scale([200, 180, 140], light), u, v, 10)
|
|
543
|
+
end
|
|
544
|
+
end
|
|
545
|
+
# the harbor with ships at the right
|
|
546
|
+
if u > 0.72 && v > 0.62
|
|
547
|
+
return [230, 225, 210] if Math.sin(u * 40) > 0.85 && v < 0.75 && v > 0.64 # sails
|
|
548
|
+
return mix([120, 150, 160], [70, 100, 110], (v - 0.62) * 3)
|
|
549
|
+
end
|
|
550
|
+
# the city around the base
|
|
551
|
+
if v > 0.66
|
|
552
|
+
return [160, 85, 60] if noise((u * 60).floor, (v * 40).floor) > 0.8
|
|
553
|
+
return jitter([170, 160, 130], u, v, 14)
|
|
554
|
+
end
|
|
555
|
+
# countryside to the horizon
|
|
556
|
+
return jitter([120, 140, 110], u, v, 12) if v > 0.55 + 0.03 * Math.sin(u * 8)
|
|
557
|
+
# clouds drifting around the upper tower
|
|
558
|
+
return [235, 238, 240] if (v - 0.2 - u * 0.1).abs < 0.03 && Math.sin(u * 18) > 0
|
|
559
|
+
mix([150, 180, 205], [215, 225, 225], v * 1.6)
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
# Hieronymus Bosch, The Garden of Earthly Delights
|
|
563
|
+
def rn_garden_of_earthly_delights(u, v)
|
|
564
|
+
a = 1.77
|
|
565
|
+
# dark frames between the panels
|
|
566
|
+
return [30, 22, 18] if u < 0.01 || u > 0.99 || (u - 0.255).abs < 0.008 || (u - 0.745).abs < 0.008
|
|
567
|
+
if u < 0.255
|
|
568
|
+
# Eden: green land, the pink fountain, a pond
|
|
569
|
+
lu = u / 0.255
|
|
570
|
+
return mix([200, 215, 220], [150, 180, 190], 1 - v * 3) if v < 0.28
|
|
571
|
+
return [235, 160, 170] if (lu - 0.5).abs < 0.06 + (v > 0.48 ? 0.05 : 0) && v > 0.3 && v < 0.55
|
|
572
|
+
return [90, 130, 150] if ellipse(lu, v, 0.5, 0.6, 0.3, 0.06) < 1
|
|
573
|
+
return [230, 210, 190] if noise((u * 90).floor, (v * 60).floor) > 0.95 && v > 0.7
|
|
574
|
+
return jitter(mix([110, 150, 80], [60, 100, 50], v), u, v, 14)
|
|
575
|
+
end
|
|
576
|
+
if u < 0.745
|
|
577
|
+
# the garden: pale sky, pink and blue fantastical towers, crowds of tiny figures
|
|
578
|
+
cu = (u - 0.255) / 0.49
|
|
579
|
+
return mix([200, 215, 225], [170, 195, 210], 1 - v * 4) if v < 0.15
|
|
580
|
+
if v < 0.32
|
|
581
|
+
[[0.15, 0.04], [0.35, 0.03], [0.5, 0.05], [0.68, 0.03], [0.86, 0.04]].each_with_index do |(tx, tw), i|
|
|
582
|
+
next unless (cu - tx).abs < tw + (v - 0.15) * 0.15
|
|
583
|
+
return dist(cu, v, tx, 0.24, a * 0.5) < 0.04 ? [90, 120, 190] : (i.even? ? [230, 160, 175] : [120, 150, 200])
|
|
584
|
+
end
|
|
585
|
+
return mix([150, 190, 170], [120, 160, 130], (v - 0.15) * 4)
|
|
586
|
+
end
|
|
587
|
+
# the round pool with its cavalcade
|
|
588
|
+
pe = ellipse(cu, v, 0.5, 0.42, 0.22, 0.07)
|
|
589
|
+
return [100, 140, 170] if pe < 0.5
|
|
590
|
+
return noise((u * 80).floor, (v * 50).floor) > 0.5 ? [210, 180, 160] : [150, 110, 80] if pe < 1
|
|
591
|
+
[[0.2, 0.62], [0.78, 0.7], [0.45, 0.82]].each do |bx, by|
|
|
592
|
+
return [110, 150, 210] if dist(cu, v, bx, by, a * 0.5) < 0.04 # blue spheres
|
|
593
|
+
end
|
|
594
|
+
n = noise((u * 100).floor, (v * 70).floor)
|
|
595
|
+
return [240, 215, 200] if n > 0.86 # tiny pale figures
|
|
596
|
+
return [200, 50, 50] if n > 0.83 # giant berries
|
|
597
|
+
return jitter([150, 180, 120], u, v, 14)
|
|
598
|
+
end
|
|
599
|
+
# hell: darkness, fire glows, the tree-man, ice
|
|
600
|
+
ru = (u - 0.745) / 0.255
|
|
601
|
+
if v < 0.3
|
|
602
|
+
glow = Math.sin(ru * 18) * 0.04 + 0.18
|
|
603
|
+
return mix([250, 170, 60], [140, 30, 10], (glow - v).abs * 12) if (v - glow).abs < 0.06
|
|
604
|
+
return [20, 14, 12]
|
|
605
|
+
end
|
|
606
|
+
return [230, 220, 210] if ellipse(ru, v, 0.5, 0.45, 0.18, 0.06) < 1 # tree-man's broken shell
|
|
607
|
+
return [180, 175, 165] if ((ru - 0.42).abs < 0.03 && v > 0.48 && v < 0.65) || ((ru - 0.6).abs < 0.03 && v > 0.48 && v < 0.62)
|
|
608
|
+
return [110, 130, 150] if v > 0.6 && v < 0.68 # frozen lake
|
|
609
|
+
return [230, 120, 40] if noise((u * 80).floor, (v * 60).floor) > 0.94
|
|
610
|
+
jitter([35, 28, 30], u, v, 10)
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
# Johannes Vermeer, Girl with a Pearl Earring
|
|
614
|
+
def rn_girl_with_pearl_earring(u, v)
|
|
615
|
+
a = 0.88
|
|
616
|
+
skin = [235, 210, 180]
|
|
617
|
+
# the pearl
|
|
618
|
+
dp = dist(u, v, 0.4, 0.62, a)
|
|
619
|
+
return [255, 255, 250] if dp < 0.012
|
|
620
|
+
return [200, 205, 205] if dp < 0.028
|
|
621
|
+
# blue turban and the yellow cloth hanging behind
|
|
622
|
+
if ellipse(u, v, 0.48, 0.24, 0.17, 0.12) < 1 && v < 0.33 - (u - 0.48) * 0.2
|
|
623
|
+
return mix([60, 90, 170], [30, 45, 100], smooth(0.4, 0.6, u))
|
|
624
|
+
end
|
|
625
|
+
if inside?(u, v, [[0.6, 0.14], [0.66, 0.16], [0.7, 0.5], [0.66, 0.6], [0.6, 0.45]])
|
|
626
|
+
return mix([230, 200, 110], [170, 140, 60], (u - 0.58) * 6)
|
|
627
|
+
end
|
|
628
|
+
# face, lit from the left
|
|
629
|
+
if ellipse(u, v, 0.5, 0.47, 0.145, 0.17) < 1 && v > 0.3
|
|
630
|
+
return [60, 45, 35] if dist(u, v, 0.44, 0.44, a) < 0.022 || dist(u, v, 0.57, 0.44, a) < 0.02 # eyes
|
|
631
|
+
return [195, 85, 80] if ellipse(u, v, 0.48, 0.59, 0.035, 0.018) < 1 # parted lips
|
|
632
|
+
return mix(skin, [180, 145, 110], 0.5) if (u - 0.5).abs < 0.012 && v > 0.46 && v < 0.53 # nose shadow
|
|
633
|
+
return mix(skin, [130, 100, 75], smooth(0.5, 0.64, u))
|
|
634
|
+
end
|
|
635
|
+
# the ochre jacket with a white collar
|
|
636
|
+
shoulder = 0.68 + (u - 0.5).abs * 0.25
|
|
637
|
+
if v > shoulder
|
|
638
|
+
return [235, 232, 220] if v < shoulder + 0.05 && u > 0.33 && u < 0.62
|
|
639
|
+
return mix([170, 140, 70], [90, 70, 40], smooth(0.3, 0.8, u))
|
|
640
|
+
end
|
|
641
|
+
return [40, 32, 25] if (u - 0.45).abs < 0.06 && v > 0.6 # shadowed neck
|
|
642
|
+
jitter([22, 24, 18], u, v, 5)
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
# Johannes Vermeer, The Milkmaid
|
|
646
|
+
def rn_milkmaid(u, v)
|
|
647
|
+
a = 0.9
|
|
648
|
+
skin = [225, 185, 145]
|
|
649
|
+
# the milk stream into the bowl
|
|
650
|
+
return [250, 245, 230] if (u - 0.425).abs < 0.008 && v > 0.58 && v < 0.66
|
|
651
|
+
return [140, 85, 45] if ellipse(u, v, 0.42, 0.67, 0.08, 0.035) < 1 # bowl
|
|
652
|
+
return [115, 72, 40] if ellipse(u, v, 0.45, 0.545, 0.05, 0.055) < 1 # jug
|
|
653
|
+
# the maid
|
|
654
|
+
return [240, 238, 225] if ellipse(u, v, 0.57, 0.17, 0.075, 0.07) < 1 && v < 0.19 # white cap
|
|
655
|
+
return mix(skin, [190, 150, 115], smooth(0.55, 0.62, u)) if ellipse(u, v, 0.56, 0.23, 0.06, 0.065) < 1
|
|
656
|
+
return [100, 125, 115] if rn_seg(u, v, 0.48, 0.33, 0.43, 0.48, a) < 0.05 || rn_seg(u, v, 0.67, 0.35, 0.56, 0.5, a) < 0.05 # sleeves
|
|
657
|
+
return skin if rn_seg(u, v, 0.43, 0.48, 0.44, 0.54, a) < 0.035 || rn_seg(u, v, 0.56, 0.5, 0.49, 0.53, a) < 0.035
|
|
658
|
+
return mix([245, 210, 80], [180, 140, 50], (u - 0.45) * 4) if inside?(u, v, [[0.46, 0.29], [0.67, 0.29], [0.7, 0.52], [0.47, 0.52]]) # yellow bodice
|
|
659
|
+
if inside?(u, v, [[0.45, 0.5], [0.7, 0.5], [0.8, 0.98], [0.44, 0.98]])
|
|
660
|
+
return [55, 85, 150] if u > 0.48 && u < 0.72 + (v - 0.5) * 0.1 && v < 0.88 # blue apron
|
|
661
|
+
return [150, 50, 40]
|
|
662
|
+
end
|
|
663
|
+
# the table with bread and the green-blue cloth
|
|
664
|
+
if v > 0.62 && u < 0.46 - (v - 0.62) * 0.2
|
|
665
|
+
return [180, 120, 60] if ellipse(u, v, 0.18, 0.68, 0.1, 0.05) < 1 || ellipse(u, v, 0.3, 0.69, 0.05, 0.03) < 1 # bread
|
|
666
|
+
return jitter([70, 100, 110], u, v, 14)
|
|
667
|
+
end
|
|
668
|
+
return [120, 90, 60] if u > 0.82 && v > 0.88 # foot warmer
|
|
669
|
+
# the window at the left
|
|
670
|
+
if u < 0.2 && v > 0.08 && v < 0.5
|
|
671
|
+
return [80, 75, 60] if (u * 20 - (u * 20).floor) < 0.15 || (v * 20 - (v * 20).floor) < 0.15
|
|
672
|
+
return mix([230, 235, 225], [180, 190, 180], v)
|
|
673
|
+
end
|
|
674
|
+
return [70, 60, 50] if dist(u, v, 0.1, 0.56, a) < 0.05 # basket on the wall
|
|
675
|
+
jitter(mix([215, 210, 190], [170, 160, 140], smooth(0.2, 1.0, u)), u, v, 8, 12)
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
# Johannes Vermeer, View of Delft
|
|
679
|
+
def rn_view_of_delft(u, v)
|
|
680
|
+
# the low skyline: roofs, towers, the gate
|
|
681
|
+
roof = 0.56 - 0.02 * Math.sin(u * 37).abs - (Math.sin(u * 91) > 0.5 ? 0.015 : 0)
|
|
682
|
+
tower = ((u - 0.66).abs < 0.015 && v > 0.36) || ((u - 0.34).abs < 0.02 && v > 0.47) || ((u - 0.28).abs < 0.012 && v > 0.45)
|
|
683
|
+
if v < 0.64 && (v > roof || tower)
|
|
684
|
+
return [235, 210, 120] if (u - 0.66).abs < 0.015 # sunlit church tower
|
|
685
|
+
return [60, 75, 90] if v < roof + 0.02 && u > 0.36 && u < 0.6 && !tower
|
|
686
|
+
return noise((u * 70).floor, (v * 50).floor) > 0.6 ? [150, 70, 45] : [110, 75, 55]
|
|
687
|
+
end
|
|
688
|
+
# the bridge
|
|
689
|
+
return [100, 80, 60] if v > 0.6 && v < 0.64 && u > 0.38 && u < 0.5
|
|
690
|
+
# water with reflections
|
|
691
|
+
if v > 0.64 && v < 0.86 - 0.03 * Math.sin(u * 6)
|
|
692
|
+
refl = Math.sin(v * 160 + u * 4) > 0.3 ? 0.9 : 1.0
|
|
693
|
+
base = u < 0.45 ? [65, 60, 55] : [70, 85, 95]
|
|
694
|
+
return Color.scale(mix(base, [120, 140, 145], (v - 0.64) * 3), refl)
|
|
695
|
+
end
|
|
696
|
+
# the sandy bank with figures and boats
|
|
697
|
+
if v >= 0.64
|
|
698
|
+
return [40, 50, 70] if ((u - 0.1).abs < 0.008 || (u - 0.14).abs < 0.008) && v > 0.85 && v < 0.9
|
|
699
|
+
return [60, 50, 40] if u > 0.8 && v < 0.88 && ellipse(u, v, 0.88, 0.86, 0.08, 0.025) < 1
|
|
700
|
+
return jitter([200, 175, 130], u, v, 12)
|
|
701
|
+
end
|
|
702
|
+
# the big cloudy sky
|
|
703
|
+
cloud = vnoise(u * 1.5, v * 3, 4)
|
|
704
|
+
base = mix([90, 125, 175], [190, 205, 215], v * 1.8)
|
|
705
|
+
return mix(base, [80, 85, 95], 0.7) if v < 0.15 && cloud > 0.45
|
|
706
|
+
return mix(base, [245, 245, 240], (cloud - 0.5) * 3) if cloud > 0.5
|
|
707
|
+
base
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
# Rembrandt, The Night Watch
|
|
711
|
+
def rn_night_watch(u, v)
|
|
712
|
+
a = 1.2
|
|
713
|
+
# the captain in black with a red sash, and the lieutenant in gold
|
|
714
|
+
return [230, 200, 170] if dist(u, v, 0.48, 0.42, a) < 0.035
|
|
715
|
+
return [240, 240, 235] if ellipse(u, v, 0.48, 0.47, 0.04, 0.015) < 1 # ruff
|
|
716
|
+
return [20, 15, 12] if dist(u, v, 0.48, 0.385, a) < 0.05 && v < 0.4 # hat
|
|
717
|
+
if inside?(u, v, [[0.44, 0.48], [0.52, 0.48], [0.55, 0.95], [0.42, 0.95]])
|
|
718
|
+
return [200, 40, 30] if (v - 0.52 - (u - 0.44) * 0.8).abs < 0.025 # sash
|
|
719
|
+
return [20, 16, 14]
|
|
720
|
+
end
|
|
721
|
+
return [225, 195, 160] if dist(u, v, 0.6, 0.44, a) < 0.03
|
|
722
|
+
return [235, 225, 200] if dist(u, v, 0.6, 0.41, a) < 0.04 && v < 0.42 # white plume hat
|
|
723
|
+
return mix([250, 225, 130], [180, 140, 60], (u - 0.57) * 8) if inside?(u, v, [[0.57, 0.48], [0.64, 0.48], [0.66, 0.95], [0.56, 0.95]])
|
|
724
|
+
# the glowing girl in gold at the left
|
|
725
|
+
return [245, 220, 150] if dist(u, v, 0.33, 0.52, a) < 0.03
|
|
726
|
+
return mix([255, 225, 120], [200, 160, 70], dist(u, v, 0.33, 0.62, a) * 10) if ellipse(u, v, 0.33, 0.64, 0.05, 0.1) < 1
|
|
727
|
+
# pikes and the musketeers in the gloom
|
|
728
|
+
if rn_seg(u, v, 0.15, 0.7, 0.3, 0.1, a) < 0.006 || rn_seg(u, v, 0.7, 0.6, 0.85, 0.05, a) < 0.006 || rn_seg(u, v, 0.62, 0.55, 0.55, 0.05, a) < 0.006
|
|
729
|
+
return [90, 70, 45]
|
|
730
|
+
end
|
|
731
|
+
[[0.12, 0.45], [0.2, 0.38], [0.26, 0.5], [0.38, 0.3], [0.55, 0.28], [0.7, 0.35], [0.78, 0.42], [0.86, 0.38], [0.92, 0.5], [0.67, 0.25]].each_with_index do |(fx, fy), i|
|
|
732
|
+
return mix([200, 160, 110], [110, 80, 50], i * 0.08) if dist(u, v, fx, fy, a) < 0.025
|
|
733
|
+
return mix([70, 50, 30], [30, 22, 16], noise(i, 3)) if (u - fx).abs < 0.04 && v > fy + 0.02 && v < 0.95
|
|
734
|
+
end
|
|
735
|
+
return [55, 45, 40] if v > 0.92 # floor
|
|
736
|
+
glow = Fx.clamp01(1 - dist(u, v, 0.5, 0.55, a) * 1.6)
|
|
737
|
+
jitter(mix([22, 16, 10], [95, 70, 40], glow), u, v, 6)
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
# Diego Velázquez, Las Meninas
|
|
741
|
+
def rn_las_meninas(u, v)
|
|
742
|
+
a = 0.87
|
|
743
|
+
skin = [230, 200, 170]
|
|
744
|
+
# the Infanta in her wide pale gown
|
|
745
|
+
return [235, 210, 150] if dist(u, v, 0.5, 0.58, a) < 0.04 && v < 0.58 # blond hair
|
|
746
|
+
return skin if dist(u, v, 0.5, 0.6, a) < 0.035
|
|
747
|
+
return mix([235, 230, 215], [190, 185, 170], (u - 0.42) * 5) if v > 0.64 && v < 0.92 && (u - 0.5).abs < 0.03 + (v - 0.64) * 0.55
|
|
748
|
+
# the maids of honor
|
|
749
|
+
[[0.38, 0.63, [150, 140, 110]], [0.62, 0.62, [120, 110, 90]]].each do |mx, my, col|
|
|
750
|
+
return skin if dist(u, v, mx, my, a) < 0.03
|
|
751
|
+
return col if v > my + 0.03 && v < 0.92 && (u - mx).abs < 0.03 + (v - my) * 0.3
|
|
752
|
+
end
|
|
753
|
+
# the dwarf and the dog at the right
|
|
754
|
+
return skin if dist(u, v, 0.76, 0.7, a) < 0.03
|
|
755
|
+
return [50, 55, 70] if v > 0.73 && v < 0.9 && (u - 0.76).abs < 0.05
|
|
756
|
+
return [150, 120, 80] if ellipse(u, v, 0.78, 0.92, 0.09, 0.03) < 1
|
|
757
|
+
# the painter before his canvas
|
|
758
|
+
return skin if dist(u, v, 0.3, 0.42, a) < 0.03
|
|
759
|
+
return [30, 25, 22] if v > 0.45 && v < 0.85 && (u - 0.3).abs < 0.04
|
|
760
|
+
# the back of the huge canvas
|
|
761
|
+
if u < 0.22 && v > 0.05 && v < 0.9
|
|
762
|
+
return [70, 50, 35] if u > 0.2 || (v - 0.1).abs < 0.01
|
|
763
|
+
return jitter([95, 70, 45], u, v, 10)
|
|
764
|
+
end
|
|
765
|
+
# the bright open doorway with a figure, and the mirror
|
|
766
|
+
if (u - 0.62).abs < 0.035 && v > 0.36 && v < 0.55
|
|
767
|
+
return [30, 25, 20] if (u - 0.62).abs < 0.01 && v > 0.42
|
|
768
|
+
return [240, 220, 170]
|
|
769
|
+
end
|
|
770
|
+
return [170, 175, 170] if (u - 0.5).abs < 0.02 && v > 0.4 && v < 0.46 # the royal couple in the mirror
|
|
771
|
+
return [40, 30, 22] if (u - 0.5).abs < 0.03 && v > 0.38 && v < 0.48
|
|
772
|
+
# paintings hung high on the back wall
|
|
773
|
+
return [45, 35, 25] if v > 0.12 && v < 0.27 && ((u - 0.4).abs < 0.08 || (u - 0.62).abs < 0.08)
|
|
774
|
+
# light from the windows at the right
|
|
775
|
+
return jitter(mix([80, 70, 55], [140, 120, 90], u), u, v, 8) if v > 0.9
|
|
776
|
+
jitter(mix([60, 50, 38], [110, 95, 75], smooth(0.3, 1.0, u) * (1 - v * 0.5)), u, v, 8)
|
|
777
|
+
end
|
|
778
|
+
|
|
779
|
+
# Caravaggio, The Calling of Saint Matthew
|
|
780
|
+
def rn_calling_of_saint_matthew(u, v)
|
|
781
|
+
a = 1.06
|
|
782
|
+
skin = [215, 170, 125]
|
|
783
|
+
# Christ at the right edge pointing across the room
|
|
784
|
+
return [200, 150, 110] if rn_seg(u, v, 0.82, 0.44, 0.66, 0.42, a) < 0.016
|
|
785
|
+
return skin if dist(u, v, 0.86, 0.37, a) < 0.04
|
|
786
|
+
return [130, 50, 40] if inside?(u, v, [[0.82, 0.42], [0.92, 0.42], [0.98, 0.95], [0.84, 0.95]])
|
|
787
|
+
return [120, 100, 70] if inside?(u, v, [[0.7, 0.47], [0.8, 0.47], [0.84, 0.95], [0.68, 0.95]]) # Peter
|
|
788
|
+
return skin if dist(u, v, 0.75, 0.43, a) < 0.035
|
|
789
|
+
# the group at the table on the left, lit by the beam
|
|
790
|
+
[[0.12, 0.38, [200, 170, 60]], [0.25, 0.4, [190, 70, 50]], [0.37, 0.36, [60, 80, 60]], [0.48, 0.4, [220, 200, 170]]].each do |fx, fy, col|
|
|
791
|
+
return mix(skin, [255, 230, 190], 0.3) if dist(u, v, fx, fy, a) < 0.04
|
|
792
|
+
return [30, 25, 20] if dist(u, v, fx, fy - 0.035, a) < 0.045 && v < fy - 0.01 # hats
|
|
793
|
+
return col if (u - fx).abs < 0.06 && v > fy + 0.04 && v < 0.66
|
|
794
|
+
end
|
|
795
|
+
return [200, 160, 110] if v > 0.62 && v < 0.7 && u < 0.6 # table top
|
|
796
|
+
return [70, 45, 35] if v > 0.7 && v < 0.95 && u < 0.6 && (u < 0.03 || (u - 0.55).abs < 0.02 || Math.sin(u * 30) > 0.8)
|
|
797
|
+
# the window, dark
|
|
798
|
+
if u > 0.38 && u < 0.62 && v > 0.08 && v < 0.32
|
|
799
|
+
return [150, 130, 90] if (u - 0.5).abs < 0.008 || (v - 0.2).abs < 0.008 || u < 0.39 || u > 0.61
|
|
800
|
+
return [40, 35, 28]
|
|
801
|
+
end
|
|
802
|
+
# the diagonal beam of light from the upper right
|
|
803
|
+
beam = v - (0.05 + (1 - u) * 0.55)
|
|
804
|
+
return jitter(mix([150, 125, 85], [95, 80, 55], -beam * 3), u, v, 8) if beam < 0.02 && beam > -0.28 && v < 0.62
|
|
805
|
+
jitter([30, 26, 22], u, v, 6)
|
|
806
|
+
end
|
|
807
|
+
end
|
|
808
|
+
|
|
809
|
+
piece(:birth_of_venus, "The Birth of Venus", "Sandro Botticelli", "c. 1485", aspect: 1.58) { |u, v| rn_birth_of_venus(u, v) }
|
|
810
|
+
piece(:primavera, "Primavera", "Sandro Botticelli", "c. 1480", aspect: 1.55) { |u, v| rn_primavera(u, v) }
|
|
811
|
+
piece(:last_supper, "The Last Supper", "Leonardo da Vinci", "1498", aspect: 1.9) { |u, v| rn_last_supper(u, v) }
|
|
812
|
+
piece(:lady_with_ermine, "Lady with an Ermine", "Leonardo da Vinci", "c. 1490", aspect: 0.74) { |u, v| rn_lady_with_ermine(u, v) }
|
|
813
|
+
piece(:vitruvian_man, "Vitruvian Man", "Leonardo da Vinci", "c. 1490", aspect: 0.73) { |u, v| rn_vitruvian_man(u, v) }
|
|
814
|
+
piece(:creation_of_adam, "The Creation of Adam", "Michelangelo", "c. 1512", aspect: 2.2) { |u, v| rn_creation_of_adam(u, v) }
|
|
815
|
+
piece(:school_of_athens, "The School of Athens", "Raphael", "1511", aspect: 1.54) { |u, v| rn_school_of_athens(u, v) }
|
|
816
|
+
piece(:arnolfini_portrait, "The Arnolfini Portrait", "Jan van Eyck", "1434", aspect: 0.73) { |u, v| rn_arnolfini_portrait(u, v) }
|
|
817
|
+
piece(:young_hare, "Young Hare", "Albrecht Dürer", "1502", aspect: 0.88) { |u, v| rn_young_hare(u, v) }
|
|
818
|
+
piece(:durer_self_portrait, "Self-Portrait at Twenty-Eight", "Albrecht Dürer", "1500", aspect: 0.73) { |u, v| rn_durer_self_portrait(u, v) }
|
|
819
|
+
piece(:hunters_in_the_snow, "Hunters in the Snow", "Pieter Bruegel the Elder", "1565", aspect: 1.39) { |u, v| rn_hunters_in_the_snow(u, v) }
|
|
820
|
+
piece(:tower_of_babel, "The Tower of Babel", "Pieter Bruegel the Elder", "1563", aspect: 1.36) { |u, v| rn_tower_of_babel(u, v) }
|
|
821
|
+
piece(:garden_of_earthly_delights, "The Garden of Earthly Delights", "Hieronymus Bosch", "c. 1500", aspect: 1.77) { |u, v| rn_garden_of_earthly_delights(u, v) }
|
|
822
|
+
piece(:girl_with_pearl_earring, "Girl with a Pearl Earring", "Johannes Vermeer", "c. 1665", aspect: 0.88) { |u, v| rn_girl_with_pearl_earring(u, v) }
|
|
823
|
+
piece(:milkmaid, "The Milkmaid", "Johannes Vermeer", "c. 1658", aspect: 0.9) { |u, v| rn_milkmaid(u, v) }
|
|
824
|
+
piece(:view_of_delft, "View of Delft", "Johannes Vermeer", "c. 1661", aspect: 1.2) { |u, v| rn_view_of_delft(u, v) }
|
|
825
|
+
piece(:night_watch, "The Night Watch", "Rembrandt", "1642", aspect: 1.2) { |u, v| rn_night_watch(u, v) }
|
|
826
|
+
piece(:las_meninas, "Las Meninas", "Diego Velázquez", "1656", aspect: 0.87) { |u, v| rn_las_meninas(u, v) }
|
|
827
|
+
piece(:calling_of_saint_matthew, "The Calling of Saint Matthew", "Caravaggio", "1600", aspect: 1.06) { |u, v| rn_calling_of_saint_matthew(u, v) }
|
|
828
|
+
end
|
|
829
|
+
end
|