用Taichi(python)实现星际穿越特效

import taichi as ti
import math
ti.init(arch=ti.gpu)

#
fps=60.0
dt=1.0/fps

#首先设置一个窗口
res = (1920,1280)
pixels = ti.Vector.field(n=3,dtype=float,shape=res)#设置像素的参数

#world space varibles
grid_size = 100
z_near,z_far = 200,3200
N=(res[0]//grid_size,res[1]//grid_size,(z_far-z_near)//grid_size)
pos=ti.Vector.field(n=3,dtype=float,shape=N)
color=ti.Vector.field(n=3,dtype=float,shape=N)
vel=ti.Vector.field(n=3,dtype=float,shape=())

#camera related varibles
fov=120
tan_half_fov=math.tan((fov/360)*math.pi)

@ti.func
def rand3():
    return ti.Vector([ti.random(),ti.random(),ti.random()])

@ti.func
def spawn(I):
    pos[I]=(I+rand3())*grid_size
    color[I]=rand3()+ti.Vector([1.0,2.0,1.0])
    
#init the stars
@ti.kernel
def init():
    for i,j,k in pos:
        I=ti.Vector([i,j,k])
        spawn(I)

#step
@ti.kernel
def step():
    for I in ti.grouped(pos):
        pos[I] += vel[None] * dt
        if pos[I].z < z_near:
            pos[I].z+=z_far-z_near

#projections
@ti.func
def project(pos_3d):
    center=ti.Vector(res)/2
    w=tan_half_fov*pos_3d.z
    rel_pos=(ti.Vector([pos_3d.x,pos_3d.y])-center)/w
    screen_space_pos=rel_pos*res[1]+center
    return screen_space_pos

#画
@ti.func
def draw_particle(c,rad,color):
    x_range=(ti.max(int(c.x-rad-1),0)),ti.min(int(c.x+rad+1),res[0])#使得遍历元素少了
    y_range=(ti.max(int(c.y-rad-1),0)),ti.min(int(c.y+rad+1),res[1])
    for I in ti.grouped(ti.ndrange(x_range,y_range)):
        dist=(I-c).norm()
        if dist<rad:
            pixels[I]=color

@ti.func
def draw_line(p1,p2,rad,color):
    x_range=(ti.max(int(ti.min(p1.x,p2.x)-rad-1),0),ti.min(int(ti.max(p1.x,p2.x)+rad+1),res[0]))
    y_range=(ti.max(int(ti.min(p1.y,p2.y)-rad-1),0),ti.min(int(ti.max(p1.y,p2.y)+rad+1),res[1]))
    for I in ti.grouped(ti.ndrange(x_range,y_range)):
        dist=ti.min((I-p1).norm(),(I-p2).norm())
        p1I=I-p1
        p1p2_normalized=(p2-p1).normalized()
        p=p1+p1I.dot(p1p2_normalized)*p1p2_normalized
        dist2=(I-p).norm()
        if 0< p1I.dot(p1p2_normalized)<(p2-p1).norm():
            dist=dist2
        if dist<rad:
            pixels[I]=color

@ti.kernel
def paint():
    for i ,j in pixels:
        pixels[i,j]=ti.Vector([0.0,0.0,0.0])
    
    for I in ti.grouped(pos):
        p_current=pos[I]
        p_previous=pos[I]-vel[None]*dt
        rad =2.0*(1.0-pos[I].z/z_far)**2
        col=color[I]*(1.0-pos[I].z/z_far)**0.5
        col *=1.0-(2*((pos[I].x/res[0]-0.5)**2+(pos[I].y/res[1]-0.5)**2))**0.2
       # draw_particle(project(pos[I]),rad,color[I])
        draw_line(project(p_current),project(p_previous),rad,col)

#main
init()
gui = ti.GUI("happy 1025",res,fast_gui = True)
t=0.0
while gui.running:
    t+=dt
    vel[None].z=-1000*(1+math.cos(t*math.pi))
    step()
    paint()
    gui.set_image(pixels)
    gui.show()

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洛可洛克

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值