def my_render_func(pos, normal, dir, light_dir):
    n = 4  # cartoon level
    #refl_dir = ts.reflect(light_dir, normal)
    refl_dir = ts.mix(light_dir, -dir, 0.5)
    NoL = pow(ts.dot(normal, refl_dir), 12)
    NoL = ts.mix(NoL, max(0, ts.dot(normal, light_dir)), 0.6)
    strength = 0.2
    if any(normal):
        strength = ti.floor(max(0, NoL * n + 0.5)) / n
    return ts.vec3(strength)
示例#2
0
    def evaluate(self, N, V, L, mat_buf, mat_id):
        outputC = ti.Vector([0.0, 0.0, 0.0])
        pdf = -1.0
        NDotL = N.dot(L)
        NDotV = N.dot(V)
        if ((NDotL > 0.0) & (NDotV > 0.0)):
            H = (L + V).normalized()
            NDotH = H.dot(N)
            LDotH = H.dot(L)
            VDotH = H.dot(V)
            Cdlin = UF.get_material_color(mat_buf, mat_id)
            metal = UF.get_material_metallic(mat_buf, mat_id)
            rough = UF.get_material_roughness(mat_buf, mat_id)
            Cdlum = 0.3 * Cdlin.x + 0.6 * Cdlin.y + 0.1 * Cdlin.z

            # spec=0.5 spectint=0 sheentint=0.5
            Ctint = ti.Vector([1.0, 1.0, 1.0])
            if Cdlum > 0.0:
                Ctint = Cdlin / Cdlum

            Cspec0 = ts.mix(ti.Vector([0.04, 0.04, 0.04]), Cdlin, metal)
            Csheen = ts.mix(ti.Vector([1.0, 1.0, 1.0]), Ctint, 1.0)

            FL = self.SchlickFresnel(NDotL)
            FV = self.SchlickFresnel(NDotV)
            Fd90 = 0.5 + 2.0 * LDotH * LDotH * rough
            Fd = ts.mix(1.0, Fd90, FL) * ts.mix(1.0, Fd90, FV)

            Fss90 = LDotH * LDotH * rough
            Fss = ts.mix(1.0, Fss90, FL) * ts.mix(1.0, Fss90, FV)
            ss = 1.25 * (Fss * (1.0 / (NDotL + NDotV) - 0.5) + 0.5)

            specularAlpha = max(0.001, rough)
            Ds = self.GTR2(NDotH, specularAlpha)
            FH = self.SchlickFresnel(LDotH)
            Fs = ts.mix(Cspec0, ti.Vector([1.0, 1.0, 1.0]), FH)
            roughg = self.sqr(rough * 0.5 + 0.5)
            Gs = self.smithG_GGX(NDotL, roughg) * self.smithG_GGX(
                NDotV, roughg)

            Fsheen = FH * Csheen

            Dr = self.GTR1(NDotH, 0.001)
            Fr = ts.mix(0.04, 1.0, FH)
            Gr = self.smithG_GGX(NDotL, 0.25) * self.smithG_GGX(NDotV, 0.25)
            outputC = (Fsheen + Cdlin *
                       (1.0 / M_PIf)) * Fd * (1.0 - metal) + Gs * Fs * Ds
            outputC *= NDotL

            diffuseRatio = 0.5 * (1.0 - metal)
            specularRatio = 1.0 - diffuseRatio
            pdfGTR2 = Ds * NDotH
            pdfGTR1 = Dr * NDotH

            pdfSpec = pdfGTR2 / (4.0 * abs(LDotH))
            pdfDiff = NDotL / M_PIf

            pdf = diffuseRatio * pdfDiff + specularRatio * pdfSpec

        return outputC, pdf
示例#3
0
    def render_func(self, pos, normal, dir, light_dir):
        color = ts.vec3(0.0)

        shineness = self.shineness
        half_lambert = ts.dot(normal, light_dir) * 0.5 + 0.5
        lambert = max(0, ts.dot(normal, light_dir))
        blinn_phong = ts.dot(normal, ts.mix(light_dir, -dir, 0.5))
        blinn_phong = pow(max(blinn_phong, 0), shineness)
        refl_dir = ts.reflect(light_dir, normal)
        phong = -ts.dot(normal, refl_dir)
        phong = pow(max(phong, 0), shineness)

        strength = 0.0
        if ti.static(self.lambert != 0.0):
            strength += lambert * self.lambert
        if ti.static(self.half_lambert != 0.0):
            strength += half_lambert * self.half_lambert
        if ti.static(self.blinn_phong != 0.0):
            strength += blinn_phong * self.blinn_phong
        if ti.static(self.phong != 0.0):
            strength += phong * self.phong
        color = ts.vec3(strength)

        if ti.static(self.is_normal_map):
            color = normal * 0.5 + 0.5

        return color
