Ejemplo n.º 1
0
def test05_scalar(t):
    if not ek.is_array_v(t) or ek.array_size_v(t) == 0:
        return
    get_class(t.__module__)

    if ek.is_mask_v(t):
        assert ek.all_nested(t(True))
        assert ek.any_nested(t(True))
        assert ek.none_nested(t(False))
        assert ek.all_nested(t(False) ^ t(True))
        assert ek.all_nested(ek.eq(t(False), t(False)))
        assert ek.none_nested(ek.eq(t(True), t(False)))

    if ek.is_arithmetic_v(t):
        assert t(1) + t(1) == t(2)
        assert t(3) - t(1) == t(2)
        assert t(2) * t(2) == t(4)
        assert ek.min(t(2), t(3)) == t(2)
        assert ek.max(t(2), t(3)) == t(3)

        if ek.is_signed_v(t):
            assert t(2) * t(-2) == t(-4)
            assert ek.abs(t(-2)) == t(2)

        if ek.is_integral_v(t):
            assert t(6) // t(2) == t(3)
            assert t(7) % t(2) == t(1)
            assert t(7) >> 1 == t(3)
            assert t(7) << 1 == t(14)
            assert t(1) | t(2) == t(3)
            assert t(1) ^ t(3) == t(2)
            assert t(1) & t(3) == t(1)
        else:
            assert t(6) / t(2) == t(3)
            assert ek.sqrt(t(4)) == t(2)
            assert ek.fmadd(t(1), t(2), t(3)) == t(5)
            assert ek.fmsub(t(1), t(2), t(3)) == t(-1)
            assert ek.fnmadd(t(1), t(2), t(3)) == t(1)
            assert ek.fnmsub(t(1), t(2), t(3)) == t(-5)
            assert (t(1) & True) == t(1)
            assert (t(1) & False) == t(0)
            assert (t(1) | False) == t(1)

        assert ek.all_nested(t(3) > t(2))
        assert ek.all_nested(ek.eq(t(2), t(2)))
        assert ek.all_nested(ek.neq(t(3), t(2)))
        assert ek.all_nested(t(1) >= t(1))
        assert ek.all_nested(t(2) < t(3))
        assert ek.all_nested(t(1) <= t(1))
        assert ek.select(ek.eq(t(2), t(2)), t(4), t(5)) == t(4)
        assert ek.select(ek.eq(t(3), t(2)), t(4), t(5)) == t(5)
        t2 = t(2)
        assert ek.hsum(t2) == t.Value(2 * len(t2))
        assert ek.dot(t2, t2) == t.Value(4 * len(t2))
        assert ek.dot_async(t2, t2) == t(4 * len(t2))

        value = t(1)
        value[ek.eq(value, t(1))] = t(2)
        value[ek.eq(value, t(3))] = t(5)
        assert value == t(2)
Ejemplo n.º 2
0
def quat_to_euler(q):
    name = _ek.detail.array_name('Array', q.Type, [3], q.IsScalar)
    module = _modules.get(q.__module__)
    Array3f = getattr(module, name)

    sinp = 2 * _ek.fmsub(q.w, q.y, q.z * q.x)
    gimbal_lock = _ek.abs(sinp) > (1.0 - 5e-8)

    # roll (x-axis rotation)
    q_y_2 = _ek.sqr(q.y)
    sinr_cosp = 2 * _ek.fmadd(q.w, q.x, q.y * q.z)
    cosr_cosp = _ek.fnmadd(2, _ek.fmadd(q.x, q.x, q_y_2), 1)
    roll = _ek.select(gimbal_lock, 2 * _ek.atan2(q.x, q.w),
                      _ek.atan2(sinr_cosp, cosr_cosp))

    # pitch (y-axis rotation)
    pitch = _ek.select(gimbal_lock, _ek.copysign(0.5 * _ek.Pi, sinp),
                       _ek.asin(sinp))

    # yaw (z-axis rotation)
    siny_cosp = 2 * _ek.fmadd(q.w, q.z, q.x * q.y)
    cosy_cosp = _ek.fnmadd(2, _ek.fmadd(q.z, q.z, q_y_2), 1)
    yaw = _ek.select(gimbal_lock, 0, _ek.atan2(siny_cosp, cosy_cosp))

    return Array3f(roll, pitch, yaw)
Ejemplo n.º 3
0
 def fallof(self, cosTheta):
     # delta = (cosTheta - self.cosTotalWidth)/(self.cosFallOffStart - self.cosTotalWidth)
     delta = (self.cutOffAngle -
              ek.acos(cosTheta)) * self.m_invTransitionWidth
     delta = ek.select(cosTheta > self.cosFallOffStart,
                       ek.full(type(delta), 1), delta)
     delta = ek.select(cosTheta < self.cosTotalWidth, ek.zero(type(delta)),
                       delta)
     return delta
