code / hill-noise

Lines837 Lua675 GLSL103 Markdown59
(199 lines)
1 local Noise = require "hill_noise"
2 local Histogram = require 'histogram'
3 local DRAW_RES = love.window.toPixels(4)
4 local SCALE = 100
5 local DRAW_HISTOGRAMS = false
6 local DRAW_GRADIENTS = false
8 local decay = function(x) return .15^x end
9 local n1,g1 = Noise.make1d{resolution=5, distribution=decay, seed=1}
10 local n2,g2 = Noise.make2d{resolution=7, distribution=decay, seed=1}
11 local n3,g3 = Noise.make3d{resolution=9, distribution=decay, seed=1}
12 local s1,s1g = Noise.make1dShader{resolution=10, distribution=decay, seed=1, draw_outline=true}
13 local s2,s2g = Noise.make2dShader{resolution=15, distribution=decay, seed=1}
14 local s3,s3g = Noise.make3dShader{resolution=20, distribution=decay, seed=1}
16 lg = love.graphics
17 W,H = lg.getDimensions()
18 local cw,ch = W/2,H/3
19 local canv = lg.newCanvas(cw,ch)
20 local font = lg.newFont(love.window.toPixels(24))
22 function love.load()
23 xOffset = 0
24 yOffset = 0
25 t0 = love.timer.getTime()
26 love.mouse.setCursor(love.mouse.getSystemCursor("hand"))
27 end
29 function love.mousepressed()
30 love.mouse.setCursor(love.mouse.getSystemCursor("sizeall"))
31 end
33 function love.mousereleased()
34 love.mouse.setCursor(love.mouse.getSystemCursor("hand"))
35 end
37 function love.draw()
38 if DRAW_HISTOGRAMS then
39 lg.setColor(0,100,0)
40 histogram1:draw()
41 lg.setColor(0,0,150)
42 histogram2:draw()
43 lg.setColor(125,0,0)
44 histogram3:draw()
45 end
47 lg.setColor(255,255,255)
48 lg.setLineWidth(love.window.toPixels(2))
49 lg.setLineJoin("none")
50 local p1 = {}
51 for x=0,W-H/3,DRAW_RES do
52 table.insert(p1,x)
53 table.insert(p1,n1(x/SCALE+xOffset)*H/3)
54 end
55 lg.line(p1)
56 do -- Draw tangent line
57 local mx = love.mouse.getX()
58 local y, dydx = n1(mx/SCALE + xOffset), g1(mx/SCALE + xOffset)
59 y = y * H/3
60 dydx = dydx * H/3 / SCALE
61 local h = 50/math.sqrt(1+dydx^2)
62 lg.setColor(255,255,0)
63 lg.line(mx-h, y - h*dydx, mx + h, y + h*dydx)
64 lg.setColor(255,255,255)
65 end
67 local p2 = {}
68 local t = love.timer.getTime()-t0
69 for x=0,W-H/3,DRAW_RES do
70 table.insert(p2,x)
71 table.insert(p2,(1+n2(x/SCALE+xOffset,t))*H/3)
72 end
73 lg.line(p2)
74 do -- Draw tangent line
75 local mx = love.mouse.getX()
76 local y = n2(mx/SCALE + xOffset, t)
77 local dydx, dydz = g2(mx/SCALE + xOffset, t)
78 y = (1+y) * H/3
79 dydx = dydx * H/3 / SCALE
80 local h = 50/math.sqrt(1+dydx^2)
81 lg.setColor(255,255,0)
82 lg.line(mx-h, y - h*dydx, mx + h, y + h*dydx)
83 lg.setColor(255,255,255)
84 end
86 for y=0,H/6*1.2,2*DRAW_RES do
87 local p3 = {}
88 for x=0,W-H/3,DRAW_RES do
89 table.insert(p3,x)
90 table.insert(p3,2/3*H+H/6*(1-n3(x/SCALE+xOffset,y/SCALE+yOffset,t))+y)
91 end
92 lg.line(p3)
93 end
94 for x=-H/6,W-H/3,DRAW_RES*2 do
95 local p3 = {}
96 local slant = .5
97 for y=0,H/6*1.2,2*DRAW_RES do
98 local x2 = x + slant*y
99 if x2 < -2*DRAW_RES then goto continue end
100 table.insert(p3,x2)
101 table.insert(p3,2/3*H+H/6*(1-n3(x2/SCALE+xOffset,y/SCALE+yOffset,t))+y)
102 if x2 > W/2 then break end
103 ::continue::
104 end
105 if #p3 > 2 then
106 lg.line(p3)
107 end
108 end
109 --[[ 3D tangent lines not working
110 do -- Draw tangent line
111 local mx = love.mouse.getX()
112 local my = love.mouse.getY()/2 - 1/3*H
113 if my < 1/6*H then my = 1/6*H end
114 mx = mx + .5*my
115 local y = 2/3*H+H/6*(1-n3(mx/SCALE + xOffset, my/SCALE + yOffset, t))+my
116 local dydx, dydz, _ = g3(mx/SCALE + xOffset, my/SCALE + yOffset, t)
117 dydx = dydx * H/3 / SCALE
118 local h = 50/math.sqrt(1+dydx^2)
119 lg.setColor(255,255,0)
120 lg.line(mx-h, y - h*dydx, mx + h, y + h*dydx)
121 lg.setColor(255,255,255)
122 end
125 local shader
126 shader = DRAW_GRADIENTS and s1g or s1
127 lg.setShader(shader)
128 shader:send("range_min", xOffset)
129 shader:send("range_max", xOffset+2*cw/SCALE)
130 lg.draw(canv,W-cw,0)
131 shader = DRAW_GRADIENTS and s2g or s2
132 lg.setShader(shader)
133 shader:send("range_min", {xOffset,yOffset})
134 shader:send("range_max", {xOffset+2*cw/SCALE,yOffset+2*ch/SCALE})
135 lg.draw(canv,W-cw,ch)
136 shader = DRAW_GRADIENTS and s3g or s3
137 lg.setShader(shader)
138 shader:send("range_min", {xOffset,yOffset})
139 shader:send("range_max", {xOffset+2*cw/SCALE,yOffset+2*ch/SCALE})
140 shader:send('z', t)
141 lg.draw(canv,W-cw,2*ch)
142 lg.setShader(nil)
144 lg.setColor(0,0,0,175)
145 lg.rectangle('fill',0,0,W,font:getHeight()+love.window.toPixels(5))
146 lg.rectangle('fill',0,H/3,W,font:getHeight()+love.window.toPixels(5))
147 lg.rectangle('fill',0,2*H/3,W,font:getHeight()+love.window.toPixels(5))
148 lg.setColor(255,230,50)
149 lg.setFont(font)
150 lg.printf("1D_Noise(x)", 5,5, W)
151 lg.printf("2D_Noise(x,time)", 5,5+H/3, W)
152 lg.printf("3D_Noise(x,y,time)", 5,5+2*H/3, W)
153 lg.printf("1D_Noise_Shader(x)", 0,5, W-5, 'right')
154 lg.printf("2D_Noise_Shader(x,y)", 0,5+H/3, W-5, 'right')
155 lg.printf("3D_Noise_Shader(x,y,time)", 0,5+2*H/3, W-5, 'right')
157 lg.setColor(20,200,20)
158 lg.printf("'h': toggle histograms, 'g': toggle gradients", 5,5, W-5, 'center')
159 end
161 function love.update(dt)
162 local key = love.keyboard.isDown
163 local dx = 400/SCALE*dt*((key('right') and 1 or 0) + (key('left') and -1 or 0))
164 local dy = 400/SCALE*dt*((key('down') and 1 or 0) + (key('up') and -1 or 0))
165 xOffset = xOffset + dx
166 yOffset = yOffset + dy
167 end
169 function love.keypressed(key)
170 if key == 'escape' then love.event.quit() end
171 if key == 'r' then love.load() end
172 if key == 'g' then
173 DRAW_GRADIENTS = not DRAW_GRADIENTS
174 end
175 if key == 'h' then
176 DRAW_HISTOGRAMS = not DRAW_HISTOGRAMS
177 if DRAW_HISTOGRAMS and not histogram1 then
178 local data1,data2,data3 = {},{},{}
179 for i=1,100000 do
180 local x = math.random()*100000
181 local y = math.random()*100000
182 local z = math.random()*100000
183 table.insert(data1, n1(x))
184 table.insert(data2, n2(x,y))
185 table.insert(data3, n3(x,y,z))
186 end
187 histogram1 = Histogram:fromList(data1,{pos={x=0,y=0},size={x=W/4,y=H/3},xmin=0,xmax=1,numBuckets=30})
188 histogram2 = Histogram:fromList(data2,{pos={x=0,y=H/3},size={x=W/4,y=H/3},xmin=0,xmax=1,numBuckets=30})
189 histogram3 = Histogram:fromList(data3,{pos={x=0,y=2*H/3},size={x=W/4,y=H/3},xmin=0,xmax=1,numBuckets=30})
190 end
191 end
192 end
194 function love.mousemoved(x,y,dx,dy)
195 if love.mouse.isDown(1) then
196 xOffset = xOffset - dx/SCALE
197 yOffset = yOffset - dy/SCALE
198 end
199 end