示例#4
0
def render(t: ti.f32):
    for i, j in pixels:
        p = ti.Vector([2.0 * i - WIDTH, 2.0 * j - HEIGHT]) / min(WIDTH, HEIGHT)
        # background-color
        bcol = ti.Vector([1.0, 0.8, 0.7 - 0.07 * p[1]
                          ]) * (1.0 - 0.25 * p.norm())
        # animate
        tt = mod(t, 1.5) / 1.5
        ss = pow(tt, 0.2) * 0.5 + 0.5
        ss = 1.0 + ss * 0.5 * ti.sin(tt * 6.283184 * 3.0 +
                                     p[1] * 0.5) * ti.exp(-4.0 * tt)
        p *= ti.Vector([0.5, 1.5]) + ss * ti.Vector([0.5, -0.5])
        # shape
        p[1] -= 0.25
        a = ti.atan2(p[0], p[1]) / 3.141592
        r = p.norm()
        h = abs(a)
        d = (13.0 * h - 22.0 * h * h + 10.0 * h * h * h) / (6.0 - 5.0 * h)
        # color
        s = 0.75 + 0.75 * p[0]
        s *= 1.0 - 0.4 * r
        s = 0.3 + 0.7 * s
        s *= 0.5 + 0.5 * pow(1.0 - clamp(r / d, 0.0, 1.0), 0.1)

        hcol = ti.Vector([1.0, 0.5 * r, 0.3]) * s
        pixels[i, j] = ts.mix(bcol, hcol, smoothstep(-0.01, 0.01, d - r))
    def sample_volume_trilinear(self, pos):
        ''' Samples volume data at `pos` and trilinearly interpolates the value

        Args:
            pos (tl.vec3): Position to sample the volume in [-1, 1]^3

        Returns:
            float: Sampled interpolated intensity
        '''
        pos = tl.clamp(((0.5 * pos) + 0.5), 0.0, 1.0) \
              * ti.static(tl.vec3(*self.volume.shape) - 1.0 - 1e-4)
        x_low, x_high, x_frac = low_high_frac(pos.x)
        y_low, y_high, y_frac = low_high_frac(pos.y)
        z_low, z_high, z_frac = low_high_frac(pos.z)

        x_high = min(x_high, ti.static(self.volume.shape[0] - 1))
        y_high = min(y_high, ti.static(self.volume.shape[1] - 1))
        z_high = min(z_high, ti.static(self.volume.shape[2] - 1))
        # on z_low
        v000 = self.volume[x_low, y_low, z_low]
        v100 = self.volume[x_high, y_low, z_low]
        x_val_y_low = tl.mix(v000, v100, x_frac)
        v010 = self.volume[x_low, y_high, z_low]
        v110 = self.volume[x_high, y_high, z_low]
        x_val_y_high = tl.mix(v010, v110, x_frac)
        xy_val_z_low = tl.mix(x_val_y_low, x_val_y_high, y_frac)
        # on z_high
        v001 = self.volume[x_low, y_low, z_high]
        v101 = self.volume[x_high, y_low, z_high]
        x_val_y_low = tl.mix(v001, v101, x_frac)
        v011 = self.volume[x_low, y_high, z_high]
        v111 = self.volume[x_high, y_high, z_high]
        x_val_y_high = tl.mix(v011, v111, x_frac)
        xy_val_z_high = tl.mix(x_val_y_low, x_val_y_high, y_frac)
        return tl.mix(xy_val_z_low, xy_val_z_high, z_frac)
示例#6
0
 def teture2D(self, u, v):
     x = ts.clamp(u * self.wid, 0.0, self.wid - 1.0)
     y = ts.clamp(v * self.hgt, 0.0, self.hgt - 1.0)
     #   lt       rt
     #    *--------*
     #    |   ↑wbt |
     #    | ← *    |
     #    | wlr    |
     #    *--------*
     #   lb       rb
     lt = ti.Vector([ti.floor(x), ti.floor(y)])
     rt = lt + ti.Vector([1, 0])
     lb = lt + ti.Vector([0, 1])
     rb = lt + ti.Vector([1, 1])
     wbt = ts.fract(y)
     wlr = ts.fract(x)
     #print(x,y,lt,wbt,wlr)
     return ts.mix(ts.mix(self.sample(lt), self.sample(rt), wlr),
                   ts.mix(self.sample(lb), self.sample(rb), wlr), wbt)
