Taichi 体素创意比赛

image.png

想法

鱼宝前几天发了个太极引擎的一个小游戏 https://zhuanlan.zhihu.com/p/507362284,我也正好在github看到了胡渊明大神的star的项目,感觉挺有意思的,我也很喜欢体素这种风格,来搞一个玩玩

动手

https://github.com/taichi-dev/voxel-challenge 这就是那个体素渲染器的项目

不得不赞扬一下tachi的安装和配置,很丝滑,两三步就配好了环境,

比赛的限制是体素大小128*128*128,代码不能超过99行

稍微看了下别人已经提交的作品,还是看到一些非常nb的

SuperSodaSea 的钻石矿
image1.jpg

0xrabbyte 的作品
image.png

思考了下,基本上要选用一些容易描述的3维图形来组合成结果,由于光线追踪的效果,我觉得造一个类似赛博朋克风格的城市会有一个不错的效果,红紫灯光交相辉映在繁华的城市,但是实在是只懂得一种感觉,具体怎么造完全没有思路。

最后我选了《Hollow Knight》的小骑士

代码

主要用了三个函数来搭建,
build_cylinder_z造一个轴向为z轴的圆柱,造任意方向的有点难,一下子没想出来,要么就是会浪费好几行,其中symmetric的想法是看到superpics的钢铁侠作品学到的,可以节省不少行数

1
2
3
4
5
6
7
@ti.func
def build_cylinder_z(p, r, height, mat, color, symmetric = 0):
for x, y, z in ti.ndrange((p.x-r, p.x+r+1), (p.y-r, p.y+r+1), (p.z, p.z+height)):
if (x-p.x)*(x-p.x) + (y-p.y)*(y-p.y) < r * r:
scene.set_voxel(ivec3(x, y, z), mat, color)
if symmetric == 1:
scene.set_voxel(ivec3(-x, y, z), mat, color)

build_cuboid造长方体,基本上用于填充形状

1
2
3
4
5
6
@ti.func
def build_cuboid(p, length_x, length_y, length_z, mat, color, symmetric = 0):
for x, y, z in ti.ndrange((p.x, p.x+length_x), (p.y, p.y+length_y), (p.z, p.z+length_z)):
scene.set_voxel(ivec3(x, y, z), mat, color)
if symmetric == 1:
scene.set_voxel(ivec3(-x, y, z), mat, color)

build_line造一条线

