> Create some graphics on the boundary of math and art
You can sample a function row by row and write the result to an image file,
write multiple files and you can create an animation. Or go beyond that and
write a ray tracer.
It all depends op your goal.
#renders 'frames' images, use ffmpeg to create an animation.
#ffmpeg -r 30 -f image2 -s 800x400 -i kawachi_%04d.png -vcodec libx264 -crf
15 -preset veryslow -pix_fmt yuv420p kawachi.mp4
import math, times, strformat
import pixie
const
Width = 800
Height = 400
proc lerp(t, minin, maxin, minout, maxout: float):float {.inline.}=
result = ((t - minin) / (maxin - minin)) * (maxout - minout) + minout
proc shuheiKawachiMod (x: float, y: float, funcVA: varargs[float]): float
{.inline.}=
result = (((cos(x) * cos(y) + cos(( sqrt(funcVA[0]) * x - y) / funcVA[1])
*
cos((x + sqrt(funcVA[0]) * y) / funcVA[1]) + cos(( sqrt(funcVA[0]) * x +
y) / funcVA[1]) *
cos((x - sqrt(funcVA[0]) * y) / funcVA[1])) / 3 ) + 1) #division by 3 to
bring it in the [-1,1] range
result = (result mod (1.0 / funcVA[2])) * funcVA[2]
proc renderXYFuncAA(
function: proc,
funcVA: varargs[float],
viewPort: (Vec2, Vec2),
scale: float,
imgInd: int
): void =
let image = newImage(Width, Height)
let xStep = lerp(1.0, 0.0, image.width.float, viewPort[0].x,
viewPort[1].x) * scale
let yStep = lerp(1.0, 0.0, image.height.float, viewPort[0].y,
viewPort[1].y) * scale
let xHStep = xStep / 2.0
let yHStep = yStep / 2.0
for j in 0..image.height:
for i in 0..image.width:
var val: float
for m in -1..1:
let y = (j.float * yStep) + (m.float * yHStep)
for n in -1..1:
let x = (i.float * yStep) + (n.float * xHStep)
val += function(x, y, funcVA)
val = val / 9
image[i,j] = color(val, val, val)
writeFile(image, fmt"kawachi_{imgInd:0>4}.png")
let
frames = 20 #1200
modStep = TAU / frames.float
for i in 0..<frames:
let
step = modStep * i.float
renderXYFuncAA(
shuheiKawachiMod,
[TAU, 1.50, step],
(vec2(0.0, 0.0), vec2(TAU, PI)),
6.0,
i
)
Run