示例#7
0
def raymarch(ro, rd):
    p = ro
    glow = 0.0
    for _ in range(700):
        dS = getDist(p)
        glow = max(glow, 1.0 / (dS + 1.0))
        bdir = -1.0 * p.normalized()
        bdist = p.norm()
        dS = min(dS, bdist) * 0.04
        if dS > 30.0:
            break
        if bdist < 1.0:
            break
        bdist = pow(bdist + 1.0, 2.0)
        bdist = dS * 1.0 / bdist
        rd = ts.mix(rd, bdir, bdist)
        p += rd * max(dS, 0.01)
    gcol = getGlow(glow)
    c_rgb = ts.mix(ti.Vector([0.0, 0.0, 0.0]),
                   ti.Vector([gcol[0], gcol[1], gcol[2]]), gcol[3])
    return ti.Vector([c_rgb[0], c_rgb[1], c_rgb[2], 1.0])
示例#8
0
def blueorange(rgb):
    '''
    Convert RGB value (vector) into blue-orange colormap (vector).

    :parameter rgb: (3D vector)
        The RGB value, X compoment is the R value, can be eitier float or int.

    :return:
        The return value is calculated as `sqrt(mix(vec(0, 0.01, 0.05), vec(1.19, 1.04, 0.98), color))`.
    '''
    blue = ts.vec(0.00, 0.01, 0.05)
    orange = ts.vec(1.19, 1.04, 0.98)
    return ti.sqrt(ts.mix(blue, orange, rgb))
    def apply_transfer_function(self, intensity: float):
        ''' Applies a 1D transfer function to a given intensity value

        Args:
            intensity (float): Intensity in [0,1]

        Returns:
            tl.vec4: Color and opacity for given `intensity`
        '''
        length = ti.static(float(self.tf_tex.shape[0] - 1))
        low, high, frac = low_high_frac(intensity * length)
        return tl.mix(
            self.tf_tex[low],
            self.tf_tex[min(high, ti.static(self.tf_tex.shape[0] - 1))], frac)
示例#10
0
    def cube(self, a, b):
        aaa = self.add_v(tl.mix(a, b, tl.D.yyy))
        baa = self.add_v(tl.mix(a, b, tl.D.xyy))
        aba = self.add_v(tl.mix(a, b, tl.D.yxy))
        aab = self.add_v(tl.mix(a, b, tl.D.yyx))
        bba = self.add_v(tl.mix(a, b, tl.D.xxy))
        abb = self.add_v(tl.mix(a, b, tl.D.yxx))
        bab = self.add_v(tl.mix(a, b, tl.D.xyx))
        bbb = self.add_v(tl.mix(a, b, tl.D.xxx))

        self.add_f4([aaa, aba, bba, baa])  # back
        self.add_f4([aab, bab, bbb, abb])  # front
        self.add_f4([aaa, aab, abb, aba])  # left
        self.add_f4([baa, bba, bbb, bab])  # right
        self.add_f4([aaa, baa, bab, aab])  # bottom
        self.add_f4([aba, abb, bbb, bba])  # top
示例#11
0
 def raycast(self, sampling_rate: float):
     ''' Produce a rendering. Run compute_entry_exit first! '''
     for i, j in self.valid_sample_step_count:  # For all pixels
         for sample_idx in range(self.sample_step_nums[i, j]):
             look_from = self.cam_pos[None]
             if self.render_tape[i, j, sample_idx -
                                 1].w < 0.99 and sample_idx < ti.static(
                                     self.max_samples):
                 tmax = self.exit[i, j]
                 n_samples = self.sample_step_nums[i, j]
                 ray_len = (tmax - self.entry[i, j])
                 tmin = self.entry[
                     i,
                     j] + 0.5 * ray_len / n_samples  # Offset tmin as t_start
                 vd = self.rays[i, j]
                 pos = look_from + tl.mix(
                     tmin, tmax,
                     float(sample_idx) /
                     float(n_samples - 1)) * vd  # Current Pos
                 light_pos = look_from + tl.vec3(0.0, 1.0, 0.0)
                 intensity = self.sample_volume_trilinear(pos)
                 sample_color = self.apply_transfer_function(intensity)
                 opacity = 1.0 - ti.pow(1.0 - sample_color.w,
                                        1.0 / sampling_rate)
                 # if sample_color.w > 1e-3:
                 normal = self.get_volume_normal(pos)
                 light_dir = (
                     pos -
                     light_pos).normalized()  # Direction to light source
                 n_dot_l = max(normal.dot(light_dir), 0.0)
                 diffuse = self.diffuse * n_dot_l
                 r = tl.reflect(light_dir,
                                normal)  # Direction of reflected light
                 r_dot_v = max(r.dot(-vd), 0.0)
                 specular = self.specular * pow(r_dot_v, self.shininess)
                 shaded_color = tl.vec4(
                     ti.min(1.0, diffuse + specular + self.ambient) *
                     sample_color.xyz * opacity * self.light_color, opacity)
                 self.render_tape[i, j, sample_idx] = (
                     1.0 - self.render_tape[i, j, sample_idx - 1].w
                 ) * shaded_color + self.render_tape[i, j, sample_idx - 1]
                 self.valid_sample_step_count[i, j] += 1
             else:
                 self.render_tape[i, j, sample_idx] = self.render_tape[
                     i, j, sample_idx - 1]
