eighteen painting with procedures. review [bitmap-from-procedure procedure width height] returns a...

51
eighteen painting with procedures

Post on 21-Dec-2015

222 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

eighteen

painting with procedures

Page 2: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Review

[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 object with the coordinates Procedure returns a color object (color image) or an integer

(grayscale image)

[point x y] Returns a point object with the specified coordinates

[point-x p] or: p.X[point-y p] or: p.Y Returns x (or y) coordinate of p

Page 3: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Review

[color name] Returns color with the specified name

[color red green blue] Returns color with the specified amounts of red, green, and blue

light Arguments should be 0-255

[red c] or c.R[green c] or c.G[blue c] or c.B Returns the amount of red/green/blue light in the color c

Page 4: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

New vector operations

[+ point point], [− point point] Returns the sum/difference of two points (vectors) Sum shifts the first point over by the amount of the second point (or vice-versa) Difference shifts the first one back

[× number point], [ ⁄ number point] Returns point stretched/shrunk by a factor of number

[rotate-vector point angle][rotate-vector-degrees point angle]

Rotates the vector about the origin [magnitude point]

Returns the length of the vector point [dot point point]

Returns the dot-product of one point onto the other aka the projection, aka the inner product, aka the scalar product

Page 5: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

New color operations

[+ color color] Adds together the light of the two colors to form a new color

[× number color], [ ⁄ number color] Brightens/dims color by the factor number

[intensity color] Returns the total amount of light in the color from 0-255

[gray intensity] Returns a neutral gray color with the specified intensity (0-255)

Page 6: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 point in the dot-product, we can get different directions for the ramp

[bitmap-from-procedure[p → [dot p [point 0.5 0.5]]]256256]

Page 7: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Changing the vector direction

[bitmap-from-procedure[p → [dot p [point 1 0]]]256256]

[bitmap-from-procedure[p → [dot p [point 0 1]]]256256]

Page 8: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 [point 1 1]]]256256]

Page 9: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 [point 1 1]]]]

Page 10: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Making it (slightly) more efficient

This version calls the point procedure for each pixel

Wasteful Arguments are always the

same Same point 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 [point 1 1]]]]

[show [with vec = [point 1 1] [p → [dot p vec]]]

Page 11: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Getting cutesy (for advanced hackers)

[curry proc args …] Makes a new procedure that calls

proc with args followed by any arguments passed to the new procedure

[curry > 7] is the same as [n → [> 7 n]]

[curry-right proc args …] Same, but args go at the end

[curry-right > 7] is [n → [> n 7]]

Currying is a very useful technique Some languages (ML, Haskell)

automatically curry procedures Named after Haskell B. Curry So is the Haskell language

[show [curry dot [point 1 1]]]

Page 12: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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]

Page 13: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 [point 128 128]]]]]

Page 14: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 [point 128 128]]]]]

Page 15: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 [point 128 128]]]]]

Page 16: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 look like that Can we make it more

readable?

[show [p → [− 255 [× 2 [magnitude [− p [point 128 128]]]]]

Page 17: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 point pattern] Makes a new pattern that’s

pattern shifted over by point [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

Page 18: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Programming with pattern operators

Now we can take the magnitude pattern

[show magnitude]

Page 19: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Programming with pattern operators

Now we can take the magnitude pattern

Shift it

[show [shift [point 128 128] magnitude]]

Page 20: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Programming with pattern operators

Now we can take the magnitude pattern

Shift it Brighten it

[show [brighten 2 [shift [point 128 128] magnitude]]]

Page 21: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 [point 128 128] magnitude]]]]

Page 22: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 ???]

Page 23: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 → ???]]

Page 24: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 → ???]]]

Page 25: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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]]]]]

Page 26: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Writing brighten

Okay, now let’s write brighten ► [define brighten ???]

Page 27: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Writing brighten

Okay, now let’s write brighten

Brighten must Take a brightness level and a

pattern as arguments

► [define brighten [level pattern → ???]]

Page 28: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 → ???]]]

Page 29: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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]]]]]

Page 30: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Writing invert

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

Page 31: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Writing invert

Okay, now let’s write invert

Invert must Take a a pattern

► [define invert [pattern → ???]]

Page 32: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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 → ???]]]

Page 33: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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]]]]]

Page 34: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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]]

Page 35: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Repeated patterns

[brighten 8 [replicate 64 64 [shift [point 32 32] magnitude]]]]

[replicate 64 64 [invert magnitude]]

Page 36: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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

Page 37: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Groovy, man

[colorize [brighten 8 [replicate 64 64 [shift [point 32 32] magnitude]]] [replicate 64 64 [invert magnitude]]

[p → 50]]]

Page 38: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Groovy, man

[colorize [brighten 8 [replicate 64 64 [shift [point 32 32] magnitude]]] [replicate 64 64 [curry dot [point 1 1]]]

[p → 50]]]

Page 39: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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

Page 40: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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]]]

Page 41: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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]]]]]]

Page 42: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Bandpass noise at different frequences

[show [p → [+ 128 [× 128 [noise [ ⁄ p 10]]]]]]

[show [p → [+ 128 [× 128 [noise [ ⁄ p 80]]]]]]

Page 43: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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]]]]]]]

Page 44: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

1/f noise

Important kind of noise Amplitude of frequency is

inversely proportional to the frequency

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]]]]]]

Page 45: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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]]]]]]

Page 46: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

Caveat

You have to divide p by some number before calling noise or turbulence

I haven’t wrapped my head around Perlin’s old C code yet, but 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 Could well be my fault

Page 47: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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

Page 48: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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]]]]]]]

Page 49: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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]]]]]

Page 50: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

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]]]]]

Page 51: Eighteen painting with procedures. Review [bitmap-from-procedure procedure width height] Returns a bitmap width pixels by height pixels Obtains colors

The Art of Noise

[show[p → [× 256

[turbulence [× 0.001 p.X p.Y]]]]]

turbulence with a numeric argument

[show[p → [× 256 [cos [× 10 [turbulence [ ⁄ p 50]]]]]]]