下面是生成三维烟雾的一段代码,请问在已经确定粒子位置且设置粒子所在网格的烟雾密度值之后,怎么在GGUI中把烟雾加进去(只能显示粒子,烟雾不知道怎么显示)

import taichi as ti
import numpy as np

ti.init(arch=ti.gpu)

参数设置

dim = 3
n = 128 # 空间网格数
n_particles = 51200 # 粒子数
dt = 1e-3 # 时间步长
alpha = 0.5 # 速度场更新系数
dx = 1.0 / n # 空间步长(网格尺寸)
inv_dx = 1.0 / dx # 空间步长的倒数
temp_decay = 0.95 # 烟雾温度衰减因子
cavas_color = (0, 0, 0) # 画布颜色

定义 Taichi 字段

smoke_density = ti.Vector.field(dim, dtype=float, shape=(n, n, n)) # 烟雾密度
temperature = ti.field(dtype=float, shape=(n, n, n)) # 温度场
velocity = ti.Vector.field(dim, dtype=float, shape=(n, n, n)) # 速度场
new_velocity = ti.Vector.field(dim, dtype=float, shape=(n, n, n)) # 新速度场
pressure = ti.field(dtype=float, shape=(n, n, n)) # 压力场
particle_positions = ti.Vector.field(dim, dtype=float, shape=n_particles) # 粒子位置,有n*1个格,每格含一个三维向量
particle_velocities = ti.Vector.field(dim, dtype=float, shape=n_particles) # 粒子速度

@ti.kernel
def init_smoke():
for i, j, k in smoke:
smoke_density[i, j, k] = (0.0, 0.0, 0.0)
temperature[i, j, k] = 23.0
velocity[i, j, k] = ti.Vector([0.0, 0.0, 0.0]) # 整个烟雾场的速度
new_velocity[i, j, k] = ti.Vector([0.0, 0.0, 0.0])
pressure[i, j, k] = 0.0

for p in range(n_particles):
    particle_positions[p] = ti.Vector([ti.random(), ti.random(), ti.random()])  # 粒子位置在0-1中随机
    particle_velocities[p] = ti.Vector([0, 0, 0])

@ti.kernel
def step_smoke():
# 计算速度场
for i, j, k in velocity:
vel = velocity[i, j, k]
new_velocity[i, j, k] = vel - dt * alpha * pressure[i, j, k] / dx

# 更新速度场
for i, j, k in velocity:
    velocity[i, j, k] = new_velocity[i, j, k]

# 更新烟雾
for i, j, k in smoke:
    smoke[i, j, k] = ti.max(smoke[i, j, k] * temp_decay, 0.0)

# 更新粒子位置
for n in range(n_particles):
    p_pos = particle_positions[n]
    p_vel = particle_velocities[n]
    new_p_pos = p_pos + dt * p_vel
    new_p_vel = p_vel + dt * velocity[int(new_p_pos[0] * inv_dx), int(new_p_pos[1] * inv_dx), int(new_p_pos[2] * inv_dx)]
    particle_positions[n] = new_p_pos
    particle_velocities[n] = new_p_vel

    int_grid_x = ti.floor(particle_positions[n].x / dx)  # 获取每个粒子所处的网格
    int_grid_y = ti.floor(particle_positions[n].y / dx)
    int_grid_z = ti.floor(particle_positions[n].z / dx)
    smoke_density[int(int_grid_x), int(int_grid_y), int(int_grid_z)] = [0.3, 0.3, 0.3]  # 把粒子所在的网格的颜色设置为定值

初始化

init_smoke()

window = ti.ui.Window(“Test for 3D_smoke”, (768, 768))
cavas = window.get_canvas()
cavas.set_background_color(cavas_color) # 画布颜色
scene = ti.ui.Scene()
camera = ti.ui.Camera()
camera.position(2, 2, 1)
while window.running:
step_smoke()
camera.track_user_inputs(window, movement_speed=0.003, hold_key=ti.ui.RMB)
scene.set_camera(camera)
scene.ambient_light((0.8, 0.8, 0.8))
scene.point_light(pos=(0.5, 1.5, 1.5), color=(1, 1, 1))
scene.particles(particle_positions, color= (0.5, 0.5, 0.5), radius=0.000001)
cavas.scene(scene)
window.show()

你想要的是渲染出烟雾的效果,而不只是显示一个个小球?那可能需要自己手写体渲染了,ggui 是不会自动做这些的。。

现在已经随机生成了一些粒子并获取它们的位置,我的想法是直接对每一个粒子所在的网格体设置颜色(RGB),这样的话是需要手写渲染体吗?需要的话有类似的代码让我参考吗? :grinning:

你可以去 shadertoy 上搜一下 volumetric rendering 的例子。
体渲染是比较耗时间的,会严重影响你的帧率。