【作业5】视角持续拉近的谢尔宾斯基地毯

作业5

作业描述

参考维基百科,写了一个视角持续拉近的谢尔宾斯基地毯。

效果展示

video
上图的最初版本里,最小的那一层方块在视角拉近的时候显得很不自然,然后我尝试了一些奇怪的办法,都没有什么好效果,最后试了下加了一个渐变效果,效果如下图,感觉自然多了,而且很有助眠效果哈哈。
video

小感想

程序动画真有趣,之后准备再写一个能生成类似STG游戏里的弹幕的taichi程序。

代码

# reference ==>
# https://zh.wikipedia.org/wiki/%E8%B0%A2%E5%B0%94%E5%AE%BE%E6%96%AF%E5%9F%BA%E5%9C%B0%E6%AF%AF
import taichi as ti
import handy_shader_functions as hsf

ti.init(arch=ti.cuda)

deepth = 5
res_x = 3**deepth
res_y = 3**deepth
pixels_1 = ti.Vector.field(3, ti.f32, shape=(res_x, res_y))
pixels_2 = ti.Vector.field(3, ti.f32, shape=(res_x, res_y))
flags_1 = ti.field(ti.i32, shape=(res_x, res_y))
flags_2 = ti.field(ti.i32, shape=(res_x, res_y))


@ti.func
def fill(x, y, W, H, deepth):
    c = 0
    for i in range(deepth):
        if x < 1 or W < 1 or H < 1:
            break
        x_ = (3 * x) // W
        y_ = (3 * y) // H
        if x_ == 1 and y_ == 1:
            c = 1 + i
            break
        x -= (x_ * W) // 3
        y -= (y_ * H) // 3
        W = W // 3
        H = H // 3
    return c


@ti.func
def zoom_in(t: ti.f32):
    scale = ti.pow(1 / 3, (t % 120) / 120)
    for i, j in pixels_2:
        flags_2[i, j] = flags_1[i, j]
        if scale < 1:
            i_ = ti.floor(scale * i)
            j_ = ti.floor(scale * j)
            flags_2[i, j] = flags_1[i_, j_]


@ti.kernel
def render(t: ti.f32):
    # draw something on your canvas
    white = ti.Vector([1.0, 1.0, 1.0])
    black = ti.Vector([0.0, 0.0, 0.0])
    for i, j in flags_1:
        flags_1[i, j] = fill(i, j, res_x, res_y, deepth)
        pixels_1[i, j] = white
        pixels_2[i, j] = white
    zoom_in(t)
    for i, j in flags_2:
        if flags_2[i, j] > 0:
            pixels_2[i, j] = black
        if flags_2[i, j] == deepth:
            gray = 2 - ti.pow(2, (t % 120) / 120)
            pixels_2[i, j] = ti.Vector([gray, gray, gray])


gui = ti.GUI("Canvas", res=(res_x, res_y))

if __name__ == '__main__':
    for i in range(120):
        t = i * 1.0
        render(t)
        gui.set_image(pixels_2)
        filename = f'./results/frame_{i:05d}.png'  # create filename with suffix png
        print(f'Frame {i} is recorded in {filename}')
        gui.show(filename)  # export and show in GUI
8 个赞

已提交至github

:clap: :clap: :clap: