Ejemplo n.º 1
0
 def max_starred() -> ti.i32:
     a = ti.Vector([1, 2, 3])
     b = ti.Vector([4, 5, 6])
     return ti.max(*a, *b)
Ejemplo n.º 2
0
 def max_u16(a: ti.u16, b: ti.u16) -> ti.u16:
     return ti.max(a, b)
Ejemplo n.º 3
0
    (lambda x: ti.sqrt(x), lambda x: np.sqrt(x)),
    (lambda x: ti.exp(x), lambda x: np.exp(x)),
    (lambda x: ti.log(x), lambda x: np.log(x)),
])
@if_has_autograd
@test_utils.test()
def test_unary(tifunc, npfunc):
    grad_test(tifunc, npfunc)


@pytest.mark.parametrize('tifunc,npfunc', [
    (lambda x: ti.min(x, 0), lambda x: np.minimum(x, 0)),
    (lambda x: ti.min(x, 1), lambda x: np.minimum(x, 1)),
    (lambda x: ti.min(0, x), lambda x: np.minimum(0, x)),
    (lambda x: ti.min(1, x), lambda x: np.minimum(1, x)),
    (lambda x: ti.max(x, 0), lambda x: np.maximum(x, 0)),
    (lambda x: ti.max(x, 1), lambda x: np.maximum(x, 1)),
    (lambda x: ti.max(0, x), lambda x: np.maximum(0, x)),
    (lambda x: ti.max(1, x), lambda x: np.maximum(1, x)),
])
@if_has_autograd
@test_utils.test()
def test_minmax(tifunc, npfunc):
    grad_test(tifunc, npfunc)


@if_has_autograd
@test_utils.test()
def test_mod():
    x = ti.field(ti.i32)
    y = ti.field(ti.i32)
Ejemplo n.º 4
0
def dda_particle(eye_pos, d_, t):
    grid_res = particle_grid_res

    bbox_min = bbox[0]
    bbox_max = bbox[1]

    hit_pos = ti.Vector([0.0, 0.0, 0.0])
    normal = ti.Vector([0.0, 0.0, 0.0])
    c = ti.Vector([0.0, 0.0, 0.0])
    d = d_
    for i in ti.static(range(3)):
        if ti.abs(d[i]) < 1e-6:
            d[i] = 1e-6

    inter, near, far = ray_aabb_intersection(bbox_min, bbox_max, eye_pos, d)
    near = ti.max(0, near)

    closest_intersection = inf

    if inter:
        pos = eye_pos + d * (near + eps)

        rinv = 1.0 / d
        rsign = ti.Vector([0, 0, 0])
        for i in ti.static(range(3)):
            if d[i] > 0:
                rsign[i] = 1
            else:
                rsign[i] = -1

        o = grid_res * pos
        ipos = ti.Matrix.floor(o).cast(ti.i32)
        dis = (ipos - o + 0.5 + rsign * 0.5) * rinv
        running = 1
        while running:
            inside = inside_particle_grid(ipos)

            if inside:
                num_particles = voxel_has_particle[ipos]
                if num_particles != 0:
                    num_particles = ti.length(pid.parent(), ipos)
                for k in range(num_particles):
                    p = pid[ipos[0], ipos[1], ipos[2], k]
                    v = particle_v[p]
                    x = particle_x[p] + t * v
                    color = particle_color[p]
                    dist, poss = intersect_sphere(eye_pos, d, x, sphere_radius)
                    hit_pos = poss
                    if dist < closest_intersection and dist > 0:
                        hit_pos = eye_pos + dist * d
                        closest_intersection = dist
                        normal = ti.Matrix.normalized(hit_pos - x)
                        c = [
                            color // 256**2 / 255.0, color / 256 % 256 / 255.0,
                            color % 256 / 255.0
                        ]
            else:
                running = 0
                normal = [0, 0, 0]

            if closest_intersection < inf:
                running = 0
            else:
                # hits nothing. Continue ray marching
                mm = ti.Vector([0, 0, 0])
                if dis[0] <= dis[1] and dis[0] <= dis[2]:
                    mm[0] = 1
                elif dis[1] <= dis[0] and dis[1] <= dis[2]:
                    mm[1] = 1
                else:
                    mm[2] = 1
                dis += mm * rsign * rinv
                ipos += mm * rsign

    return closest_intersection, normal, c