Ejemplo n.º 4
0
def test_sample_direction(variant_scalar_spectral, spectrum_key, it_pos,
                          wavelength_sample, cutoff_angle, lookat):
    # Check the correctness of the sample_direction() method

    import math
    from mitsuba.core import sample_shifted, Transform4f
    from mitsuba.render import SurfaceInteraction3f

    cutoff_angle_rad = math.radians(cutoff_angle)
    beam_width_rad = cutoff_angle_rad * 0.75
    inv_transition_width = 1 / (cutoff_angle_rad - beam_width_rad)
    emitter, spectrum = create_emitter_and_spectrum(lookat, cutoff_angle,
                                                    spectrum_key)
    eval_t = 0.3
    trafo = Transform4f(emitter.world_transform().eval(eval_t))

    # Create a surface iteration
    it = SurfaceInteraction3f.zero()
    it.p = it_pos
    it.time = eval_t

    # Sample a wavelength from spectrum
    wav, spec = spectrum.sample(it, sample_shifted(wavelength_sample))
    it.wavelengths = wav

    # Direction from the position to the point emitter
    d = -it.p + lookat["pos"]
    dist = ek.norm(d)
    d /= dist

    # Calculate angle between lookat direction and ray direction
    angle = ek.acos((trafo.inverse().transform_vector(-d))[2])
    angle = ek.select(
        ek.abs(angle - beam_width_rad) < 1e-3, beam_width_rad, angle)
    angle = ek.select(
        ek.abs(angle - cutoff_angle_rad) < 1e-3, cutoff_angle_rad, angle)

    # Sample a direction from the emitter
    ds, res = emitter.sample_direction(it, [0, 0])

    # Evalutate the spectrum
    spec = spectrum.eval(it)
    spec = ek.select(
        angle <= beam_width_rad, spec,
        spec * ((cutoff_angle_rad - angle) * inv_transition_width))
    spec = ek.select(angle <= cutoff_angle_rad, spec, 0)

    assert ds.time == it.time
    assert ds.pdf == 1.0
    assert ds.delta
    assert ek.allclose(ds.d, d)
    assert ek.allclose(res, spec / (dist**2))
Ejemplo n.º 5
0
def test_sample_ray(variant_packet_spectral, spectrum_key, wavelength_sample,
                    pos_sample, cutoff_angle, lookat):
    # Check the correctness of the sample_ray() method

    import math
    from mitsuba.core import warp, sample_shifted, Transform4f
    from mitsuba.render import SurfaceInteraction3f

    cutoff_angle_rad = math.radians(cutoff_angle)
    cos_cutoff_angle_rad = math.cos(cutoff_angle_rad)
    beam_width_rad = cutoff_angle_rad * 0.75
    inv_transition_width = 1 / (cutoff_angle_rad - beam_width_rad)
    emitter, spectrum = create_emitter_and_spectrum(lookat, cutoff_angle,
                                                    spectrum_key)
    eval_t = 0.3
    trafo = Transform4f(emitter.world_transform().eval(eval_t))

    # Sample a local direction and calculate local angle
    dir_sample = pos_sample  # not being used anyway
    local_dir = warp.square_to_uniform_cone(pos_sample, cos_cutoff_angle_rad)
    angle = ek.acos(local_dir[2])
    angle = ek.select(
        ek.abs(angle - beam_width_rad) < 1e-3, beam_width_rad, angle)
    angle = ek.select(
        ek.abs(angle - cutoff_angle_rad) < 1e-3, cutoff_angle_rad, angle)

    # Sample a ray (position, direction, wavelengths) from the emitter
    ray, res = emitter.sample_ray(eval_t, wavelength_sample, pos_sample,
                                  dir_sample)

    # Sample wavelengths on the spectrum
    it = SurfaceInteraction3f.zero()
    wav, spec = spectrum.sample(it, sample_shifted(wavelength_sample))
    it.wavelengths = wav
    spec = spectrum.eval(it)
    spec = ek.select(
        angle <= beam_width_rad, spec,
        spec * ((cutoff_angle_rad - angle) * inv_transition_width))
    spec = ek.select(angle <= cutoff_angle_rad, spec, 0)

    assert ek.allclose(
        res, spec / warp.square_to_uniform_cone_pdf(
            trafo.inverse().transform_vector(ray.d), cos_cutoff_angle_rad))
    assert ek.allclose(ray.time, eval_t)
    assert ek.all(local_dir.z >= cos_cutoff_angle_rad)
    assert ek.allclose(ray.wavelengths, wav)
    assert ek.allclose(ray.d, trafo.transform_vector(local_dir))
    assert ek.allclose(ray.o, lookat["pos"])
Ejemplo n.º 6
0
def test16_custom(cname):
    t = get_class(cname)

    v1 = ek.zero(t, 100)
    v2 = ek.empty(t, 100)
    assert len(v1.state) == 100
    assert len(v2.inc) == 100

    v2.state = v1.state
    v1.state = ek.arange(type(v1.state), 100)
    v3 = ek.select(v1.state < 10, v1, v2)
    assert v3.state[3] == 3
    assert v3.state[11] == 0

    assert ek.width(v3) == 100
    v4 = ek.zero(t, 1)
    ek.schedule(v4)
    ek.resize(v4, 200)
    assert ek.width(v4) == 200

    assert ek.width(v3) == 100
    v4 = ek.zero(t, 1)
    ek.resize(v4, 200)
    assert ek.width(v4) == 200

    index = ek.arange(type(v1.state), 100)
    ek.scatter(v4, v1, index)
    v5 = ek.gather(t, v4, index)
    ek.eval(v5)
    assert v5.state == v1.state and v5.inc == v1.inc