示例#12
0
    def raycast_nondiff(self, sampling_rate: float):
        ''' Raycasts in a non-differentiable (but faster and cleaner) way. Use `get_final_image_nondiff` with this.

        Args:
            sampling_rate (float): Sampling rate (multiplier with Nyquist frequence)
        '''
        for i, j in self.valid_sample_step_count:  # For all pixels
            for cnt in range(self.sample_step_nums[i, j]):
                look_from = self.cam_pos[None]
                if self.render_tape[i, j, 0].w < 0.99:
                    tmax = self.exit[i, j]
                    n_samples = self.sample_step_nums[i, j]
                    ray_len = (tmax - self.entry[i, j])
                    tmin = self.entry[
                        i,
                        j] + 0.5 * ray_len / n_samples  # Offset tmin as t_start
                    vd = self.rays[i, j]
                    pos = look_from + tl.mix(
                        tmin, tmax,
                        float(cnt) / float(n_samples - 1)) * vd  # Current Pos
                    light_pos = look_from + tl.vec3(0.0, 1.0, 0.0)
                    intensity = self.sample_volume_trilinear(pos)
                    sample_color = self.apply_transfer_function(intensity)
                    opacity = 1.0 - ti.pow(1.0 - sample_color.w,
                                           1.0 / sampling_rate)
                    if sample_color.w > 1e-3:
                        normal = self.get_volume_normal(pos)
                        light_dir = (pos - light_pos).normalized(
                        )  # Direction to light source
                        n_dot_l = max(normal.dot(light_dir), 0.0)
                        diffuse = self.diffuse * n_dot_l
                        r = tl.reflect(light_dir,
                                       normal)  # Direction of reflected light
                        r_dot_v = max(r.dot(-vd), 0.0)
                        specular = self.specular * pow(r_dot_v, self.shininess)
                        shaded_color = tl.vec4(
                            (diffuse + specular + self.ambient) *
                            sample_color.xyz * opacity * self.light_color,
                            opacity)
                        self.render_tape[
                            i, j,
                            0] = (1.0 - self.render_tape[i, j, 0].w
                                  ) * shaded_color + self.render_tape[i, j, 0]
示例#13
0
def noise(x):
    i = ti.floor(x)
    f = fract(x)
    u = f * f * (3.0 - 2.0 * f)

    v1 = ts.mix(hash(i + ti.Vector([0.0, 0.0, 0.0])),
                hash(i + ti.Vector([1.0, 0.0, 0.0])), u[0])
    v2 = ts.mix(hash(i + ti.Vector([0.0, 1.0, 0.0])),
                hash(i + ti.Vector([1.0, 1.0, 0.0])), u[0])
    v12 = ts.mix(v1, v2, u[1])

    v3 = ts.mix(hash(i + ti.Vector([0.0, 0.0, 1.0])),
                hash(i + ti.Vector([1.0, 0.0, 1.0])), u[0])
    v4 = ts.mix(hash(i + ti.Vector([0.0, 1.0, 1.0])),
                hash(i + ti.Vector([1.0, 1.0, 1.0])), u[0])
    v34 = ts.mix(v3, v4, u[1])

    return ts.mix(v12, v34, u[2])
示例#14
0
 def pre_process(self, color):
     blue = ts.vec3(0.00, 0.01, 0.05)
     orange = ts.vec3(1.19, 1.04, 0.98)
     return ti.sqrt(ts.mix(blue, orange, color))
示例#15
0
 def frensel(self, view, halfway, color):
     f0 = ts.mix(ts.vec3(self.specular), color, self.metallic)
     hdotv = min(1, max(ti.dot(halfway, view), 0))
     return (f0 + (1.0 - f0) * (1.0 - hdotv)**5) * self.ks