Ejemplo n.º 5
0
 def max_i64(a: ti.i64, b: ti.i64) -> ti.i64:
     return ti.max(a, b)
Ejemplo n.º 6
0
def dot_or_zero(n, l):
    return ti.max(0.0, n.dot(l))
Ejemplo n.º 7
0
 def max(self):
     import taichi as ti
     ret = self.entries[0]
     for i in range(1, len(self.entries)):
         ret = ti.max(ret, self.entries[i])
     return ret
Ejemplo n.º 8
0
 def max_i32(a: ti.i32, b: ti.i32) -> ti.i32:
     return ti.max(a, b)
Ejemplo n.º 9
0
def clamp(x):
    return ti.max(0, ti.min(1.0, x))
Ejemplo n.º 10
0
def boxSDF(p, b):
    q = ti.abs(p) - b
    return length(ti.max(q, 0.0)) + ti.min(q.max(), 0.0)
Ejemplo n.º 11
0
ti.init(ti.cpu)

scene = t3.Scene()
obj = t3.Geometry.cube()
model = t3.Model(t3.Mesh.from_obj(obj))
model.material = t3.Material(
    t3.BlinnPhong(
        # https://learnopengl.com/img/textures/container2.png
        color=t3.Texture('docs/_media/container2.png'),
        specular=t3.Texture('docs/_media/container2_specular.png'),
    ))
scene.add_model(model)
camera = t3.Camera()
scene.add_camera_d(camera)
original = t3.FrameBuffer(camera)
filted = t3.ImgUnaryOp(original, lambda x: ti.max(0, x - 1))
blurred = t3.GaussianBlur(filted, radius=21)
final = t3.ImgBinaryOp(original, blurred, lambda x, y: x + y)
scene.add_buffer(final)
light = t3.Light(dir=[-0.2, -0.6, -1.0], color=1.6)
scene.add_light(light)

gui_original = ti.GUI('Original', filted.res)
gui_filted = ti.GUI('Filted', filted.res)
gui_blurred = ti.GUI('Blurred', blurred.res)
gui_final = ti.GUI('Final', final.res)
gui_original.fps_limit = None
gui_filted.fps_limit = None
gui_blurred.fps_limit = None
gui_final.fps_limit = None
while gui_final.running and gui_filted.running and gui_blurred.running and gui_original.running:
Ejemplo n.º 12
0
def saturate(x):
    return ti.max(0, ti.min(1.0, x))
Ejemplo n.º 13
0
def SdfCapsule(X, radius, half_length):
    alpha = ti.min(ti.max((X[0] / half_length + 1.0) * 0.5, 0.0), 1.0)
    tmp = ti.Vector([X[0], X[1]])
    tmp[0] += (1.0 - 2.0 * alpha) * half_length
    return tmp.norm() - radius
Ejemplo n.º 14
0
 def max_i16(a: ti.i16, b: ti.i16) -> ti.i16:
     return ti.max(a, b)
Ejemplo n.º 15
0
def plane(pos):
    return ts.length(ti.max(ti.abs(pos) - ts.vec(12.0, 0.5, 12.0), 0.0))
Ejemplo n.º 16
0
 def max_u32(a: ti.u32, b: ti.u32) -> ti.u32:
     return ti.max(a, b)
Ejemplo n.º 17
0
def sdfBox(p, length):
    p = ti.abs(p) - length
    d = ti.max(p, ti.Vector([0., 0., 0.])).norm()
    d += ti.min(ti.max(p[0], ti.max(p[1], p[2])), 0.)
    return d
Ejemplo n.º 18
0
 def max_u64(a: ti.u64, b: ti.u64) -> ti.u64:
     return ti.max(a, b)
Ejemplo n.º 19
0
 def apply_grad(self, lr: float, gamma: float, max_grad: float):
     for i in self.tf_tex:
         self.tf_momentum[i] = gamma * self.tf_momentum[i] + \
                               lr * tl.clamp(self.tf_tex.grad[i], -max_grad, max_grad)
         self.tf_tex[i] -= self.tf_momentum[i]
         self.tf_tex[i] = ti.max(self.tf_tex[i], 0)
