code:
import taichi as ti
from taichi_glsl import *
ti.init(ti.cpu)
TRAPS = True
CUT = True
kNumIte = 200
kPrecis = 0.00025
kC = ti.Vector([-2.0, 6.0, 15.0, -6.0]) / 22.0
kFocLen = 3.0
if TRAPS:
kbSRad = 2.0
else:
kbSRad = 1.2
kNumBounces = 3
seed = 1
def srand(s):
global seed
seed = s
def rand():
global seed
seed = seed * 0x343fd+0x269ec3
return (seed >> 16) & 32767
def hash(n):
n = (n << 13) ^ n
return n * (n * n * 15731 + 789221) + 1376312589
def frand():
return float(rand()) / 32767.0
def cosineDirection(nor):
u = frand() * 2.0 - 1.0
a = frand() * 6.28318531
return (nor + ti.Vector([
ti.sqrt(1.0 - u * u) * ti.cos(a),
ti.sqrt(1.0 - u * u) * ti.sin(a),
u,
])).normalized()
def qSquare(q):
return ti.Vector([
q.x * q.x - q.y * q.y - q.z * q.z - q.w * q.w,
2.0 * q.x * q.y,
2.0 * q.x * q.z,
2.0 * q.x * q.w,
])
def qCube(q):
q2 = q * q
return ti.Vector([
q.x * (q2.x - 3.0 * q2.y - 3.0 * q2.z - 3.0 * q2.w),
q.y * (3.0 * q2.x - q2.y - q2.z - q2.w),
q.z * (3.0 * q2.x - q2.y - q2.z - q2.w),
q.w * (3.0 * q2.x - q2.y - q2.z - q2.w),
])
def qLength2(q):
return q.dot(q)
def iSphere(ro, rd, rad):
b = ro.dot(rd)
c = ro.dot(ro) - rad * rad
h = b * b - c
if (h < 0.0):
return ti.Vector([-1.0, 0.0])
h = ti.sqrt(h)
return ti.Vector([-b - h, -b + h])
@ti.func
def setCamera(ro, ta, cr):
cw = (ta - ro).normalized()
cp = ti.Vector([ti.sin(cr), ti.cos(cr), 0.0])
cu = (cw.cross(cp)).normalized()
cv = (cu.cross(cw)).normalized()
# rows or cols ?
return ti.Matrix.rows([cu, cv, cw])
@ti.kernel
def mapFunc(p_x: ti.f32, p_y: ti.f32, p_z: ti.f32):
p = ti.Vector([p_x, p_y, p_z])
z = ti.Vector([p.x, p.y, p.z, 0.0])
dz2 = 1.0
m2 = 0.0
n = 0.0
if ti.static(TRAPS):
o = 1e10
for i in range(kNumIte):
dz2 *= 9.0 * qLength2(qSquare(z))
z = qCube(z) + kC
m2 = qLength2(z)
if ti.static(TRAPS):
o = ti.min(o, ti.Vector([z.x - 0.45, z.z - 0.55]).norm() - 0.1)
if m2 > 256.0:
break
n += 1.0
d = 0.25 * ti.log(m2) * ti.sqrt(m2/dz2)
if ti.static(TRAPS):
d = ti.min(o, d)
if ti.static(CUT):
d = ti.max(d, p.y)
return ti.Vector([d, n])
# 1 or 2 ?
def calcNormal1(pos):
pass
@ti.kernel
def calcNormal2(p_x: ti.f32, p_y: ti.f32, p_z: ti.f32):
p = ti.Vector([p_x, p_y, p_z])
# if ti.static(TRAPS):
# the code below only works for the actual Julia set, not the traps
z = ti.Vector([p.x, p.y, p.z, 0.0])
J = ti.Matrix([
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0],
])
for i in range(kNumIte):
k1 = 6.0 * z.x * z.y
k2 = 6.0 * z.x * z.z
k3 = 6.0 * z.x * z.w
k4 = 2.0 * z.y * z.z
k5 = 2.0 * z.y * z.w
k6 = 2.0 * z.z * z.w
sx = z.x * z.x
sy = z.y * z.y
sz = z.z * z.z
sw = z.w * z.w
mx = 3.0 * sx - 3.0 * sy - 3.0 * sz - 3.0 * sw
my = 3.0 * sx - 3.0 * sy - sz - sw
mz = 3.0 * sx - sy - 3.0 * sz - sw
mw = 3.0 * sx - sy - sz - 3.0 * sw
J = J * ti.Matrix([
[mx, -k1, -k2, -k3],
[k1, my, -k4, -k5],
[k2, -k4, mz, -k6],
[k3, -k5, -k6, mw],
])
z = qCube(z) + kC
if z.dot(z) > 256.0:
break
if p.y > 0.0:
return ti.Vector([0.0, 1.0, 0.0])
else:
temp = J@z
return ti.Vector(temp.x, temp.y, temp.z).normalized()
def raycast(ro, rd):
tmax = 7.0
tmin = kPrecis
if ti.static(CUT):
kSplit = 0.01
tpS = (kSplit - ro.y) / rd.y
if tpS > 0.0:
if ro.y > kSplit:
tmin = ti.max(tmin, tpS)
else:
tmax = ti.min(tmax, tpS)
if ti.static(True):
tpF = (-0.8 - ro.y) / rd.y
if tpF > 0.0:
tmax = ti.min(tmax, tpF)
if ti.static(True):
bv = iSphere(ro, rd, kbSRad)
if bv.y < 0.0:
return ti.Vector([-2.0, 0.0])
tmin = ti.max(tmin, bv.x)
tmax = ti.min(tmax, bv.y)
res = ti.Vector([-1.0, 0.0])
t = tmin
lt = 0.0
lh = 0.0
for i in range(1024):
res = mapFunc(ro + rd * t)
if res.x < kPrecis:
break
lt = t
lh = res.x
if ti.static(not TRAPS):
t += ti.min(res.x, 0.2)
else:
t += ti.min(res.x, 0.01) * (0.5 * 0.5 * frand())
if t > tmax:
break
if lt > 0.0001 and res.x < 0.0:
t = lt - lh * (t - lt) / (res.x - lh)
if t < tmax:
res.x = t
else:
res.x = -1.0
return res
def colorSurface(pos, nor, tn):
col = 0.5 + 0.5 * \
ti.cos(ti.Vector([0.0, 0.6, 1.0]) +
ti.log(tn.y) / ti.log(2.0) * 0.9 + 3.5)
if pos.y > 0.0:
col = mix(col, ti.Vector([1.0, 0.0, 0.0]), 0.2)
inside = smoothstep(14.0, 15.0, tn.y)
col *= vec3(0.45, 0.42, 0.40) + vec3(0.55, 0.58, 0.60) * inside
col = mix(col * col * (3.0 - 2.0 * col), col, inside)
col = mix(mix(col, vec3(dot(col, vec3(0.3333))), -0.4), col, inside)
return clamp(col * 0.65, 0.0, 1.0)
def render(fragCoord, ro, rd, resPos, resT):
colorMask = vec3(1.0)
resT = 1e20
for bounce in range(kNumBounces):
tn = raycast(ro, rd)
t = tn.x
if t < 0.0:
if bounce > 0:
return colorMask * 1.65 * step(0.0, rd.y), resPos, resT
else:
return vec3(clamp(0.02 + 0.021 * rd.y, 0.0, 1.0)), resPos, resT
else:
pos = ro + t*rd
# 1 or 2 ?
nor = calcNormal2(pos)
if bounce == 0:
resT = t
resPos = pos
colorMask *= colorSurface(pos, nor, tn)
rd = cosineDirection(nor)
ro = pos + nor * kPrecis
return vec3(0.0), resPos, resT
iResolution = ti.Vector([1024, 512])
pixels = ti.Vector.field(4, ti.f32, (iResolution.x, iResolution.y))
@ti.kernel
def mainImage(iFrame: ti.i32, iTime: ti.f32):
for fragCoord_x, fragCoord_y in pixels:
fragCoord = vec2(fragCoord_x, fragCoord_y)
q = vec2([fragCoord_x, fragCoord_y])
srand(hash(q.x + hash(q.y + hash(1117 * iFrame))))
an = 0.5 * iTime * 0.03
ro = 2.0 * vec3(ti.sin(an), 0.8, ti.cos(an))
ta = vec3(0.0, -0.1, 0.0)
if ti.static(CUT):
ta = vec3(0.0, -0.3, 0.0)
# todo
cam = setCamera(ro, ta, 0.0)
p = ti.Vector([
2.0 * fragCoord.x - iResolution.x / iResolution.y,
2.0 * fragCoord.y - iResolution.x / iResolution.y,
])
rd = normalize(cam @ vec3(p.x, p.y, kFocLen))
pos = vec3(0.0, 0.0, 0.0)
resT = 0.0
col, pos, resT = render(fragCoord, ro, rd, pos, resT)
# oldCam ship
oldCam = mat(
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
)
wpos = vec4(pos, 1.0)
cpos = oldCam @ wpos
npos = vec2(kFocLen * cpos.x / cpos.z, kFocLen * cpos.y / cpos.z)
spos = 0.5 + 0.5 * npos * vec2(iResolution.y / iResolution.x, 1.0)
rpos = spos * iResolution
# ocolt = textureLod(iChannel0, spos, 0.0);
ocolt = vec4(0.0, 0.0, 0.0, 0.0)
if iFrame > 0 and resT < 100.0 and (rpos.y > 1.5 or rpos.x > 3.5):
col = mix(vec3(ocolt.x, ocolt.y, ocolt.z), col, 0.06)
if q.y == 0 and q.x < 3:
if q.x == 0:
pixels[fragCoord_x][fragCoord_y] = vec4(cam[0], -dot(cam[0], ro))
elif q.x == 1:
pixels[fragCoord_x][fragCoord_y] = vec4(cam[1], -dot(cam[1], ro))
else:
pixels[fragCoord_x][fragCoord_y] = vec4(cam[2], -dot(cam[2], ro))
else:
pixels[fragCoord_x][fragCoord_y] = vec4(col, resT)
if __name__ == "__main__":
gui = ti.GUI("Julia_3d", (iResolution.x, iResolution.y))
iFrame = 0
while gui.running:
iFrame += 1
mainImage(iFrame, iFrame / 60.0)
gui.set_image(pixels)
gui.show()
error:
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/vw/Projects/ti/BufferA.py", line 340, in <module>
mainImage(iFrame, iFrame / 60.0)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/kernel_impl.py", line 715, in wrapped
return primal(*args, **kwargs)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/kernel_impl.py", line 643, in __call__
key = self.ensure_compiled(*args)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/kernel_impl.py", line 629, in ensure_compiled
self.materialize(key=key, args=args, arg_features=arg_features)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/kernel_impl.py", line 475, in materialize
taichi_kernel = _ti_core.create_kernel(taichi_ast_generator,
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/kernel_impl.py", line 465, in taichi_ast_generator
transform_tree(tree, ctx)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/transform.py", line 8, in transform_tree
ASTTransformer()(ctx, tree)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 26, in __call__
raise e
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 23, in __call__
return method(ctx, node)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 484, in build_Module
build_stmt(ctx, stmt)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 26, in __call__
raise e
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 23, in __call__
return method(ctx, node)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 448, in build_FunctionDef
build_stmts(ctx, node.body)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 1083, in build_stmts
build_stmt(ctx, stmt)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 26, in __call__
raise e
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 23, in __call__
return method(ctx, node)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 911, in build_For
return ASTTransformer.build_struct_for(ctx,
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 829, in build_struct_for
build_stmts(ctx, node.body)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 1083, in build_stmts
build_stmt(ctx, stmt)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 26, in __call__
raise e
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 23, in __call__
return method(ctx, node)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 950, in build_If
build_stmts(ctx, node.body)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 1083, in build_stmts
build_stmt(ctx, stmt)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 26, in __call__
raise e
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 23, in __call__
return method(ctx, node)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 950, in build_If
build_stmts(ctx, node.body)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 1083, in build_stmts
build_stmt(ctx, stmt)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 26, in __call__
raise e
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 23, in __call__
return method(ctx, node)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 69, in build_Assign
build_stmt(ctx, node.value)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 26, in __call__
raise e
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 23, in __call__
return method(ctx, node)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 323, in build_Call
build_stmts(ctx, node.args)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 1083, in build_stmts
build_stmt(ctx, stmt)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 26, in __call__
raise e
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 23, in __call__
return method(ctx, node)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer.py", line 525, in build_UnaryOp
build_stmt(ctx, node.operand)
File "/Users/vw/miniconda3/envs/taichi/lib/python3.8/site-packages/taichi/lang/ast/ast_transformer_utils.py", line 32, in __call__
raise TaichiCompilationError(msg)
taichi.lang.exception.TaichiCompilationError: On line 326 of file "/Users/vw/Projects/ti/BufferA.py":
pixels[fragCoord_x][fragCoord_y] = vec4(cam[0], -dot(cam[0],
^^^^^^^^^^^^^^^
AttributeError: 'Expr' object has no attribute 'dot'
这里我无论是 v1.dot(v2)还是 dot(v1, v2)都是error。这个error我看报错无法自己解决,请问是什么原因呢?