有个error,可以帮忙解决吗?

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我看报错无法自己解决,请问是什么原因呢?

你的cam[0]这种访问Matrix的方式是访问的标量,不是一行或一列的Vector,太极好像还不支持这种

的确如此。谢谢你。