Ejemplo n.º 20
0
def fill_color(ipixels: ti.template(), idyef: ti.template()):
    for i, j in ipixels:
        density = ti.min(1.0, ti.max(0.0, idyef[i, j]))
        ipixels[i, j] = density
Ejemplo n.º 21
0
def computeNormalAndCurvature():
    """
    Compute the normal and the curvature at all points voxels.
    Based on the PC limplementation:
    https://pointclouds.org/documentation/group__features.html
    """
    radius = 50
    for i,j in pts:
        nb_pts = ti.cast(0, ti.f32)
        accu_0 = ti.cast(0, ti.f32)
        accu_1 = ti.cast(0, ti.f32)
        accu_2 = ti.cast(0, ti.f32)
        accu_3 = ti.cast(0, ti.f32)
        accu_4 = ti.cast(0, ti.f32)
        accu_5 = ti.cast(0, ti.f32)
        accu_6 = ti.cast(0, ti.f32)
        accu_7 = ti.cast(0, ti.f32)
        accu_8 = ti.cast(0, ti.f32)
        z = 0
        for x in range(i-radius, i+radius):
            for y in range(j-radius, j+radius):
                if ti.is_active(block1, [x,y]):
                    accu_0 += x * x
                    accu_1 += x * y
                    accu_2 += x * z
                    accu_3 += y * y
                    accu_4 += y * z
                    accu_5 += z * z
                    accu_6 += x
                    accu_7 += y
                    accu_8 += z
                    nb_pts += 1
        accu_0 /= nb_pts
        accu_1 /= nb_pts
        accu_2 /= nb_pts
        accu_3 /= nb_pts
        accu_4 /= nb_pts
        accu_5 /= nb_pts
        accu_6 /= nb_pts
        accu_7 /= nb_pts
        accu_8 /= nb_pts
        cov_mat_0 = accu_0 - accu_6 * accu_6
        cov_mat_1 = accu_1 - accu_6 * accu_7
        cov_mat_2 = accu_2 - accu_6 * accu_8
        cov_mat_4 = accu_3 - accu_7 * accu_7
        cov_mat_5 = accu_4 - accu_7 * accu_8
        cov_mat_8 = accu_5 - accu_8 * accu_8
        cov_mat_3 = cov_mat_1
        cov_mat_6 = cov_mat_2
        cov_mat_7 = cov_mat_5

        # Compute eigen value and eigen vector
        # Make sure in [-1, 1]
        scale = ti.max(1.0,   ti.abs(cov_mat_0))
        scale = ti.max(scale, ti.abs(cov_mat_1))
        scale = ti.max(scale, ti.abs(cov_mat_2))
        scale = ti.max(scale, ti.abs(cov_mat_3))
        scale = ti.max(scale, ti.abs(cov_mat_4))
        scale = ti.max(scale, ti.abs(cov_mat_5))
        scale = ti.max(scale, ti.abs(cov_mat_6))
        scale = ti.max(scale, ti.abs(cov_mat_7))
        scale = ti.max(scale, ti.abs(cov_mat_8))
        if scale > 1.0:
            cov_mat_0 /= scale
            cov_mat_1 /= scale
            cov_mat_2 /= scale
            cov_mat_3 /= scale
            cov_mat_4 /= scale
            cov_mat_5 /= scale
            cov_mat_6 /= scale
            cov_mat_7 /= scale
            cov_mat_8 /= scale
        
        # Compute roots
        eigen_val_0 = ti.cast(0, ti.f32)
        eigen_val_1 = ti.cast(0, ti.f32)
        eigen_val_2 = ti.cast(0, ti.f32)
        
        c0 = cov_mat_0 * cov_mat_4 * cov_mat_8 \
            + 2 * cov_mat_3 * cov_mat_6 * cov_mat_7 \
            - cov_mat_0 * cov_mat_7 * cov_mat_7 \
            - cov_mat_4 * cov_mat_6 * cov_mat_6 \
            - cov_mat_8 * cov_mat_3 * cov_mat_3
        c1 = cov_mat_0 * cov_mat_4 \
            - cov_mat_3 * cov_mat_3 \
            + cov_mat_0 * cov_mat_8 \
            - cov_mat_6 * cov_mat_6 \
            + cov_mat_4 * cov_mat_8 \
            - cov_mat_7 * cov_mat_7
        c2 = cov_mat_0 + cov_mat_4 + cov_mat_8
  
        if ti.abs(c0) < 0.00001:
            eigen_val_0 = 0
            d = c2 * c2 - 4.0 * c1
            if d < 0.0:  # no real roots ! THIS SHOULD NOT HAPPEN!
                d = 0.0
            sd = ti.sqrt(d)
            eigen_val_2 = 0.5 * (c2 + sd)
            eigen_val_1 = 0.5 * (c2 - sd)
        else:
            s_inv3 = ti.cast(1.0 / 3.0, ti.f32)
            s_sqrt3 = ti.sqrt(3.0)
            c2_over_3 = c2 * s_inv3
            a_over_3 = (c1 - c2 * c2_over_3) * s_inv3
            if a_over_3 > 0:
                a_over_3 = 0
        
            half_b = 0.5 * (c0 + c2_over_3 * (2 * c2_over_3 * c2_over_3 - c1))
            q = half_b * half_b + a_over_3 * a_over_3 * a_over_3
            if q > 0:
                q = 0
        
            rho = ti.sqrt(-a_over_3)
            theta = ti.atan2(ti.sqrt(-q), half_b) * s_inv3
            cos_theta = ti.cos(theta)
            sin_theta = ti.sin(theta)
            eigen_val_0 = c2_over_3 + 2 * rho * cos_theta
            eigen_val_1 = c2_over_3 - rho * (cos_theta + s_sqrt3 * sin_theta)
            eigen_val_2 = c2_over_3 - rho * (cos_theta - s_sqrt3 * sin_theta)
            temp_swap = ti.cast(0, ti.f32)
        
            # Sort in increasing order.
            if eigen_val_0 >= eigen_val_1:
                temp_swap = eigen_val_1
                eigen_val_1 = eigen_val_0
                eigen_val_0 = temp_swap
            if eigen_val_1 >= eigen_val_2:
                temp_swap = eigen_val_2
                eigen_val_2 = eigen_val_1
                eigen_val_1 = temp_swap
                if eigen_val_0 >= eigen_val_1:
                    temp_swap = eigen_val_1
                    eigen_val_1 = eigen_val_0
                    eigen_val_0 = temp_swap
        
            if eigen_val_0 <= 0:
                eigen_val_0 = 0
                d = c2 * c2 - 4.0 * c1
                if d < 0.0:  # no real roots ! THIS SHOULD NOT HAPPEN!
                    d = 0.0
                sd = ti.sqrt(d)
                eigen_val_2 = 0.5 * (c2 + sd)
                eigen_val_1 = 0.5 * (c2 - sd)
            # end of compute roots

        eigen_value = eigen_val_1 * scale # eigen value for 2D SDF
        # eigen value for 3D SDF
        #eigen_value = eigen_val_0 * scale

        #print("eigen_val_0 ", eigen_val_0)
        #print("eigen_val_1 ", eigen_val_1)
        #print("eigen_val_2 ", eigen_val_2)
    
        # TODO
        #scaledMat.diagonal ().array () -= eigenvalues (0)
        #eigenvector = detail::getLargest3x3Eigenvector<Vector> (scaledMat).vector;

        # Compute normal vector (TODO)
        #visual_norm[i,j][0] = eigen_val_0 #eigen_vector[0]
        #visual_norm[i,j][1] = eigen_val_1 #eigen_vector[1]
        #visual_norm[i,j][2] = eigen_val_2 #eigen_vector[2]

        # Compute the curvature surface change
        eig_sum = cov_mat_0 + cov_mat_1 + cov_mat_2
        visual_curv[i,j][0] = 0
        if eig_sum != 0:
            visual_curv[i,j][0] = eigen_val_1 # true curvature is: ti.abs(eigen_value / eig_sum)