1
2
3
4
5
@ti.func
def build_line(point, decrease, level, mat, color):
for i in range(level):
for j in range(abs(decrease)//1+1):
scene.set_voxel(vec3(int(point.x + decrease*i)+j, point.y+i, point.z), mat, color)

具体代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
from scene import Scene; import taichi as ti; from taichi.math import *

scene = Scene(voxel_edges=0, exposure=100)
scene.set_floor(-63/64, (1, 1, 1))
scene.set_background_color((0, 0, 0))
scene.set_directional_light((1, 0.5, 1), 0.1, (0.01, 0.01, 0.01))

@ti.func
def build_cylinder_z(p, r, height, mat, color, symmetric = 0):
for x, y, z in ti.ndrange((p.x-r, p.x+r+1), (p.y-r, p.y+r+1), (p.z, p.z+height)):
if (x-p.x)*(x-p.x) + (y-p.y)*(y-p.y) < r * r:
scene.set_voxel(ivec3(x, y, z), mat, color)
if symmetric == 1:
scene.set_voxel(ivec3(-x, y, z), mat, color)

@ti.func
def build_cuboid(p, length_x, length_y, length_z, mat, color, symmetric = 0):
for x, y, z in ti.ndrange((p.x, p.x+length_x), (p.y, p.y+length_y), (p.z, p.z+length_z)):
scene.set_voxel(ivec3(x, y, z), mat, color)
if symmetric == 1:
scene.set_voxel(ivec3(-x, y, z), mat, color)

@ti.func
def build_line(point, decrease, level, mat, color):
for i in range(level):
for j in range(abs(decrease)//1+1):
scene.set_voxel(vec3(int(point.x + decrease*i)+j, point.y+i, point.z), mat, color)

@ti.kernel
def initialize_voxels():
knight_pos = vec3(0, -44, 0)
white = vec3(1, 1, 1); black = vec3(0, 0, 0); green = vec3(0.1, 0.3, 0.1)
silver = vec3(0.7, 0.7, 0.7)
xaxis = vec3(1, 0, 0); yaxis = vec3(0, 1, 0); zaxis = vec3(0, 0, 1)
# build hair
knight_hair_pos = knight_pos + yaxis * 30
build_cylinder_z(knight_hair_pos - xaxis * 5 - zaxis * 2, 20, 5, 1, white, 1)
build_cylinder_z(knight_hair_pos - xaxis * 5 - zaxis * 2, 15, 5, 0, white, 1)
build_cuboid(knight_hair_pos - xaxis * 7 - yaxis * 10 - zaxis * 2, 15, 31, 5, 0, white)
build_cuboid(knight_hair_pos - xaxis * 40 + yaxis * 10 - zaxis * 2, 81, 21, 5, 0, white)
build_cuboid(knight_hair_pos - xaxis * 21 + yaxis * 8 - zaxis * 2, 2, 5, 9, 0, green, 1)
#build head
knight_head_pos = knight_pos + yaxis * 10
build_cylinder_z(knight_head_pos - xaxis * 10 + yaxis * 5 - zaxis * 6, 5, 12, 1, white, 1)
build_cylinder_z(knight_head_pos - xaxis * 10 - yaxis * 5 - zaxis * 6, 5, 12, 1, white, 1)
build_cuboid(knight_head_pos - xaxis * 10 - yaxis * 10 - zaxis * 6, 21, 21, 12, 1, white)
build_cuboid(knight_head_pos - xaxis * 15 - yaxis * 5 - zaxis * 6, 31, 11, 12, 1, white)

build_cylinder_z(knight_head_pos - xaxis * 8 - yaxis * 2 + zaxis * 4, 4, 2, 1, black, 1)
build_cylinder_z(knight_head_pos - xaxis * 8 - yaxis * 4 + zaxis * 4, 4, 2, 1, black, 1)
#build cloth
knight_body_pos = knight_pos - yaxis * 10
for i in range(-3, 3):
build_cuboid(knight_body_pos - xaxis * 5 + yaxis * 6 + zaxis * i, 13, 2, 1, 1, green)
build_cuboid(knight_body_pos - xaxis * 4 + yaxis * 4 + zaxis * i, 13, 2, 1, 1, green)
build_cuboid(knight_body_pos - xaxis * 3 + yaxis * 2 + zaxis * i, 13, 2, 1, 1, green)
build_cuboid(knight_body_pos - xaxis * 2 - yaxis * 0 + zaxis * i, 13, 2, 1, 1, green)
build_cuboid(knight_body_pos - xaxis * 1 - yaxis * 2 + zaxis * i, 13, 2, 1, 1, green)
build_cuboid(knight_body_pos + xaxis * 2 - yaxis * 3 + zaxis * i, 11, 1, 1, 1, green)
build_cuboid(knight_body_pos + xaxis * 3 - yaxis * 4 + zaxis * i, 10, 1, 1, 1, green)
build_cuboid(knight_body_pos + xaxis * 4 - yaxis * 5 + zaxis * i, 9, 1, 1, 1, green)
build_cuboid(knight_body_pos + xaxis * 5 - yaxis * 6 + zaxis * i, 9, 1, 1, 1, green)
build_line(knight_body_pos + xaxis * 11 - yaxis * 6 + zaxis * i, -0.6, 16, 1, black)
build_line(knight_body_pos + xaxis * 7 - yaxis * 6 + zaxis * i, -0.7, 16, 1, black)

build_cuboid(knight_body_pos - xaxis * 6 + yaxis * 8 + zaxis * i, 13, 2, 2, 1, green)
build_cuboid(knight_body_pos - xaxis * 7 + yaxis * 6 + zaxis * i, 13, 2, 2, 1, green)
build_cuboid(knight_body_pos - xaxis * 8 + yaxis * 4 + zaxis * i, 13, 2, 2, 1, green)
build_cuboid(knight_body_pos - xaxis * 9 + yaxis * 2 + zaxis * i, 13, 2, 2, 1, green)
build_cuboid(knight_body_pos - xaxis * 10 - yaxis * 0 + zaxis * i, 13, 2, 2, 1, green)
build_cuboid(knight_body_pos - xaxis * 11 - yaxis * 2 + zaxis * i, 13, 2, 2, 1, green)
build_cuboid(knight_body_pos - xaxis * 12 - yaxis * 3 + zaxis * i, 13, 1, 2, 1, green)
build_cuboid(knight_body_pos - xaxis * 12 - yaxis * 4 + zaxis * i, 12, 1, 2, 1, green)
build_cuboid(knight_body_pos - xaxis * 13 - yaxis * 5 + zaxis * i, 11, 1, 2, 1, green)
build_cuboid(knight_body_pos - xaxis * 13 - yaxis * 6 + zaxis * i, 9, 1, 2, 1, green)
build_line(knight_body_pos - xaxis * 11 - yaxis * 6 + zaxis * (i+1), 0.6, 16, 1, black)
build_line(knight_body_pos - xaxis * 7 - yaxis * 6 + zaxis * (i+1), 0.7, 16, 1, black)
#build body
build_cuboid(knight_body_pos - xaxis * 5 - yaxis * 10 - zaxis * 2, 11, 20, 4, 1, black)
build_cuboid(knight_body_pos - xaxis * 3 - yaxis * 10 - zaxis * 2, 7, 6, 4, 0, black)
#build sword
for i in range(-5, -2):
build_line(knight_body_pos - xaxis * 5 - yaxis * 5 + zaxis * i, 1.0, 15, 1, silver)
build_line(knight_body_pos - xaxis * 5 - yaxis * 5 + zaxis * i, 1.3, 13, 1, silver)
build_line(knight_body_pos - xaxis * 5 - yaxis * 5 + zaxis * i, 1.5, 14, 1, silver)
build_line(knight_body_pos - xaxis * 5 - yaxis * 5 + zaxis * i, 1.6, 14, 1, silver)
build_line(knight_body_pos - xaxis * 5 - yaxis * 5 + zaxis * i, 2.0, 9, 1, silver)
build_line(knight_body_pos - xaxis * 5 - yaxis * 5 + zaxis * i, 2.5, 8, 1, silver)
build_cuboid(knight_body_pos + xaxis * 7 + yaxis * 2 + zaxis * i, 5, 6, 1, 1, silver)
build_line(knight_body_pos + xaxis * 14 + yaxis * 2 + zaxis * i, -0.6, 8, 1, silver)
scene.set_voxel(knight_body_pos + xaxis * 6 + yaxis * 1 + zaxis * i, 1, silver)

initialize_voxels(); scene.finish()

效果
image.png

代码有点丑,前面画角和头部的时候感觉还有点思路,后面到画衣服的部分只是单纯的拼凑色块了。。。

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2020-2022 d1gg12
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信