Presentation is loading. Please wait.

Presentation is loading. Please wait.

Twelve painting with procedures. Overview Making shaded images with procedures Making a more elegant language Making textures with noise functions.

Similar presentations


Presentation on theme: "Twelve painting with procedures. Overview Making shaded images with procedures Making a more elegant language Making textures with noise functions."— Presentation transcript:

1 twelve painting with procedures

2 Overview Making shaded images with procedures Making a more elegant language Making textures with noise functions

3 Making bitmaps [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors for pixels by calling procedure Passes procedure a point (vector) object with the coordinates Procedure returns a color object (color image) or a single number (grayscale image)

4 Making a grayscale ramp We can use dot products to make a grayscale ramp The dot-product of two vectors is a single number It increases as The first vector grows in the direction of the second, or alternatively, The second grows in the direction of the first i.e. it’s symmetrical Each vector gets bigger By manipulating the direction of the vector in the dot- product, we can get different directions for the ramp [bitmap-from-procedure [p → [dot p [vector 0.5 0.5]]] 256 256]

5 Changing the vector direction [bitmap-from-procedure [p → [dot p [vector 1 0]]] 256 256] [bitmap-from-procedure [p → [dot p [vector 0 1]]] 256 256]

6 Clipping Why is this one different? The display only has the ability to produce amounts of light in the range 0-255 [bitmap-from-procedure [p → [dot p [vector 1 1]]] 256 256]

7 Constructive laziness It’s bad to keep typing the same arguments over and over again Slows you down Frustrates you Leads to errors So make a new procedure that Just takes the parameter we care about and Fills in the rest for us [define show [procedure → [bitmap-from-procedure procedure 256 256]]] Now we can just say: [show [p → [dot p [vector 1 1]]]]

8 Making it (slightly) more efficient This version calls the vector procedure for each pixel Wasteful Arguments are always the same Same vector is always returned (more or less) We only need to call it once So we can call it once and save it in a local variable [show [p → [dot p [vector 1 1]]]] [show [with vec = [vector 1 1] [p → [dot p vec]]]

9 Making another pattern The magnitude procedure gives the length of the vector passed to it So using it as the painting function for a bitmap gives us A radial pattern That’s black at (0,0) And grows white farther away Like a grayscale ramp, but circular [show magnitude]

10 Question What’s the difference between: magnitude and: [p → [magnitude p]] Nothing; they behave the same Both take a vector as input And return its magnitude as output [show magnitude] [show [p → [magnitude p]]]

11 Shifting it over How do we shift it so that the black part is in the center of the image? We shift the vector we’re taking the magnitude of We use − to shift vectors What vector do we subtract off? It’s a 256×256 image So the center is (128, 128) [show [p → [magnitude [− p [vector 128 128]]]]]

12 Making it brighter Now it’s too dark How do we fix it? Brighten by multiplying Multiplying by 2 Doubles the brightness Although now it clips [show [p → [× 2 [magnitude [− p [vector 128 128]]]]]]

13 White on black Okay, but what if we want it to be white in the center and black on the outside? How do we fix it? Just subtract The brightness computed brightness From 255 (the maximum brightness) [show [p → [− 255 [× 2 [magnitude [− p [vector 128 128]]]]]]]

14 Overview Making shaded images with procedures Making a more elegant language Making textures with noise functions

15 Thinking about it differently We started with a simple pattern (magnitude) We shifted it over We brightened it We inverted it But the code doesn’t make that clear Can we make the code reflect our intentions more clearly? [show [p → [− 255 [× 2 [magnitude [− p [vector 128 128]]]]]]]

16 Making the code clearer We’d like to be able to write the code like this Take the magnitude image Shift it by [vector 128 128] Brighten it And invert it Can we make Meta work this way? [show [invert [brighten 2 [shift [vector 128 128] magnitude]]]]

17 Procedures that operate on whole patterns Let’s call A pattern a procedure that takes a point and returns a brightness A pattern operator a procedure that takes a pattern and returns a new pattern If we had pattern operators For shifting, brightening, and inverting We could write the code much more clearly [shift vector pattern] Makes a new pattern that’s pattern shifted over by vector [brighten level pattern] Makes a new pattern that’s like pattern but with its brightness multiplied by level [invert pattern] Makes a new pattern that’s the same as pattern, but with black exchanged for white

18 Programming with pattern operators Now we can take the magnitude pattern Since magnitude takes a point as input And returns a number So we can use it as a pattern [show magnitude]

19 Programming with pattern operators Now we can take the magnitude pattern Shift it [show [shift [vector 128 128] magnitude]]

20 Programming with pattern operators Now we can take the magnitude pattern Shift it Brighten it [show [brighten 2 [shift [vector 128 128] magnitude]]]

21 Programming with pattern operators Now we can take the magnitude pattern Shift it Brighten it And invert it Now we don’t even need to know that patterns are really procedures [show [invert [brighten 2 [shift [vector 128 128] magnitude]]]]

22 Writing brighten Okay, now let’s write brighten Remember we want to be able to say something like: [brighten 2 [p → [magnitude p]]] And get back something that behaves like: [p → [× 2 [magnitude p]]] ► [define brighten ???]

23 Writing brighten Okay, now let’s write brighten Brighten must Take a brightness level and a pattern as arguments ► [define brighten [level pattern → ???]]

24 Writing brighten Okay, now let’s write brighten Brighten must Take a brightness level and a pattern as arguments Return a new procedure that Takes a point as an argument ► [define brighten [level pattern → [p → ???]]]

25 Writing brighten Okay, now let’s write brighten Brighten must Take a brightness level and a pattern as arguments Return a new procedure that Takes a point as an argument And computes the correct brightness ► [define brighten [level pattern → [p → [× level [pattern p]]]]]

26 Higher-order procedures Brighten is called a “higher-order” procedure It takes a procedure as input And returns a new procedure as a result Procedures that make new procedures are perfectly acceptable And very useful [define brighten [level pattern → [p → [× level [pattern p]]]]] [brighten 2 magnitude] = [p → [× 2 [magnitude p]]] [brighten 3 magntidue] = [p → [× 3 [magnitude p]]] [brighten 3 [brighten 2 magnitude]] = [p → [× 3 [ [p → [× 2 [magnitude p]]] p]] ≈ [p → [× 3 [× 2 [magnitude p]]]]

27 Writing invert Okay, now let’s write invert► [define invert ???]

28 Writing invert Okay, now let’s write invert Invert must Take a a pattern ► [define invert [pattern → ???]]

29 Writing invert Okay, now let’s write invert Invert must Take a a pattern Return a new procedure that Takes a point as an argument ► [define invert [pattern → [p → ???]]]

30 Writing invert Okay, now let’s write invert Invert must Take a a pattern Return a new procedure that Takes a point as an argument And computes the correct brightness ► [define invert [pattern → [p → [− 255 [pattern p]]]]]

31 Writing shift Patterns are procedures So shift is a higher order procedure It takes a procedure as an argument And returns a new procedure as its result ► [define shift ???]

32 Writing shift Patterns are procedures So shift is a higher order procedure It takes a procedure as an argument And returns a new procedure as its result Shift must Take an offset and a pattern as arguments ► [define shift [offset pattern → ???]]

33 Writing shift Patterns are procedures So shift is a higher order procedure It takes a procedure as an argument And returns a new procedure as its result Shift must Take an offset and a pattern as arguments Return a new procedure that Takes a point as an argument ► [define shift [offset pattern → [p → ???]]]

34 Writing shift Patterns are procedures So shift is a higher order procedure It takes a procedure as an argument And returns a new procedure as its result Shift must Take an offset and a pattern as arguments Return a new procedure that Takes a point as an argument And computes the correct brightness ► [define shift [offset pattern → [p → [pattern [− p offset]]]]]

35 Repeated patterns [mod a b] For positive numbers, returns the remainder when dividing a by b When a is negative, returns b minus the remainder This turns out to be just the right thing to make a repeated texture [define replicate [width height pattern → [p → [pattern [point [mod p.X width] [mod p.Y height]]]] ]] [show [replicate 64 64 magnitude]]

36 Repeated patterns [brighten 8 [replicate 64 64 [shift [point 32 32] magnitude]]]] [replicate 64 64 [invert magnitude]]

37 And now, in color … [define colorize [r-pattern g-pattern b-pattern → [p → [color [r-pattern p] [g-pattern p] [b-pattern p]]]]] Takes three grayscale patterns and combines them into a single color pattern

38 Groovy, man [colorize [brighten 8 [replicate 64 64 [shift [point 32 32] magnitude]]] [replicate 64 64 [invert magnitude]] [p → 50]]]

39 Groovy, man [colorize [brighten 8 [replicate 64 64 [shift [point 32 32] magnitude]]] [replicate 64 64 [p → [dot p [point 1 1]]]] [p → 50]]]

