【小作业】Reaction-Diffusion

作业1

作业描述

实现了一个 reaction-diffusion 动画

开发和运行环境

[Taichi] version 0.8.8, llvm 10.0.0, commit 7bae9c77, linux, python 3.8.10

效果展示

代码链接

import numpy as np
import taichi as ti
ti.init(arch=ti.gpu)

W, H = 640, 360
pixels = ti.Vector.field(3, ti.f32, shape=(W, H))
#Du, Dv, feed, kill = 0.160, 0.080, 0.060, 0.062
Du, Dv, feed, kill = 0.210, 0.105, 0.018, 0.051
# set uv grid
uv_grid = np.zeros((W, H, 4), dtype=np.float32)
uv_grid[:, :, 0] = 1.0
rand_rows = np.random.choice(range(W), 50)
rand_cols = np.random.choice(range(H), 50)
uv_grid[rand_rows, rand_cols, 1] = 1.0
uv = ti.Vector.field(2, ti.f32, shape=(W, H))
uv.from_numpy(uv_grid)
# set palette
palette = ti.Vector.field(4, ti.f32, shape=(5,))
palette[0] = [0, 0, 0, 0]  # [0.0, 0.0, 0.0, 0.31372549]
palette[1] = [0, 1, 0, 0.2]  # [1.0, 0.1843, 0.53333333, 0.376470588]
palette[2] = [1.0, 1.0, 0.0, 0.2078431373]  # [0.854901961, 1.0, 0.5333333, 0.3882353]
palette[3] = [1, 0, 0, 0.4]  # [0.376471, 1.0, 0.47843, 0.39215686]
palette[4] = [1.0, 1.0, 1.0, 0.6]

@ti.func
def vec4_from_vec3(v):
    return ti.Vector([v[0], v[1], v[2]])

@ti.func
def mix(a, b, t):
    return a * (1.0 - t) + b * t

@ti.func
def clamp(v, v_min, v_max):
    return ti.max(ti.min(v, v_max), v_min)

@ti.kernel
def compute():
    for i, j in uv:
        cen = uv[i, j]
        lapl = uv[i + 1, j] + uv[i, j + 1] + uv[i - 1, j] +  uv[i, j - 1] - 4.0 * cen
        du = Du * lapl[0] - cen[0] * cen[1] * cen[1] + feed * (1 - cen[0])
        dv = Dv * lapl[1] + cen[0] * cen[1] * cen[1] - (feed + kill) * cen[1]
        val = cen + 1. * ti.Vector([du, dv])
        uv[i, j] = val

@ti.kernel
def render():
    for i, j in pixels:
        value = uv[i, j][1]
        color = ti.Vector([0., 0., 0.])
        if value <= palette[0][3]:
            color = vec4_from_vec3(palette[0])

        for k in ti.ndrange(4):
            c0 = palette[k]
            c1 = palette[k + 1]
            if c0[3] < value < c1[3]:
                a = (value - c0[3]) / (c1[3] - c0[3])
                color = mix(vec4_from_vec3(c0), vec4_from_vec3(c1), a)

        pixels[i, j] = color


gui = ti.GUI("Reaction-Diffusion", res=(W, H))
for i in range(1000000):
    compute()
    render()
    gui.set_image(pixels)
    gui.show()

4 个赞