1. 开始之前
1.1 学习资源链接
Taichi_THREE 原作者的教程视频:
https://www.bilibili.com/video/av628129594
github 链接:
https://github.com/taichi-dev/taichi_three#how-to-play
- 运行程序之前记得将资源文件夹
assets
分别复制进docs
和example
文件目录下。
1.2 安装
- 运行是基于
Taichi
环境:
python3 -m pip install taichi
- 安装
Taichi THREE
:
python3 -m pip install taichi-tina
具体安装流程见官方文档:
2. 你好,三角形
2.1 坐标系
Tina
使用的右手坐标系:
2.2 创建窗口
import taichi as ti
import tina
# 创建场景对象 scene
scene = tina.Scene()
# 创建一个 SimpleMesh 类的网格对象 mesh ,绑定和设置到 scene
mesh = tina.SimpleMesh()
scene.add_object(mesh)
# 初始化 taichi 的一个 gui 对象
gui = ti.GUI('simple triangle')
# 渲染循环
while gui.running:
# 渲染 scene
scene.render()
# 将获得的像素信息传递给 gui 渲染出来
gui.set_image(scene.img)
gui.show()
得到一个空白窗口:
2.3 设置顶点数据
# 维护顶点数据
# 注意是三角形数组,该处只有一个三角形
verts = np.array([[
[-1, -1, 0], # vertex 1
[ 1, -1, 0], # vertex 2
[ 0, 1, 0], # vertex 3
]])
......
# 渲染循环
while gui.running:
# 绑定和设置 VAO
mesh.set_face_verts(verts)
# 渲染 scene
scene.render()
# 将获得的像素信息传递给 gui 渲染出来
gui.set_image(scene.img)
gui.show()
设置相机,轮询 gui 的鼠标事件:
- 依靠鼠标中键拖动相机视角:
- 滚轮拉近和远离;
- 按
Tab
键切换“透视模式”和“正交模式”
while gui.running:
scene.input(gui)
......
2.4 示例代码
import taichi as ti
import numpy as np
import tina
verts = np.array([[
[-1, -1, 0], # vertex 1
[ 1, -1, 0], # vertex 2
[ 0, 1, 0], # vertex 3
]])
scene = tina.Scene()
mesh = tina.MeshNoCulling(tina.MeshGrid(32))
scene.add_object(mesh)
gui = ti.GUI('Triangle')
while gui.running:
scene.input(gui)
scene.render()
mesh.set_face_verts(verts)
gui.set_image(scene.img)
gui.show()
3. 网格
3.1 简单网格
mesh = tina.MeshNoCulling(tina.MeshGrid(32))
生成一个 32×32 的网格:
调整一下 [16, 16] 顶点的坐标:
mesh.pos[16, 16].z += 0.3
网格发生变化:
可以对网格内的顶点进行遍历:
@ti.kernel
def deform():
for i, j in mesh.pos:
mesh.pos[i, j].z = 0.2 * ti.exp(-0.1 * ((i-16)**2 + (j-16)**2))
4. 粒子
4.1 创建粒子模型
model = tina.SimpleParticles(maxpars=n_particles)
4.2 设置粒子参数
4.2.1 位置参数
位置参数是一个 maxpars x 3
的矩阵:
pos = np.empty((n_particles, 3), dtype=np.float32) # 需要初始化
pos = np.zeros((n_particles, 3), dtype=np.float32)
pos = np.ones((n_particles, 3), dtype=np.float32)
# taichi 中的变量需要进行转换
pos = (ti.Vector.field(3, float, n_particles)).to_numpy()
使用示例
......
# 传递粒子数组的位置
pos = (ti.Vector.field(3, float, n_particles)).to_numpy()
......
# 渲染循环
while gui.running:
......
model.set_particles(pos)
......
4.2.2 半径参数
位置参数是一个 maxpars x 1
的矩阵:
......
# 传递粒子半径的数组
radii = np.ones(n_particles,dtype=np.float32) * 0.02
......
# 渲染循环
while gui.running:
......
model.set_particle_radii(radii)
......
4.2.3 颜色参数
颜色参数是一个 maxpars x 3
的矩阵:
......
# 参数是一个 n_particles x 3 的矩阵
colors = np.ones((n_particles, 3), dtype=np.float32)
# 将颜色的 G 通道置为 0
# (255, 255, 255) => (255, 0, 255)
for icolor in colors:
icolor[1] = 0
......
# 渲染循环
while gui.running:
......
model.set_particle_colors(colors)
......
4.3 给粒子添加 Mesh
4.3.1 参考文档
源码使用的 Marching Cube 算法实现:
《水泡动画模拟(Marching Cubes)》
4.3.2 使用示例
# 开启平滑着色和 SSAO
scene = tina.Scene(smoothing=True,ssao=True)
# 设置分辨率(例中将分辨率提高到了 1.25)
mciso = tina.MCISO((n_grid * 1.25, n_grid * 1.25, n_grid * 1.25))
scene.add_object(mciso)
......
while gui.running:
......
mciso.march(x, w0=2, rad=0, sig=0)
scene.render()
gui.set_image(scene.img)
gui.show()
4.3.3 应用变换
使用网格模型的变换
# 1. 初始化
scene = tina.Scene(smoothing=True,ssao=True)
mciso = tina.MCISO((n_grid * 1.25, n_grid * 1.25, n_grid * 1.25))
mciso = tina.MeshTransform(mciso)
# 2. 绑定
scene.add_object(mciso)
# 3. 设置变换
transformMatrix = tina.translate([-0.5, -0.5, -0.5])
transformMatrix = tina.scale([2., 2., 2.]) @ transformMatrix
mciso.set_transform(transformMatrix)
5. 立方体
5.1 创建立方体模型
volume = tina.SimpleVolume(32)
5.2 加载 .npy 二进制数据
dens = np.load('assets/smoke.npy')
# density:密度
scene = tina.Scene(N=dens.shape[0], taa=True, density=16)
volume = tina.SimpleVolume(N=dens.shape[0])
scene.add_object(volume)
6. 其他基础元件
6.1 球体
6.1.1 创建
scene = tina.Scene()
ball = tina.PrimitiveMesh.sphere()
scene.add_object(ball)
6.1.2 设置
while gui.running:
.......
ball_tran_matrix = tina.scale(ball_radius)
ball_tran_matrix = tina.translate(ball_vel[None].value) @ ball_tran_matrix
ball.set_transform(ball_tran_matrix)
......
6.2 圆柱体
6.2.1 创建
scene = tina.Scene()
bucket = tina.PrimitiveMesh.cylinder()
scene.add_object(bucket)
6.2.2 设置
while gui.running:
.......
bucket_tran_matrix = tina.scale(bucket_radius)
bucket_tran_matrix = tina.translate(bucket_vel[None].value) @ bucket_tran_matrix
bucket.set_transform(bucket_tran_matrix)
......
7. 模型
7.1 加载模型
model = tina.MeshModel('assets/monkey.obj')
scene.add_object(model)
可以增加模型载入的数量:
scene = tina.Scene(maxfaces=2**18)
7.2 材质
7.2.1 初始化材质对象
roughness = tina.Param(float, initial=0)#.15)
metallic = tina.Param(float, initial=0)#.25)
material = tina.PBR(metallic=metallic, roughness=roughness)
或者使用
material = tina.CookTorrance(roughness=0.1, fresnel=0.9)
参 数 | 含 义 |
---|---|
roughness | 粗糙度 |
fresnel | 菲尼尔反射效应:在掠射角的角度,光照结果会更亮一些 |
7.2.2 示例代码
model = tina.MeshModel('assets/monkey.obj')
material = tina.CookTorrance(roughness=0.1, fresnel=0.9)
scene.add_object(model, material)
7.3 光源
scene.lighting.clear_lights()
# 添加点光源(同时可以设置光的颜色)
scene.lighting.add_light(pos=[0, 1, 0], color=[1, 0, 0])
# 添加平行光源
scene.lighting.add_light(dir=[1, 1, 0])
# 设置环境光源
scene.lighting.set_ambient_light(color=[0.2, 0.1, 0.1])
8. 变换
8.1 激活变换
网格模型 :
model = tina.MeshTransform(model)
粒子模型 :
model = tina.ParsTransform(model)
8.2 构造变换矩阵
《欧拉角,四元数,旋转矩阵相互转化》
# 设置一个位移变换
transformMatrix = tina.translate([-0.5, -0.5, -0.5])
# 再进行一个缩放:调整的是整个粒子模型的大小
# 注意向量是列向量表示,矩阵需要左乘添加变换
transformMatrix = tina.scale([2., 2., 2.]) @ transformMatrix
# 欧拉角
transformMatrix = tina.eularXYZ([0., 2., 0.]) @ transformMatrix
# 四元数
transformMatrix = tina.quaternion([1., 0., 0., 0.]) @ transformMatrix
......
8.3 设置变换
网格模型 :
# 设置网格变换
model.set_transform(transformMatrix)
粒子模型 :
# 设置粒子变换(第二个参数是 scale :调整的是单个粒子的大小)
model.set_transform(transformMatrix, 1)
9. 其他基础功能
9.1 面剔除
Tina
是默认是开启面剔除功能的,所以需要三角形两面都显示的情况时,可以在“创建场景对象”的时候声明:
scene = tina.Scene(culling=False)
但是这种方式获得的三角形反面法线是相反的,这时推荐渲染正反两个三角形面:
verts = np.array([[
[-1, -1, 0], # vertex 1
[ 1, -1, 0], # vertex 2
[ 0, 1, 0], # vertex 3
],[
[ 1, -1, 0], # vertex 1
[-1, -1, 0], # vertex 2
[ 0, 1, 0], # vertex 3
]])
同时,可以在“创建网格对象”的阶段声明以下语句,来取消剔除功能:
mesh = tina.MeshNoCulling(tina.SimpleMesh())
9.2 抗锯齿
可以在“创建场景对象”阶段开启 TAA 选项(静止时按帧周期性变动采样点):
scene = tina.Scene(taa=True)
9.3 平滑着色
可以在“创建场景对象”阶段开启光滑着色,尤其适合在网格中使用:
scene = tina.Scene(smoothing=True)
同时也可以在“创建网格对象”的阶段取消平滑着色,锐化法线信息:
mesh = tina.MeshFlatNormal(tina.MeshNoCulling(tina.MeshGrid(32)))
9.4 屏幕空间环境光遮罩
scene = tina.Scene(ssao=True)
9.5 天空盒
9.5.1 激活天空盒
scene = tina.Scene(smoothing=True, taa=True, ibl=True)
9.5.2 设置天空盒
目前暂时需要在源码 raster.py
(Line:30,31) 中更改:
skybox = tina.Skybox(skybox.resolution).cook_from(skybox)
# skybox = tina.Skybox('assets/skybox.jpg', cubic=True)
通过注释进行切换,选择使用缺省值或者使用路径中的天空盒素材
10. 资源导出
10.1 导出图片
flame = 0
while gui.running:
scene.input(gui)
......
scene.render()
gui.set_image(scene.img)
......
filename = 'OutPng\\output_png_{:04d}.png'.format(flame)
ti.imwrite(scene.img, filename)
flame += 1
......
gui.show()
Note :
- 使用
gui.show(filename)
无法正常导出。