Ejemplo n.º 22
0
def point_aabb_distance2(box_min, box_max, o):
    p = ti.Vector([0.0, 0.0, 0.0])
    for i in ti.static(range(3)):
        p[i] = ti.max(ti.min(o[i], box_max[i]), box_min[i])
    return (p - o).norm_sqr()
Ejemplo n.º 23
0
 def util_color_map_value(self, c0, c1, v) -> ti.i32:
     vl = ti.max(0.0, ti.min(1.0, v))
     r = c1 - c0
     d = ti.cast(c0 + r * vl, ti.i32)
     return d
Ejemplo n.º 24
0
def apply_grad():
    # gradient descent
    for i, j, k in density:
        density[i, j, k] -= learning_rate * density.grad[i, j, k]
        density[i, j, k] = ti.max(density[i, j, k], 0)
Ejemplo n.º 25
0
 def substep():
     for i, j in grid_m:
         grid_v[i, j] = [0, 0]
         grid_m[i, j] = 0
         grid_v_int[i, j] = [0, 0]
         grid_m_int[i, j] = 0
     for p in x:  # Particle state update and scatter to grid (P2G)
         base = (x[p] * inv_dx - 0.5).cast(int)
         fx = x[p] * inv_dx - base.cast(float)
         # Quadratic kernels  [http://mpm.graphics   Eqn. 123, with x=fx, fx-1,fx-2]
         w = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2]
         F[p] = (ti.Matrix.identity(float, 2) +
                 dt * C[p]) @ F[p]  # deformation gradient update
         h = ti.exp(
             10 * (1.0 - Jp[p])
         )  # Hardening coefficient: snow gets harder when compressed
         if material[p] == 1:  # jelly, make it softer
             h = 0.3
         mu, la = mu_0 * h, lambda_0 * h
         if material[p] == 0:  # liquid
             mu = 0.0
         U, sig, V = ti.svd(F[p])
         J = 1.0
         for d in ti.static(range(2)):
             new_sig = sig[d, d]
             if material[p] == 2:  # Snow
                 new_sig = ti.min(ti.max(sig[d, d], 1 - 2.5e-2),
                                  1 + 4.5e-3)  # Plasticity
             Jp[p] *= sig[d, d] / new_sig
             sig[d, d] = new_sig
             J *= new_sig
         if material[
                 p] == 0:  # Reset deformation gradient to avoid numerical instability
             F[p] = ti.Matrix.identity(float, 2) * ti.sqrt(J)
         elif material[p] == 2:
             F[p] = U @ sig @ V.transpose(
             )  # Reconstruct elastic deformation gradient after plasticity
         stress = 2 * mu * (F[p] - U @ V.transpose()) @ F[p].transpose(
         ) + ti.Matrix.identity(float, 2) * la * J * (J - 1)
         stress = (-dt * p_vol * 4 * inv_dx * inv_dx) * stress
         affine = stress + p_mass * C[p]
         for i, j in ti.static(ti.ndrange(
                 3, 3)):  # Loop over 3x3 grid node neighborhood
             offset = ti.Vector([i, j])
             dpos = (offset.cast(float) - fx) * dx
             weight = w[i][0] * w[j][1]
             grid_v_int[base + offset] += int(
                 ti.floor(0.5 + weight * (p_mass * v[p] + affine @ dpos) *
                          (2.0**v_exp)))
             grid_m_int[base + offset] += int(
                 ti.floor(0.5 + weight * p_mass * (2.0**m_exp)))
     for i, j in grid_m:
         if grid_m_int[i, j] > 0:  # No need for epsilon here
             # grid_v[i, j] = (1.0 / grid_m[i, j]) * grid_v[i, j] # Momentum to velocity
             grid_v[i, j] = (2**(m_exp - v_exp) / grid_m_int[i, j]
                             ) * grid_v_int[i, j]  # Momentum to velocity
             grid_v[i, j][1] -= dt * 50  # gravity
             if i < 3 and grid_v[i, j][0] < 0:
                 grid_v[i, j][0] = 0  # Boundary conditions
             if i > n_grid - 3 and grid_v[i, j][0] > 0:
                 grid_v[i, j][0] = 0
             if j < 3 and grid_v[i, j][1] < 0:
                 grid_v[i, j][1] = 0
             if j > n_grid - 3 and grid_v[i, j][1] > 0:
                 grid_v[i, j][1] = 0
     for p in x:  # grid to particle (G2P)
         base = (x[p] * inv_dx - 0.5).cast(int)
         fx = x[p] * inv_dx - base.cast(float)
         w = [
             0.5 * (1.5 - fx)**2, 0.75 - (fx - 1.0)**2, 0.5 * (fx - 0.5)**2
         ]
         new_v = ti.Vector.zero(float, 2)
         new_C = ti.Matrix.zero(float, 2, 2)
         for i, j in ti.static(ti.ndrange(
                 3, 3)):  # loop over 3x3 grid node neighborhood
             dpos = ti.Vector([i, j]).cast(float) - fx
             g_v = grid_v[base + ti.Vector([i, j])]
             weight = w[i][0] * w[j][1]
             new_v += weight * g_v
             new_C += 4 * inv_dx * weight * g_v.outer_product(dpos)
         v[p], C[p] = new_v, new_C
         x[p] += dt * v[p]  # advection