40 Overview Making shaded images with procedures Making a more elegant language Making textures with noise functions

41 Spatial frequencies Pictures can be thought of as having harmonic structure Like sound Picture can be thought of as many different frequencies combined We won’t go into this in any detail, but … Frequency corresponds roughly to size Fine detail is high frequency Bigger structures are lower frequeny

42 White noise White noise is a random signal Every pixel (sample) computed using a random number generator Called “white” because it contains equal amounts of all frequencies Not very interesting as a texture ► [show [p → [random-integer 0 255]]]

43 Bandpass noise But now suppose we zoom in between the randomly chosen pixel values And smoothly interpolate between them The result is still a random texture, but it’s missing the very high and very low frequencies [noise point] Interpolated noise Gaussian distribution Result is between -0.7 and 0.7 [show [p → [+ 128 [× 128 [noise [ ⁄ p 30]]]]]]

44 Bandpass noise at different frequences [show [p → [+ 128 [× 128 [noise [ ⁄ p 10]]]]]] [show [p → [+ 128 [× 128 [noise [ ⁄ p 80]]]]]]

45 Summing bandpass noise You can get interesting effects by summing bandpass noise at different frequencies [show [p → [+ 128 [× 128 [+ [noise [ ⁄ p 80]] [noise [ ⁄ p 40]] [noise [ ⁄ p 20]]]]]]]