Ejemplo n.º 7
0
    def eval(self, si, active):
        cosTheta = ek.dot(si.wi, si.n)

        tmp2 = ek.select(Frame3f.cos_theta(si.wi) > 0, \
                self.m_radiance.eval(si, active)*self.fallof(cosTheta), \
                float(0))
        return tmp2
Ejemplo n.º 8
0
 def collatz(value: p.Int):
     counter = p.Int(0)
     loop = p.Loop(value, counter)
     while (loop.cond(ek.neq(value, 1))):
         is_even = ek.eq(value & 1, 0)
         value.assign(ek.select(is_even, value // 2, 3 * value + 1))
         counter += 1
     return counter
Ejemplo n.º 9
0
 def pdf_direction(self, ref, ds, active):
     # as the shape init happens after the emitter init
     if (not (hasattr(self, "m_shape"))):
         self.set_shape_area()
     tmp3 = ek.select(
         ek.dot(ds.d, ds.n) < 0,
         self.m_shape.pdf_direction(ref, ds, active), float(0))
     return tmp3
Ejemplo n.º 10
0
    def pdf(self, ctx, si, wo, active):
        if not ctx.is_enabled(BSDFFlags.DiffuseReflection):
            return Vector3f(0)

        cos_theta_i = Frame3f.cos_theta(si.wi)
        cos_theta_o = Frame3f.cos_theta(wo)

        pdf = warp.square_to_cosine_hemisphere_pdf(wo)

        return ek.select((cos_theta_i > 0.0) & (cos_theta_o > 0.0), pdf, 0.0)
Ejemplo n.º 11
0
    def eval(self, ctx, si, wo, active):
        if not ctx.is_enabled(BSDFFlags.DiffuseReflection):
            return Vector3f(0)

        cos_theta_i = Frame3f.cos_theta(si.wi)
        cos_theta_o = Frame3f.cos_theta(wo)

        value = self.m_reflectance.eval(si, active) * math.InvPi * cos_theta_o

        return ek.select((cos_theta_i > 0.0) & (cos_theta_o > 0.0), value,
                         Vector3f(0))
    def sample(self, ctx, si, sample1, sample2, active):
        bs = BSDFSample3f()
        bs.wo = mr.retro_transmit(si.wi)
        bs.pdf = 1
        bs.sampled_type = +BSDFFlags.DeltaTransmission
        bs.sampled_component = 0
        bs.eta = 1

        value = self.m_retro_transmittance.eval(si, active)

        return (bs, ek.select(active, value, 0))
Ejemplo n.º 13
0
    def sincos(x):
        Float = type(x)
        Int = ek.int_array_t(Float)

        xa = ek.abs(x)

        j = Int(xa * 1.2732395447351626862)

        j = (j + Int(1)) & ~Int(1)

        y = Float(j)

        Shift = Float.Type.Size * 8 - 3

        sign_sin = ek.reinterpret_array(Float, j << Shift) ^ x
        sign_cos = ek.reinterpret_array(Float, (~(j - Int(2)) << Shift))

        y = xa - y * 0.78515625 \
               - y * 2.4187564849853515625e-4 \
               - y * 3.77489497744594108e-8

        z = y * y
        z |= ek.eq(xa, ek.Infinity)

        s = poly2(z, -1.6666654611e-1,
                  8.3321608736e-3,
                  -1.9515295891e-4) * z

        c = poly2(z, 4.166664568298827e-2,
                  -1.388731625493765e-3,
                  2.443315711809948e-5) * z

        s = ek.fmadd(s, y, y)
        c = ek.fmadd(c, z, ek.fmadd(z, -0.5, 1))

        polymask = ek.eq(j & Int(2), ek.zero(Int))

        return (
            ek.mulsign(ek.select(polymask, s, c), sign_sin),
            ek.mulsign(ek.select(polymask, c, s), sign_cos)
        )
Ejemplo n.º 14
0
def integrator_sample(scene, sampler, rays, medium, active=True):
    si = scene.ray_intersect(rays)
    active = si.is_valid() & active

    # Visible emitters
    emitter_vis = si.emitter(scene, active)
    result = ek.select(active, Emitter.eval_vec(emitter_vis, si, active), Vector3f(0.0))

    ctx = BSDFContext()
    bsdf = si.bsdf(rays)

    # Emitter sampling
    sample_emitter = active & has_flag(BSDF.flags_vec(bsdf), BSDFFlags.Smooth)
    ds, emitter_val = scene.sample_emitter_direction(si, sampler.next_2d(sample_emitter), True, sample_emitter)
    active_e = sample_emitter & ek.neq(ds.pdf, 0.0)
    wo = si.to_local(ds.d)
    bsdf_val = BSDF.eval_vec(bsdf, ctx, si, wo, active_e)
    bsdf_pdf = BSDF.pdf_vec(bsdf, ctx, si, wo, active_e)
    mis = ek.select(ds.delta, Float(1), mis_weight(ds.pdf, bsdf_pdf))
    result += ek.select(active_e, emitter_val * bsdf_val * mis, Vector3f(0))

    # BSDF sampling
    active_b = active
    bs, bsdf_val = BSDF.sample_vec(bsdf, ctx, si, sampler.next_1d(active), sampler.next_2d(active), active_b)
    si_bsdf = scene.ray_intersect(si.spawn_ray(si.to_world(bs.wo)), active_b)
    emitter = si_bsdf.emitter(scene, active_b)
    active_b &= ek.neq(emitter, 0)
    emitter_val = Emitter.eval_vec(emitter, si_bsdf, active_b)
    delta = has_flag(bs.sampled_type, BSDFFlags.Delta)
    ds = DirectionSample3f(si_bsdf, si)
    ds.object = emitter
    emitter_pdf = ek.select(delta, Float(0), scene.pdf_emitter_direction(si, ds, active_b))
    result += ek.select(active_b, bsdf_val * emitter_val * mis_weight(bs.pdf, emitter_pdf), Vector3f(0))
    return result, si.is_valid(), ek.select(si.is_valid(), si.t, Float(0.0))
Ejemplo n.º 15
0
def matrix_to_quat(m):
    if not _ek.is_matrix_v(m):
        raise Exception('Unsupported type!')

    name = _ek.detail.array_name('Quaternion', m.Type, [4], m.IsScalar)
    module = _modules.get(m.__module__)
    Quat4f = getattr(module, name)

    o = 1.0
    t0 = o + m[0, 0] - m[1, 1] - m[2, 2]
    q0 = Quat4f(t0, m[1, 0] + m[0, 1], m[0, 2] + m[2, 0], m[2, 1] - m[1, 2])

    t1 = o - m[0, 0] + m[1, 1] - m[2, 2]
    q1 = Quat4f(m[1, 0] + m[0, 1], t1, m[2, 1] + m[1, 2], m[0, 2] - m[2, 0])

    t2 = o - m[0, 0] - m[1, 1] + m[2, 2]
    q2 = Quat4f(m[0, 2] + m[2, 0], m[2, 1] + m[1, 2], t2, m[1, 0] - m[0, 1])

    t3 = o + m[0, 0] + m[1, 1] + m[2, 2]
    q3 = Quat4f(m[2, 1] - m[1, 2], m[0, 2] - m[2, 0], m[1, 0] - m[0, 1], t3)

    mask0 = m[0, 0] > m[1, 1]
    t01 = _ek.select(mask0, t0, t1)
    q01 = _ek.select(mask0, q0, q1)

    mask1 = m[0, 0] < -m[1, 1]
    t23 = _ek.select(mask1, t2, t3)
    q23 = _ek.select(mask1, q2, q3)

    mask2 = m[2, 2] < 0.0
    t0123 = _ek.select(mask2, t01, t23)
    q0123 = _ek.select(mask2, q01, q23)

    return q0123 * (_ek.rsqrt(t0123) * 0.5)
Ejemplo n.º 16
0
    def eval(self, ctx, si, wo, active):
        """
        Emitter sampling
        """
        if not ctx.is_enabled(BSDFFlags.DiffuseReflection):
            return Vector3f(0)

        cos_theta_i = Frame3f.cos_theta(si.wi) 
        cos_theta_o = Frame3f.cos_theta(wo)

        value = self.get_btf(si.wi, wo, si.uv) * math.InvPi

        return ek.select((cos_theta_i > 0.0) & (cos_theta_o > 0.0), value, Vector3f(0))
Ejemplo n.º 17
0
    def estimate(self, in_pos, im, props, sigma_n, active):
        """
        Estimate output position and absorption with VAE
        Notice that the types of arguments are in pytorch (tensor) except sigma_n, but the ones of returns are in mitsuba (Vector3f, Float)
        Args:
            in_pos: Incident position in local mesh coordinates, and the type of this is tensor
            im: Height map around incident position ranging to multiple of sigma_n.
                This map can be generated by clip_scaled_map() from data_handler, and the type is tensor
            props: Medium properties vector including (and following this order)
                   - effective albedo
                   - g
                   - eta
                   - incident angle (xyz)
                   - max height
                   , and the type of this argument is tensor
            sigma_n: Standard deviation of the range of medium scattering.
                     In this method, this value is used as scale factor of coordinates in vae
            active: Boolean mask which indicates whether a ray is applied VAE or not

        Return:
            recon_pos: estimated outgoing position (Vector3f)
            recon_abs: estimated absorption probability (Spectrum)
        """

        n_sample, _, _, _ = im.shape
        pos = Vector3f(in_pos)
        abs_prob = Float().zero(n_sample)

        self.model.eval()

        with torch.no_grad():
            # Feature conversion
            feature = self.model.feature_conversion(
                im.to(self.device, dtype=torch.float),
                props.to(self.device, dtype=torch.float))

            # Sample latent variable from normal distribution
            z = torch.randn(n_sample, 4).to(self.device, dtype=torch.float)

            # Decode and get reconstructed position and absorption
            recon_pos, recon_abs = self.model.decode(feature, z)

        # Convert from tensor to Vector3f and Float
        recon_pos = Vector3f(recon_pos)
        abs_prob = Spectrum(recon_abs.view(1, -1).squeeze())

        # Reconstruct real scale position in mesh local coordinates
        pos += ek.select(active, sigma_n * recon_pos, 0)

        return pos, abs_prob
Ejemplo n.º 18
0
def test47_nan_propagation(m):
    for i in range(2):
        x = ek.arange(m.Float, 10)
        ek.enable_grad(x)
        f0 = m.Float(0)
        y = ek.select(x < (20 if i == 0 else 0), x, x * (f0 / f0))
        ek.backward(y)
        g = ek.grad(x)
        if i == 0:
            assert g == 1
        else:
            assert ek.all(ek.isnan(g))

    for i in range(2):
        x = ek.arange(m.Float, 10)
        ek.enable_grad(x)
        f0 = m.Float(0)
        y = ek.select(x < (20 if i == 0 else 0), x, x * (f0 / f0))
        ek.forward(x)
        g = ek.grad(y)
        if i == 0:
            assert g == 1
        else:
            assert ek.all(ek.isnan(g))
Ejemplo n.º 19
0
def sqrt_(a0):
    if not a0.IsFloat:
        raise Exception("sqrt(): requires floating point operands!")
    ar, sr = _check1(a0)
    if not a0.IsSpecial:
        for i in range(sr):
            ar[i] = _ek.sqrt(a0[i])
    elif a0.IsComplex:
        n = abs(a0)
        m = a0.real >= 0
        zero = _ek.eq(n, 0)
        t1 = _ek.sqrt(.5 * (n + abs(a0.real)))
        t2 = .5 * a0.imag / t1
        im = _ek.select(m, t2, _ek.copysign(t1, a0.imag))
        ar.real = _ek.select(m, t1, abs(t2))
        ar.imag = _ek.select(zero, 0, im)
    elif a0.IsQuaternion:
        ri = _ek.norm(a0.imag)
        cs = _ek.sqrt(a0.Complex(a0.real, ri))
        ar.imag = a0.imag * (_ek.rcp(ri) * cs.imag)
        ar.real = cs.real
    else:
        raise Exception("sqrt(): unsupported array type!")
    return ar
Ejemplo n.º 20
0
    def sample(self, ctx, si, sample1, sample2, active):
        cos_theta_i = Frame3f.cos_theta(si.wi)

        active &= cos_theta_i > 0

        bs = BSDFSample3f()
        bs.wo = warp.square_to_cosine_hemisphere(sample2)
        bs.pdf = warp.square_to_cosine_hemisphere_pdf(bs.wo)
        bs.eta = 1.0
        bs.sampled_type = +BSDFFlags.DiffuseReflection
        bs.sampled_component = 0

        value = self.m_reflectance.eval(si, active)

        return (bs, ek.select(active & (bs.pdf > 0.0), value, Vector3f(0)))
Ejemplo n.º 21
0
    def sample_bssrdf(self, scene, bsdf, bs, si, bdata, heightmap_pybind,
                      channel, active):
        """
        Get projected sample position and absorption probability form VAE BSSRDF

        Args:
            scene: rendered scene object
            bsdf: BSDF information of each ray
            bs: BSDF Sample object of each ray
            si: Surface interaction object of each ray
            bdata: BSSRDF data object in scene data from data_pipeline.py
            channel: RGB channel of interest
                TODO: Support multi channel sampling
            active: Mask data whether a ray needs to process BSSRDF or not

        Returns:
            projected_si: Projected surface interaction object from BSSRDF
            proj_suc: Mask data indicating projection succeed or not
            abs_recon: absorption probability from BSSRDF
        """

        # Get ID of BSSDRF mesh for each sur face interactions
        mesh_id = BSDF.mesh_id_vec(bsdf, active)

        # Convert incident position into local coordinates of mesh of interested as tensor
        in_pos = ek.select(active, si.to_mesh_local(bs), Vector3f(0))

        # Get properties, e.g., medium params and incident angle as tensor
        props, sigma_n = get_props(bs, si, channel)

        # Get height map around incident position as tensor
        im_bind = heightmap_pybind.get_height_map(in_pos.torch().cpu(),
                                                  mesh_id.torch().cpu())
        im = torch.tensor(im_bind)

        # Estimate position and absorption probability with VAE as mitsuba types
        recon_pos_local, abs_recon = self.estimate(in_pos.torch(), im, props,
                                                   sigma_n, active)

        # Convert from mesh coordinates to world coordinates
        recon_pos_world = si.to_mesh_world(bs, recon_pos_local)

        # Project estimated position onto nearest mesh
        projected_si, proj_suc = si.project_to_mesh_normal(
            scene, recon_pos_world, bs, channel, active)

        return projected_si, proj_suc, abs_recon
Ejemplo n.º 22
0
    def sample_direction(self, ref, sample, active):
        # as the shape init happens after the emitter init
        if (not (hasattr(self, "m_shape"))):
            self.set_shape_area()

        ds = self.m_shape.sample_direction(ref, sample, active)

        active &= (ek.dot(ds.d, ds.n) < 0) & (ek.neq(ds.pdf, 0))

        si = SurfaceInteraction3f(ds, ref.wavelengths)
        # spatially varying
        cosTheta = -ek.dot(ds.d, ds.n)
        fall = self.fallof(cosTheta)

        spec = self.m_radiance.eval(si, active) * fall / ds.pdf

        ds.object = 0  # HACK

        return (ds, ek.select(active, spec, ek.zero(type(spec))))
def mis_weight(pdf_a, pdf_b):
    pdf_a *= pdf_a
    pdf_b *= pdf_b
    return ek.select(pdf_a > 0.0, pdf_a / (pdf_a + pdf_b), Float(0.0))
Ejemplo n.º 24
0
def postprocess_render(results,
                       weights,
                       blocks,
                       pos,
                       aovs=False,
                       invalid_sample=False):
    """postprocessing for sampling result"""

    result = results[0]
    valid_rays = results[1]

    result *= weights
    xyz = Color3f(srgb_to_xyz(result))
    aovs_result = [
        xyz[0], xyz[1], xyz[2],
        ek.select(valid_rays, Float(1.0), Float(0.0)), 1.0
    ]

    if not aovs and not invalid_sample:
        block = blocks
    else:
        block = blocks["result"]

    block.put(pos, aovs_result)

    if aovs:
        scatter = results[2]
        non_scatter = results[3]

        scatter *= weights
        non_scatter *= weights

        xyz_scatter = Color3f(srgb_to_xyz(scatter))
        xyz_nonscatter = Color3f(srgb_to_xyz(non_scatter))

        aovs_scatter = [
            xyz_scatter[0], xyz_scatter[1], xyz_scatter[2],
            ek.select(valid_rays, Float(1.0), Float(0.0)), 1.0
        ]
        aovs_nonscatter = [
            xyz_nonscatter[0], xyz_nonscatter[1], xyz_nonscatter[2],
            ek.select(valid_rays, Float(1.0), Float(0.0)), 1.0
        ]

        block_scatter = blocks["scatter"]
        block_nonscatter = blocks["non_scatter"]

        block_scatter.put(pos, aovs_scatter)
        block_nonscatter.put(pos, aovs_nonscatter)

    if invalid_sample:
        invalid = results[4]

        invalid *= weights

        xyz_invalid = Color3f(srgb_to_xyz(invalid))

        aovs_invalid = [
            xyz_invalid[0], xyz_invalid[1], xyz_invalid[2],
            ek.select(valid_rays, Float(1.0), Float(0.0)), 1.0
        ]

        block_invalid = blocks["invalid"]

        block_invalid.put(pos, aovs_invalid)
Ejemplo n.º 25
0
def select_(a0, a1, a2):
    ar, sr = _check3_select(a0, a1, a2)
    for i in range(sr):
        ar[i] = _ek.select(a0[i], a1[i], a2[i])
    return ar
Ejemplo n.º 26
0
    def sample(self, scene, sampler, ray, medium=None, active=True):
        result = Vector3f(0.0)
        si = scene.ray_intersect(ray, active)
        active = si.is_valid() & active

        # emitter = si.emitter(scene)
        # result = ek.select(active, Emitter.eval_vec(emitter, si, active), Vector3f(0.0))

        # z_axis = np.array([0, 0, 1])

        # vertex = si.p.numpy()
        # v_count = vertex.shape[0]
        # vertex = np.expand_dims(vertex, axis=1)
        # vertex = np.repeat(vertex, self.light.vertex_count(), axis=1)

        # light_vertices = self.light.vertex_positions_buffer().numpy().reshape(self.light.vertex_count(), 3)
        # light_vertices = np.expand_dims(light_vertices, axis=0)
        # light_vertices = np.repeat(light_vertices, v_count, axis=0)

        # sph_polygons = light_vertices - vertex
        # sph_polygons = sph_polygons / np.linalg.norm(sph_polygons, axis=2, keepdims=True)

        # z_axis = np.repeat( np.expand_dims(z_axis, axis=0), v_count, axis=0 )
        # result_np = np.zeros(v_count, dtype=np.double)

        # for idx in range( self.light.vertex_count() ):
        #     idx1 = (idx+1) % self.light.vertex_count()
        #     idx2 = (idx) % self.light.vertex_count()

        #     dp = np.sum( sph_polygons[:, idx1, :] * sph_polygons[:, idx2, :], axis=1 )
        #     acos = np.arccos(dp)

        #     cp = np.cross( sph_polygons[:, idx1, :], sph_polygons[:, idx2, :] )
        #     cp = cp / np.linalg.norm(cp, axis=1, keepdims=True)

        #     dp = np.sum( cp * z_axis, axis=1 )

        #     result_np += acos * dp

        # result_np *= 0.5 * 1.0/math.pi
        # result_np = np.repeat( result_np.reshape((v_count, 1)), 3, axis=1 )

        # fin = self.light_radiance * Vector3f(result_np)
        # fin[fin < 0] = 0
        # result += ek.select(active, fin, Vector3f(0.0))

        ctx = BSDFContext()
        bsdf = si.bsdf(ray)

        # bs, bsdf_val = BSDF.sample_vec(bsdf, ctx, si, sampler.next_1d(active), sampler.next_2d(active), active)
        # pdf = bs.pdf
        # wo = si.to_world(bs.wo)

        ds, emitter_val = scene.sample_emitter_direction(
            si, sampler.next_2d(active), True, active)
        pdf = ds.pdf
        active_e = active & ek.neq(ds.pdf, 0.0)
        wo = ds.d
        bsdf_val = BSDF.eval_vec(bsdf, ctx, si, wo, active_e)
        emitter_val[emitter_val > 1.0] = 1.0
        bsdf_val *= emitter_val

        # _, wi_theta, wi_phi = sph_convert(si.to_world(si.wi))
        _, wo_theta, wo_phi = sph_convert(wo)

        y_0_0_ = y_0_0(bsdf_val, wo_theta, wo_phi) / ek.select(
            pdf > 0, pdf, Float(0.01))

        y_1_n1_ = y_1_n1(bsdf_val, wo_theta, wo_phi) / ek.select(
            pdf > 0, pdf, Float(0.01))
        y_1_0_ = y_1_0(bsdf_val, wo_theta, wo_phi) / ek.select(
            pdf > 0, pdf, Float(0.01))
        y_1_p1_ = y_1_p1(bsdf_val, wo_theta, wo_phi) / ek.select(
            pdf > 0, pdf, Float(0.01))

        y_2_n2_ = y_2_n2(bsdf_val, wo_theta, wo_phi) / ek.select(
            pdf > 0, pdf, Float(0.01))
        y_2_n1_ = y_2_n1(bsdf_val, wo_theta, wo_phi) / ek.select(
            pdf > 0, pdf, Float(0.01))
        y_2_0_ = y_2_0(bsdf_val, wo_theta, wo_phi) / ek.select(
            pdf > 0, pdf, Float(0.01))
        y_2_p1_ = y_2_p1(bsdf_val, wo_theta, wo_phi) / ek.select(
            pdf > 0, pdf, Float(0.01))
        y_2_p2_ = y_2_p2(bsdf_val, wo_theta, wo_phi) / ek.select(
            pdf > 0, pdf, Float(0.01))

        return result, si.is_valid(), [ Float(y_0_0_[0]), Float(y_0_0_[1]), Float(y_0_0_[2]),\
                                        Float(y_1_n1_[0]), Float(y_1_n1_[1]), Float(y_1_n1_[2]),\
                                        Float(y_1_0_[0]), Float(y_1_0_[1]), Float(y_1_0_[2]),\
                                        Float(y_1_p1_[0]), Float(y_1_p1_[1]), Float(y_1_p1_[2]),\
                                        Float(y_2_n2_[0]), Float(y_2_n2_[1]), Float(y_2_n2_[2]),\
                                        Float(y_2_n1_[0]), Float(y_2_n1_[1]), Float(y_2_n1_[2]),\
                                        Float(y_2_0_[0]), Float(y_2_0_[1]), Float(y_2_0_[2]),\
                                        Float(y_2_p1_[0]), Float(y_2_p1_[1]), Float(y_2_p1_[2]),\
                                        Float(y_2_p2_[0]), Float(y_2_p2_[1]), Float(y_2_p2_[2]) ]
Ejemplo n.º 27
0
def render_sample(scene, sampler, rays, bdata, heightmap_pybind, bssrdf=None):
    """
    Sample RTE
    TODO: Support multi channel sampling

    Args:
        scene: Target scene object
        sampler: Sampler object for random number
        rays: Given rays for sampling
        bdata: BSSRDF Data object
        heightmap_pybind: Object for getting height map around incident position.
                          Refer src/librender/python/heightmap.cpp

    Returns:
        result: Sampling RTE result
        valid_rays: Mask data whether rays are valid or not
        scatter: Scatter components of Sampling RTE result
        non_scatter: Non scatter components of Sampling RTE result
        invalid_sample: Sampling RTE result with invalid sampled data by VAEBSSRDF
    """

    eta = Float(1.0)
    emission_weight = Float(1.0)
    throughput = Spectrum(1.0)
    result = Spectrum(0.0)
    scatter = Spectrum(0.0)
    non_scatter = Spectrum(0.0)
    invalid_sample = Spectrum(0.0)
    active = True
    is_bssrdf = False

    ##### First interaction #####
    si = scene.ray_intersect(rays, active)
    active = si.is_valid() & active
    valid_rays = si.is_valid()

    emitter = si.emitter(scene, active)

    depth = 0

    # Set channel
    # At and after evaluating BSSRDF, a ray consider only this one channel
    n_channels = 3
    channel = UInt32(
        ek.min(sampler.next_1d(active) * n_channels, n_channels - 1))

    d_out_local = Vector3f().zero()
    d_out_pdf = Float(0)

    sss = Mask(False)

    while (True):
        depth += 1
        if config.aovs and depth == 2:
            sss = is_bssrdf

        ##### Interaction with emitters #####
        emission_val = emission_weight * throughput * Emitter.eval_vec(
            emitter, si, active)

        result += ek.select(active, emission_val, Spectrum(0.0))
        invalid_sample += ek.select(active, emission_val, Spectrum(0.0))
        scatter += ek.select(active & sss, emission_val, Spectrum(0.0))
        non_scatter += ek.select(active & ~sss, emission_val, Spectrum(0.0))

        active = active & si.is_valid()

        # Process russian roulette
        if depth > config.rr_depth:
            q = ek.min(ek.hmax(throughput) * ek.sqr(eta), 0.95)
            active = active & (sampler.next_1d(active) < q)
            throughput *= ek.rcp(q)

        # Stop if the number of bouces exceeds the given limit bounce, or
        # all rays are invalid. latter check is done only when the limit
        # bounce is infinite
        if depth >= config.max_depth:
            break

        ##### Emitter sampling #####
        bsdf = si.bsdf(rays)
        ctx = BSDFContext()

        active_e = active & has_flag(BSDF.flags_vec(bsdf), BSDFFlags.Smooth)
        ds, emitter_val = scene.sample_emitter_direction(
            si, sampler.next_2d(active_e), True, active_e)
        active_e &= ek.neq(ds.pdf, 0.0)

        # Query the BSDF for that emitter-sampled direction
        wo = si.to_local(ds.d)
        bsdf_val = BSDF.eval_vec(bsdf, ctx, si, wo, active_e)
        # Determine density of sampling that same direction using BSDF sampling
        bsdf_pdf = BSDF.pdf_vec(bsdf, ctx, si, wo, active_e)

        mis = ek.select(ds.delta, Float(1), mis_weight(ds.pdf, bsdf_pdf))

        emission_val = mis * throughput * bsdf_val * emitter_val

        result += ek.select(active, emission_val, Spectrum(0.0))
        invalid_sample += ek.select(active, emission_val, Spectrum(0.0))
        scatter += ek.select(active & sss, emission_val, Spectrum(0.0))
        non_scatter += ek.select(active & ~sss, emission_val, Spectrum(0.0))

        ##### BSDF sampling #####
        bs, bsdf_val = BSDF.sample_vec(bsdf, ctx, si, sampler.next_1d(active),
                                       sampler.next_2d(active), active)

        ##### BSSRDF replacing #####
        if (config.enable_bssrdf):
            # Replace bsdf samples by ones of BSSRDF
            bs.wo = ek.select(is_bssrdf, d_out_local, bs.wo)
            bs.pdf = ek.select(is_bssrdf, d_out_pdf, bs.pdf)
            bs.sampled_component = ek.select(is_bssrdf, UInt32(1),
                                             bs.sampled_component)
            bs.sampled_type = ek.select(is_bssrdf,
                                        UInt32(+BSDFFlags.DeltaTransmission),
                                        bs.sampled_type)
        ############################

        throughput *= ek.select(is_bssrdf, Float(1.0), bsdf_val)
        active &= ek.any(ek.neq(throughput, 0))

        eta *= bs.eta

        # Intersect the BSDF ray against the scene geometry
        rays = RayDifferential3f(si.spawn_ray(si.to_world(bs.wo)))
        si_bsdf = scene.ray_intersect(rays, active)

        ##### Checking BSSRDF #####
        if (config.enable_bssrdf):
            # Whether the BSDF is BSS   RDF or not?
            is_bssrdf = (active
                         & has_flag(BSDF.flags_vec(bsdf), BSDFFlags.BSSRDF)
                         & (Frame3f.cos_theta(bs.wo) < Float(0.0))
                         & (Frame3f.cos_theta(si.wi) > Float(0.0)))

            # Decide whether we should use 0-scattering or multiple scattering
            is_zero_scatter = utils_render.check_zero_scatter(
                sampler, si_bsdf, bs, channel, is_bssrdf)
            is_bssrdf = is_bssrdf & ~is_zero_scatter

            throughput *= ek.select(is_bssrdf, ek.sqr(bs.eta), Float(1.0))
        ###########################

        ###### Process for BSSRDF ######
        if (config.enable_bssrdf and not ek.none(is_bssrdf)):
            # Get projected samples from BSSRDF
            projected_si, project_suc, abs_prob = bssrdf.sample_bssrdf(
                scene, bsdf, bs, si, bdata, heightmap_pybind, channel,
                is_bssrdf)

            if config.visualize_invalid_sample and (depth <= 1):
                active = active & (~is_bssrdf | project_suc)
                invalid_sample += ek.select((is_bssrdf & (~project_suc)),
                                            Spectrum([100, 0, 0]),
                                            Spectrum(0.0))

            # Sample outgoing direction from projected position
            d_out_local, d_out_pdf = utils_render.resample_wo(
                sampler, is_bssrdf)
            # Apply absorption probability
            throughput *= ek.select(is_bssrdf,
                                    Spectrum(1) - abs_prob, Spectrum(1))
            # Replace interactions by sampled ones from BSSRDF
            si_bsdf = SurfaceInteraction3f().masked_si(si_bsdf, projected_si,
                                                       is_bssrdf)
        ################################

        # Determine probability of having sampled that same
        # direction using emitter sampling
        emitter = si_bsdf.emitter(scene, active)
        ds = DirectionSample3f(si_bsdf, si)
        ds.object = emitter

        delta = has_flag(bs.sampled_type, BSDFFlags.Delta)
        emitter_pdf = ek.select(delta, Float(0.0),
                                scene.pdf_emitter_direction(si, ds))
        emission_weight = mis_weight(bs.pdf, emitter_pdf)

        si = si_bsdf

    return result, valid_rays, scatter, non_scatter, invalid_sample