Ejemplo n.º 26
0
def color_f32_to_i8(x):
    return ti.cast(ti.min(ti.max(x, 0.0), 1.0) * 255, ti.i32)
Ejemplo n.º 27
0
def trace(sample: ti.u32):
    for i, j in linear_pixel:
        o = ti.Vector([camera_pos[0], camera_pos[1], camera_pos[2]])
        aperture_size = 0.2
        forward = -o.normalized()

        u = ti.Vector([0.0, 1.0, 0.0]).cross(forward).normalized()
        v = forward.cross(u).normalized()
        u = -u
        # anti aliasing
        d = ((i + ti.random() - width / 2.0) / width * u * 1.5
             + (j + ti.random() - height / 2.0) / width * v * 1.5
             + width / width * forward).normalized()

        focal_point = d * focal_length / d.dot(forward) + o

        o += d * 0.01

        # assuming a circle-like aperture
        phi = 2.0 * math.pi * ti.random()
        aperture_radius = ti.random() * aperture_size
        o += u * aperture_radius * ti.cos(phi) + \
            v * aperture_radius * ti.sin(phi)

        d = (focal_point - o).normalized()
        uv = cubemap_coord(d)
        albedo_factor = ti.Vector([1.0, 1.0, 1.0])
        radiance = ti.Vector([0.0, 0.0, 0.0])
        for step in ti.ndrange(32):
            sp = spheres.intersect(o, d)
            uv = cubemap_coord(d)
            if sp[1] > -1:
                sp_index = int(sp[1])
                p = sp[0] * d + o
                c_ = spheres.center_radius[sp_index]
                c = ti.Vector([c_[0], c_[1], c_[2]])
                n = (p - c).normalized()
                wo = -d
                albedo = spheres.albedos[sp_index]
                metallic = spheres.metallics[sp_index]
                ior = spheres.iors[sp_index]
                roughness = ti.max(0.04, spheres.roughness[sp_index])
                f0 = (1.0 - ior) / (1.0 + ior)
                f0 = f0 * f0
                f0 = lerp(f0, luma(albedo), metallic)
                wi = reflect(-wo, n)
                radiance += spheres.emissions[sp_index] * albedo_factor

                view_fresnel = schlick2(wo, n, f0)
                sample_weights = ti.Vector([1.0 - view_fresnel, view_fresnel])

                weight = 0.0

                h = (wi + wo).normalized()

                shaded = ti.Vector([0.0, 0.0, 0.0])

                if ti.random() < sample_weights[0]:
                    wi = cosine_sample(n).normalized()
                    h = (wi + wo).normalized()
                    shaded = ti.max(0.00, wi.dot(n) * albedo / math.pi)

                else:
                    wi = ggx_sample(n, wo, roughness).normalized()
                    h = (wi + wo).normalized()
                    F = schlick2(wi, n, f0)
                    shaded = ti.max(0.0, wi.dot(n) * albedo * ggx_smith_uncorrelated(
                        roughness, h.dot(n), wo.dot(n), wi.dot(n), F))

                pdf_lambert = wi.dot(n) / math.pi
                pdf_ggx = ggx_pdf(roughness, h.dot(n), wo.dot(h))

                weight = ti.max(0.0, 1.0 / (sample_weights[0] *
                                            pdf_lambert + sample_weights[1] * pdf_ggx))

                # russian roule
                albedo_factor *= shaded * weight
                if step > 5:
                    if luma(albedo) < ti.random():
                        break
                    else:
                        albedo_factor /= luma(albedo)
                d = wi
                o = p + eps * d

            else:
                radiance += albedo_factor * tex2d(skybox.field, uv) / 255
                break

        linear_pixel[i, j] = (linear_pixel[i, j] *
                              (sample - 1) + radiance) / sample
        pixel[i, j] = ti.sqrt(linear_pixel[i, j])