46 “1/f noise” Important kind of noise Amplitude of frequency f is 1/f Self-similar (like fractals) Zoom in on it and it still looks like itself Approximated using bandpass noise Compute at different scales Sum with weights that vary inversely with frequency Also known as Brown noise (Brownian motion) Turbulence [show [p → [+ 128 [× 128 [+ [noise [ ⁄ p 80]] [ ⁄ [noise [ ⁄ p 40]] 2] [ ⁄ [noise [ ⁄ p 20]] 4]]]]]]

47 Perlin noise Ken Perlin (1985) Technique for approximating 1/f noise using interpolated bandpass noise Built into most graphics cards [turbulence point] Computes a sum of many calls to noise All you really need to understand for this class [show [p → [+ 128 [× 128 [turbulence [ ⁄ p 30]]]]]]

48 Annoying bug/misfeature You have to divide p by some number before calling noise or turbulence The noise function returns 0 for all points whose coordinates are both integers So you have to divide by something to make sure the coordinates are usually not integers

49 The Art of Noise [show [p → [× 255 [turbulence [ ⁄ p 30]]]]] Noise clips on low end [show [p → [abs [× 255 [turbulence [ ⁄ p 30]]]]]] Abs produces abrupt change on low end

50 The Art of Noise [show [with center = [point 128 128] [p → [× 255 [sin [+ [ ⁄ [magnitude [− p center]] 10] [turbulence [ ⁄ p 30]]]]]]] Noise used in input to another function (sin) [show [p → [× 255 [sin [+ [turbulence [ ⁄ p 20]] [dot p [point 0.1 0.1]]]]]]]

51 Extra arguments to turbulence Turbulence works by calling noise at different frequencies and summing You can call turbulence with three extra arguments Drop-off factor Amplitude of the new noise component drops by this factor each iteration Frequency multiplier Frequency get multiplied by this each iteration Iteration count Try playing with the extra arguments The default values are 2, 2, and 4 [show [p → [+ 127 [× 128 [turbulence [ ⁄ p 30] 1.5 2 8]]]]]

52 Extra arguments to turbulence Turbulence works by calling noise at different frequencies and summing You can call turbulence with three extra arguments Drop-off factor Amplitude of the new noise component drops by this factor each iteration Frequency multiplier Frequency get multiplied by this each iteration Iteration count Try playing with the extra arguments The default values are 2, 2, and 4 [show [p → [+ 127 [× 128 [turbulence [ ⁄ p 30] 5 2 8]]]]]

53 The Art of Noise [show [p → [× 256 [turbulence [× 0.001 p.X p.Y]]]]] You can also call noise or turbulence with a number as an argument (rather than a point) [show [p → [× 256 [cos [× 10 [turbulence [ ⁄ p 50]]]]]]]

54 Using the code from today’s lecture Meta is distributed with the code for brighten, invert, etc. To load it and make it available, just type: [using Examples.Painting] Doing it twice won’t hurt anything You only need to do this when you start using Meta But you have to do it over again if you exit Meta and run it again later


Download ppt "Twelve painting with procedures. Overview Making shaded images with procedures Making a more elegant language Making textures with noise functions."

Similar presentations


Ads by Google