Beispiel #1
0
def test17_cos(m):
    x = ek.linspace(m.Float, 0.01, 10, 10)
    ek.enable_grad(x)
    y = ek.cos(x)
    ek.backward(y)
    assert ek.allclose(ek.detach(y), ek.cos(ek.detach(x)))
    assert ek.allclose(ek.grad(x), -ek.sin(ek.detach(x)))
Beispiel #2
0
def test05_specular_reflection(variant_scalar_rgb):
    from mitsuba.core import Matrix4f
    from mitsuba.render.mueller import specular_reflection
    import numpy as np

    # Identity matrix (and no phase shift) at perpendicular incidence
    assert ek.allclose(specular_reflection(1, 1.5),   Matrix4f.identity()*0.04)
    assert ek.allclose(specular_reflection(1, 1/1.5), Matrix4f.identity()*0.04)

    # 180 deg phase shift at grazing incidence
    assert ek.allclose(specular_reflection(0, 1.5),   [[1,0,0,0],[0,1,0,0],[0,0,-1,0],[0,0,0,-1]], atol=1e-6)
    assert ek.allclose(specular_reflection(0, 1/1.5), [[1,0,0,0],[0,1,0,0],[0,0,-1,0],[0,0,0,-1]], atol=1e-6)

    # Perfect linear polarization at Brewster's angle
    M = np.zeros((4, 4))
    M[0:2, 0:2] = 0.0739645
    assert ek.allclose(specular_reflection(ek.cos(ek.atan(1/1.5)), 1/1.5), M, atol=1e-6)
    assert ek.allclose(specular_reflection(ek.cos(ek.atan(1.5)), 1.5), M, atol=1e-6)

    # 180 deg phase shift just below Brewster's angle (air -> glass)
    M = specular_reflection(ek.cos(ek.atan(1.5)+1e-4), 1.5)
    assert M[0, 0] > 0 and M[1, 1] > 0 and M[2, 2] < 0 and M[3, 3] < 0
    M = specular_reflection(ek.cos(ek.atan(1/1.5)+1e-4), 1/1.5)
    assert M[0, 0] > 0 and M[1, 1] > 0 and M[2, 2] < 0 and M[3, 3] < 0

    # Complex phase shift in the total internal reflection case
    eta = 1/1.5
    cos_theta_min = ek.sqrt((1 - eta**2) / (1 + eta**2))
    M = specular_reflection(cos_theta_min, eta).numpy()
    assert np.all(M[0:2, 2:4] == 0) and np.all(M[2:4, 0:2] == 0) and ek.allclose(M[0:2, 0:2], np.eye(2), atol=1e-6)
    phi_delta = 4*ek.atan(eta)
    assert ek.allclose(M[2:4, 2:4], [[ek.cos(phi_delta), ek.sin(phi_delta)], [-ek.sin(phi_delta), ek.cos(phi_delta)]])
def test02_unit_frame(variant_scalar_rgb):
    from mitsuba.core import Frame3f, Vector2f, Vector3f

    for theta in [30 * mitsuba.core.math.Pi / 180, 95 * mitsuba.core.math.Pi / 180]:
        phi = 73 * mitsuba.core.math.Pi / 180
        sin_theta, cos_theta = ek.sin(theta), ek.cos(theta)
        sin_phi, cos_phi = ek.sin(phi), ek.cos(phi)

        v = Vector3f(
            cos_phi * sin_theta,
            sin_phi * sin_theta,
            cos_theta
        )
        f = Frame3f(Vector3f(1.0, 2.0, 3.0) / ek.sqrt(14))

        v2 = f.to_local(v)
        v3 = f.to_world(v2)

        assert ek.allclose(v3, v)

        assert ek.allclose(Frame3f.cos_theta(v), cos_theta)
        assert ek.allclose(Frame3f.sin_theta(v), sin_theta)
        assert ek.allclose(Frame3f.cos_phi(v), cos_phi)
        assert ek.allclose(Frame3f.sin_phi(v), sin_phi)
        assert ek.allclose(Frame3f.cos_theta_2(v), cos_theta * cos_theta)
        assert ek.allclose(Frame3f.sin_theta_2(v), sin_theta * sin_theta)
        assert ek.allclose(Frame3f.cos_phi_2(v), cos_phi * cos_phi)
        assert ek.allclose(Frame3f.sin_phi_2(v), sin_phi * sin_phi)
        assert ek.allclose(Vector2f(Frame3f.sincos_phi(v)), [sin_phi, cos_phi])
        assert ek.allclose(Vector2f(Frame3f.sincos_phi_2(v)), [sin_phi * sin_phi, cos_phi * cos_phi])
Beispiel #4
0
def test03_smith_g1_beckmann(variant_packet_rgb):
    from mitsuba.core import Vector3f
    from mitsuba.render import MicrofacetDistribution, MicrofacetType

    # Compare against data obtained from previous Mitsuba v0.6 implementation
    mdf = MicrofacetDistribution(MicrofacetType.Beckmann, 0.1, 0.3, False)
    mdf_i = MicrofacetDistribution(MicrofacetType.Beckmann, 0.1, False)
    steps = 20
    theta = ek.linspace(Float, ek.pi / 3, ek.pi / 2, steps)

    phi = Float.full(ek.pi / 2, steps)
    cos_theta, sin_theta = ek.cos(theta), ek.sin(theta)
    cos_phi, sin_phi = ek.cos(phi), ek.sin(phi)
    v = [cos_phi * sin_theta, sin_phi * sin_theta, cos_theta]
    wi = Vector3f(0, 0, 1)
    ek.set_slices(wi, steps)

    assert np.allclose(mdf.smith_g1(v, wi), [
        1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000523e+00,
        9.9941480e-01, 9.9757767e-01, 9.9420297e-01, 9.8884594e-01,
        9.8091525e-01, 9.6961778e-01, 9.5387781e-01, 9.3222123e-01,
        9.0260512e-01, 8.6216795e-01, 8.0686140e-01, 7.3091686e-01,
        6.2609726e-01, 4.8074335e-01, 2.7883825e-01, 1.9197471e-06
    ])

    assert ek.allclose(mdf_i.smith_g1(v, wi), [
        1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00,
        1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00,
        1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00,
        1.0000000e+00, 1.0000000e+00, 9.9828446e-01, 9.8627287e-01,
        9.5088160e-01, 8.5989666e-01, 6.2535185e-01, 5.7592310e-06
    ])

    steps = 20
    theta = Float.full(ek.pi / 2 * 0.98, steps)
    phi = ek.linspace(Float, 0, 2 * ek.pi, steps)
    cos_theta, sin_theta = ek.cos(theta), ek.sin(theta)
    cos_phi, sin_phi = ek.cos(phi), ek.sin(phi)
    v = [cos_phi * sin_theta, sin_phi * sin_theta, cos_theta]

    assert ek.allclose(mdf.smith_g1(v, wi), [
        0.67333597, 0.56164336, 0.42798978, 0.35298213, 0.31838724, 0.31201753,
        0.33166203, 0.38421196, 0.48717275, 0.63746351, 0.63746351, 0.48717275,
        0.38421196, 0.33166203, 0.31201753, 0.31838724, 0.35298213, 0.42798978,
        0.56164336, 0.67333597
    ])

    assert ek.allclose(mdf_i.smith_g1(v, wi), Float.full(0.67333597, steps))
Beispiel #5
0
def test09_trig():
    for i in range(-5, 5):
        for j in range(-5, 5):
            a = ek.sin(C(i, j))
            b = C(cmath.sin(complex(i, j)))
            assert ek.allclose(a, b)

            a = ek.cos(C(i, j))
            b = C(cmath.cos(complex(i, j)))
            assert ek.allclose(a, b)

            sa, ca = ek.sincos(C(i, j))
            sb = C(cmath.sin(complex(i, j)))
            cb = C(cmath.cos(complex(i, j)))
            assert ek.allclose(sa, sb)
            assert ek.allclose(ca, cb)

            # Python appears to handle the branch cuts
            # differently from Enoki, C, and Mathematica..
            a = ek.asin(C(i, j + 0.1))
            b = C(cmath.asin(complex(i, j + 0.1)))
            assert ek.allclose(a, b)

            a = ek.acos(C(i, j + 0.1))
            b = C(cmath.acos(complex(i, j + 0.1)))
            assert ek.allclose(a, b)

            if abs(j) != 1 or i != 0:
                a = ek.atan(C(i, j))
                b = C(cmath.atan(complex(i, j)))
                assert ek.allclose(a, b, atol=1e-7)
def test01_fresnel(variant_scalar_rgb):
    from mitsuba.render import fresnel

    ct_crit = -ek.sqrt(1 - 1 / 1.5**2)
    assert ek.allclose(fresnel(1, 1.5), (0.04, -1, 1.5, 1 / 1.5))
    assert ek.allclose(fresnel(-1, 1.5), (0.04, 1, 1 / 1.5, 1.5))
    assert ek.allclose(fresnel(1, 1 / 1.5), (0.04, -1, 1 / 1.5, 1.5))
    assert ek.allclose(fresnel(-1, 1 / 1.5), (0.04, 1, 1.5, 1 / 1.5))
    assert ek.allclose(fresnel(0, 1.5), (1, ct_crit, 1.5, 1 / 1.5))
    assert ek.allclose(fresnel(0, 1 / 1.5), (1, 0, 1 / 1.5, 1.5))

    # Spot check at 45 deg (1 -> 1.5)
    # Source: http://hyperphysics.phy-astr.gsu.edu/hbase/phyopt/freseq.html
    F, cos_theta_t, _, scale = fresnel(ek.cos(45 * ek.pi / 180), 1.5)
    cos_theta_t_ref = -ek.cos(28.1255057020557 * ek.pi / 180)
    F_ref = 0.5 * (0.09201336304552442**2 + 0.3033370452904235**2)
    L = (scale * ek.sqrt(1 - ek.cos(45 * ek.pi / 180)**2))**2 + cos_theta_t**2
    assert ek.allclose(L, 1)
    assert ek.allclose(cos_theta_t, cos_theta_t_ref)
    assert ek.allclose(F, F_ref)

    # 1.5 -> 1
    F, cos_theta_t, _, _ = fresnel(ek.cos(45 * ek.pi / 180), 1 / 1.5)
    assert ek.allclose(F, 1)
    assert ek.allclose(cos_theta_t, 0)

    F, cos_theta_t, _, scale = fresnel(ek.cos(10 * ek.pi / 180), 1 / 1.5)
    cos_theta_t_ref = -ek.cos(15.098086605159006 * ek.pi / 180)
    F_ref = 0.5 * (0.19046797197779405**2 + 0.20949431963852014**2)
    L = (scale * ek.sqrt(1 - ek.cos(10 * ek.pi / 180)**2))**2 + cos_theta_t**2
    assert ek.allclose(L, 1)
    assert ek.allclose(cos_theta_t, cos_theta_t_ref)
    assert ek.allclose(F, F_ref)
Beispiel #7
0
def test03_smith_g1_ggx(variant_packet_rgb):
    from mitsuba.render import MicrofacetDistribution, MicrofacetType

    # Compare against data obtained from previous Mitsuba v0.6 implementation
    mdf = MicrofacetDistribution(MicrofacetType.GGX, 0.1, 0.3, False)
    mdf_i = MicrofacetDistribution(MicrofacetType.GGX, 0.1, False)
    steps = 20
    theta = ek.linspace(Float, ek.pi / 3, ek.pi / 2, steps)
    phi = Float.full(ek.pi / 2, steps)
    cos_theta, sin_theta = ek.cos(theta), ek.sin(theta)
    cos_phi, sin_phi = ek.cos(phi), ek.sin(phi)
    v = [cos_phi * sin_theta, sin_phi * sin_theta, cos_theta]
    wi = np.tile([0, 0, 1], (steps, 1))

    assert ek.allclose(mdf.smith_g1(v, wi), [
        9.4031686e-01, 9.3310797e-01, 9.2485082e-01, 9.1534841e-01,
        9.0435863e-01, 8.9158219e-01, 8.7664890e-01, 8.5909742e-01,
        8.3835226e-01, 8.1369340e-01, 7.8421932e-01, 7.4880326e-01,
        7.0604056e-01, 6.5419233e-01, 5.9112519e-01, 5.1425743e-01,
        4.2051861e-01, 3.0633566e-01, 1.6765384e-01, 1.0861372e-06
    ])

    assert ek.allclose(mdf_i.smith_g1(v, wi), [
        9.9261039e-01, 9.9160647e-01, 9.9042398e-01, 9.8901933e-01,
        9.8733366e-01, 9.8528832e-01, 9.8277503e-01, 9.7964239e-01,
        9.7567332e-01, 9.7054905e-01, 9.6378750e-01, 9.5463598e-01,
        9.4187391e-01, 9.2344058e-01, 8.9569420e-01, 8.5189372e-01,
        7.7902949e-01, 6.5144652e-01, 4.1989169e-01, 3.2584082e-06
    ])

    theta = Float.full(ek.pi / 2 * 0.98, steps)
    phi = ek.linspace(Float, 0, 2 * ek.pi, steps)
    cos_theta, sin_theta = ek.cos(theta), ek.sin(theta)
    cos_phi, sin_phi = ek.cos(phi), ek.sin(phi)
    v = [cos_phi * sin_theta, sin_phi * sin_theta, cos_theta]

    assert ek.allclose(mdf.smith_g1(v, wi), [
        0.46130955, 0.36801264, 0.26822716, 0.21645154, 0.19341162, 0.18922243,
        0.20219423, 0.23769052, 0.31108665, 0.43013984, 0.43013984, 0.31108665,
        0.23769052, 0.20219423, 0.18922243, 0.19341162, 0.21645154, 0.26822716,
        0.36801264, 0.46130955
    ])

    assert ek.allclose(mdf_i.smith_g1(v, wi), Float.full(0.46130955, steps))
Beispiel #8
0
def sec_(a0):
    if not a0.IsFloat:
        raise Exception("sec(): requires floating point operands!")
    if not a0.IsSpecial:
        ar, sr = _check1(a0)
        for i in range(sr):
            ar[i] = _ek.sec(a0[i])
    else:
        return 1 / _ek.cos(a0)
    return ar
def test02_fresnel_polarized(variant_scalar_rgb):
    from mitsuba.render import fresnel_polarized

    # Brewster's angle
    angle = ek.cos(56.3099 * ek.pi / 180)

    a_s, a_p, cos_theta_t, _, scale = fresnel_polarized(angle, 1.5)

    assert ek.allclose(ek.real(a_s * a_s), 0.3846150939598947**2)
    assert ek.allclose(ek.real(a_p * a_p), 0)
def test04_snell(variant_packet_rgb):
    from mitsuba.render import fresnel

    # Snell's law
    theta_i = ek.linspace(Float, 0, ek.pi / 2, 20)
    F, cos_theta_t, _, _ = fresnel(ek.cos(theta_i), 1.5)
    theta_t = ek.acos(cos_theta_t)

    assert ek.allclose(ek.sin(theta_i) - 1.5 * ek.sin(theta_t),
                       Float.zero(20),
                       atol=1e-5)
Beispiel #11
0
def test03_linear_polarizer(variant_scalar_rgb):
    from mitsuba.render.mueller import rotated_element, linear_polarizer

    # Malus' law
    angle = 30 * ek.pi/180
    value_malus = ek.cos(angle)**2
    polarizer = rotated_element(angle, linear_polarizer(1.0))

    stokes_in  = [1, 1, 0, 0]
    stokes_out = polarizer @ stokes_in
    intensity  = stokes_out[0]
    assert ek.allclose(intensity, value_malus)
def test03_fresnel_conductor(variant_packet_rgb):
    from mitsuba.render import fresnel, fresnel_conductor

    # The conductive and diel. variants should agree given a real-valued IOR
    cos_theta_i = ek.cos(ek.linspace(Float, 0, ek.pi / 2, 20))

    r, cos_theta_t, _, scale = fresnel(cos_theta_i, 1.5)
    r_2 = fresnel_conductor(cos_theta_i, 1.5)
    assert ek.allclose(r, r_2)

    r, cos_theta_t, _, scale = fresnel(cos_theta_i, 1 / 1.5)
    r_2 = fresnel_conductor(cos_theta_i, 1 / 1.5)
    assert ek.allclose(r, r_2)
Beispiel #13
0
def cos_(a0):
    if not a0.IsFloat:
        raise Exception("cos(): requires floating point operands!")
    ar, sr = _check1(a0)
    if not a0.IsSpecial:
        for i in range(sr):
            ar[i] = _ek.cos(a0[i])
    elif a0.IsComplex:
        s, c = _ek.sincos(a0.real)
        sh, ch = _ek.sincosh(a0.imag)
        ar.real = c * ch
        ar.imag = -s * sh
    else:
        raise Exception("cos(): unsupported array type!")

    return ar
Beispiel #14
0
def test04_linear_polarizer_rotated(variant_scalar_rgb):
    from mitsuba.render.mueller import rotated_element, linear_polarizer, rotator

    # The closed-form expression for a rotated linear polarizer is available
    # in many textbooks and should match the behavior of manually rotating the
    # optical element.
    angle = 33 * ek.pi/180
    s, c = ek.sin(2*angle), ek.cos(2*angle)
    M_ref = ek.scalar.Matrix4f([[1, c, s, 0],
                                [c, c*c, s*c, 0],
                                [s, s*c, s*s, 0],
                                [0, 0, 0, 0]]) * 0.5
    R = rotator(angle)
    L = linear_polarizer()
    M = rotated_element(angle, L)
    assert ek.allclose(M, M_ref)
Beispiel #15
0
def test06_specular_transmission(variant_scalar_rgb):
    from mitsuba.core import Matrix4f
    from mitsuba.render.mueller import specular_transmission

    assert ek.allclose(specular_transmission(1, 1.5), Matrix4f.identity() * 0.96, atol=1e-5)
    assert ek.allclose(specular_transmission(1, 1/1.5), Matrix4f.identity() * 0.96, atol=1e-5)
    assert ek.allclose(specular_transmission(1e-7, 1.5), Matrix4f.zero(), atol=1e-5)
    assert ek.allclose(specular_transmission(1e-7, 1/1.5), Matrix4f.zero(), atol=1e-5)
    assert ek.allclose(specular_transmission(0, 1.5), Matrix4f.zero(), atol=1e-5)
    assert ek.allclose(specular_transmission(0, 1/1.5), Matrix4f.zero(), atol=1e-5)

    ref = ek.scalar.Matrix4f([[ 0.9260355 , -0.07396451,  0.        ,  0.        ],
                              [-0.07396451,  0.9260355 ,  0.        ,  0.        ],
                              [ 0.        ,  0.        ,  0.92307705,  0.        ],
                              [ 0.        ,  0.        ,  0.        ,  0.92307705]])
    assert ek.allclose(specular_transmission(ek.cos(ek.atan(1/1.5)), 1/1.5), ref)
def test_sample_ray(variant_packet_spectral, spectrum_key, wavelength_sample,
                    pos_sample, cutoff_angle, lookat):
    # Check the correctness of the sample_ray() method

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

    cutoff_angle_rad = cutoff_angle / 180 * ek.pi
    cos_cutoff_angle_rad = ek.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_spectrum(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.transform_point(0))
def test05_phase(variant_scalar_rgb):
    from mitsuba.render import fresnel_polarized

    # 180 deg phase shift for perpendicularly arriving light (air -> glass)
    a_s, a_p, _, _, _ = fresnel_polarized(1, 1.5)
    assert ek.real(a_s) < 0 and ek.real(a_p) < 0 and ek.imag(
        a_s) == 0 and ek.imag(a_p) == 0

    # 180 deg phase shift only for s-polarized light below brewster's angle (air -> glass)
    a_s, a_p, _, _, _ = fresnel_polarized(.1, 1.5)
    assert ek.real(a_s) < 0 and ek.real(a_p) > 0 and ek.imag(
        a_s) == 0 and ek.imag(a_p) == 0

    # No phase shift for perpendicularly arriving light (glass -> air)
    a_s, a_p, _, _, _ = fresnel_polarized(1, 1 / 1.5)
    assert ek.real(a_s) > 0 and ek.real(a_p) > 0 and ek.imag(
        a_s) == 0 and ek.imag(a_p) == 0

    # 180 deg phase shift only for s-polarized light below brewster's angle (glass -> air)
    b = ek.atan(1 / 1.5)
    a_s, a_p, _, _, _ = fresnel_polarized(ek.cos(b + 0.01), 1 / 1.5)
    assert ek.real(a_s) > 0 and ek.real(a_p) < 0 and ek.imag(
        a_s) == 0 and ek.imag(a_p) == 0
def test02_eval_pdf(variant_scalar_rgb):
    from mitsuba.core import Frame3f
    from mitsuba.render import BSDFContext, BSDFFlags, SurfaceInteraction3f
    from mitsuba.core.xml import load_string

    bsdf = load_string("<bsdf version='2.0.0' type='diffuse'></bsdf>")

    si    = SurfaceInteraction3f()
    si.p  = [0, 0, 0]
    si.n  = [0, 0, 1]
    si.wi = [0, 0, 1]
    si.sh_frame = Frame3f(si.n)

    ctx = BSDFContext()

    for i in range(20):
        theta = i / 19.0 * (ek.pi / 2)
        wo = [ek.sin(theta), 0, ek.cos(theta)]

        v_pdf  = bsdf.pdf(ctx, si, wo=wo)
        v_eval = bsdf.eval(ctx, si, wo=wo)[0]
        assert ek.allclose(v_pdf, wo[2] / ek.pi)
        assert ek.allclose(v_eval, 0.5 * wo[2] / ek.pi)
def test06_phase_tir(variant_scalar_rgb):
    import numpy as np
    from mitsuba.render import fresnel_polarized

    eta = 1 / 1.5
    # Check phase shift at critical angle (total internal reflection case)
    crit = ek.asin(eta)
    a_s, a_p, _, _, _ = fresnel_polarized(ek.cos(crit), eta)

    assert ek.allclose(ek.arg(a_s), 0.0)
    assert ek.allclose(ek.arg(a_p), ek.pi) or ek.allclose(ek.arg(a_p), -ek.pi)

    # Check phase shift at grazing angle (total internal reflection case)
    a_s, a_p, _, _, _ = fresnel_polarized(0.0, eta)

    assert ek.allclose(ek.arg(a_s), ek.pi) or ek.allclose(ek.arg(a_s), -ek.pi)
    assert ek.allclose(ek.arg(a_p), 0.0)

    # Location of minimum phase difference
    cos_theta_min = ek.sqrt((1 - eta**2) / (1 + eta**2))
    phi_delta = 4 * ek.atan(eta)
    a_s, a_p, _, _, _ = fresnel_polarized(cos_theta_min, eta)
    assert ek.allclose(ek.arg(a_s) - ek.arg(a_p), phi_delta)
Beispiel #20
0
def y_2_n2(colors, theta, phi):
    K = ek.sqrt(15.0 / (4 * ek.pi))
    return K * ek.sin(phi) * ek.cos(phi) * ek.pow(ek.sin(theta), 2) * colors
Beispiel #21
0
def y_2_0(colors, theta, phi):
    K = ek.sqrt(5.0 / (16 * ek.pi))
    return K * (3 * ek.pow(ek.cos(theta), 2) - 1) * colors
Beispiel #22
0
def y_2_p1(colors, theta, phi):
    K = ek.sqrt(15.0 / (4 * ek.pi))
    return K * ek.cos(phi) * ek.sin(theta) * -ek.cos(theta) * colors
Beispiel #23
0
def test05_path_tracer_malus_law(variant_scalar_mono_polarized):
    from mitsuba.core import Spectrum
    from mitsuba.core.xml import load_string
    from mitsuba.render import BSDFContext, TransportMode
    from mitsuba.render.mueller import stokes_basis, rotate_stokes_basis_m

    def spectrum_from_stokes(v):
        res = Spectrum(0.0)
        for i in range(4):
            res[i,0] = v[i]
        return res

    # Test polarizer implementation inside of an actual polarized path tracer.
    # (Serves also as test case for the polarized path tracer itself.)
    #
    # This test involves a setup using two polarizers placed along an optical
    # axis between light source and camera.
    # - The first polarizer is fixed, and transforms the emitted radiance into
    #   linearly polarized light.
    # - The second polarizer rotates to different angles, thus attenuating the
    #   final observed intensity at the camera. We verify that this intensity
    #   follows Malus' law as expected.

    angles = [0, 15, 30, 45, 60, 75, 90]
    radiance = []

    for angle in angles:
        # Build scene with given polarizer rotation angle
        scene_str = """<scene version='2.0.0'>
                           <integrator type="path"/>

                           <sensor type="perspective">
                               <float name="fov" value="0.00001"/>
                               <transform name="to_world">
                                   <lookat origin="0, 10, 0"
                                           target="0, 0, 0"
                                           up    ="0, 0, 1"/>
                               </transform>
                               <film type="hdrfilm">
                                   <integer name="width" value="1"/>
                                   <integer name="height" value="1"/>
                                   <rfilter type="gaussian"/>
                                   <string name="pixel_format" value="rgb"/>
                               </film>
                           </sensor>

                           <!-- Light source -->
                           <shape type="rectangle">
                               <transform name="to_world">
                                   <rotate x="1" y="0" z="0" angle="-90"/>
                                   <translate y="-10"/>
                               </transform>

                               <emitter type="area">
                                   <spectrum name="radiance" value="1"/>
                               </emitter>
                           </shape>

                           <!-- First polarizer. Stays fixed. -->
                           <shape type="rectangle">
                               <bsdf type="polarizer"/>

                               <transform name="to_world">
                                   <rotate x="1" y="0" z="0" angle="-90"/>
                                   <translate y="-5"/>
                               </transform>
                           </shape>

                           <!-- Second polarizer. Rotates. -->
                           <shape type="rectangle">
                               <bsdf type="polarizer"/>

                               <transform name="to_world">
                                   <rotate x="1" y="0" z="0" angle="-90"/>
                                   <rotate x="0" y="1" z="0" angle="{}"/>  <!-- Rotate around optical axis -->
                                   <translate y="0"/>
                               </transform>
                           </shape>

                       </scene>""".format(angle)

        scene = load_string(scene_str)
        integrator = scene.integrator()
        sensor     = scene.sensors()[0]
        sampler    = sensor.sampler()

        # Sample ray from sensor
        ray, _ = sensor.sample_ray_differential(0.0, 0.5, [0.5, 0.5], [0.5, 0.5])

        # Call integrator
        value, _, _ = integrator.sample(scene, sampler, ray)

        # Extract intensity from returned Stokes vector
        v = value[0,0]

        # Avoid occasional rounding problems
        v = ek.max(0.0, v)

        # Keep track of observed radiance
        radiance.append(v)

    # Check that Malus' law holds
    for i in range(len(angles)):
        theta = angles[i] * ek.pi/180
        malus = ek.cos(theta)**2
        malus *= radiance[0]
        assert ek.allclose(malus, radiance[i], atol=1e-2)
Beispiel #24
0
def y_2_p2(colors, theta, phi):
    K = ek.sqrt(15.0 / (16 * ek.pi))
    return K * (ek.pow(ek.cos(phi), 2) - ek.pow(ek.sin(phi), 2)) * ek.pow(
        ek.sin(theta), 2) * colors
def test02_sample_pol_local(variant_scalar_mono_polarized):
    from mitsuba.core import Frame3f, Transform4f, Spectrum, UnpolarizedSpectrum, Vector3f
    from mitsuba.core.xml import load_string
    from mitsuba.render import BSDFContext, TransportMode, SurfaceInteraction3f, fresnel_conductor
    from mitsuba.render.mueller import stokes_basis, rotate_mueller_basis

    def spectrum_from_stokes(v):
        res = Spectrum(0.0)
        for i in range(4):
            res[i, 0] = v[i]
        return res

    # Create a Silver conductor BSDF and reflect different polarization states
    # at a 45˚ angle.
    # All tests take place directly in local BSDF coordinates. Here we only
    # want to make sure that the output of this looks like what you would
    # expect from a Mueller matrix describing specular reflection on a mirror.

    eta = 0.136125 + 4.010625j  # IoR values of Ag at 635.816284nm
    bsdf = load_string("""<bsdf version='2.0.0' type='conductor'>
                              <spectrum name="eta" value="{}"/>
                              <spectrum name="k" value="{}"/>
                          </bsdf>""".format(eta.real, eta.imag))

    theta_i = 45 * ek.pi / 180
    wi = Vector3f([-ek.sin(theta_i), 0, ek.cos(theta_i)])

    ctx = BSDFContext()
    ctx.mode = TransportMode.Importance
    si = SurfaceInteraction3f()
    si.p = [0, 0, 0]
    si.wi = wi
    n = [0, 0, 1]
    si.sh_frame = Frame3f(n)

    bs, M_local = bsdf.sample(ctx, si, 0.0, [0.0, 0.0])
    wo = bs.wo

    # Rotate into standard coordinates for specular reflection
    bi_s = ek.normalize(ek.cross(n, -wi))
    bi_p = ek.normalize(ek.cross(-wi, bi_s))
    bo_s = ek.normalize(ek.cross(n, wo))
    bo_p = ek.normalize(ek.cross(wo, bi_s))

    M_local = rotate_mueller_basis(M_local, -wi, stokes_basis(-wi), bi_p, wo,
                                   stokes_basis(wo), bo_p)

    # Apply to unpolarized light and verify that it is equivalent to normal Fresnel
    a0 = M_local @ spectrum_from_stokes([1, 0, 0, 0])
    F = fresnel_conductor(ek.cos(theta_i),
                          ek.scalar.Complex2f(eta.real, eta.imag))
    a0 = a0[0, 0]
    assert ek.allclose(a0[0], F, atol=1e-3)

    # Apply to horizontally polarized light (linear at 0˚)
    # Test that it is..
    # 1) still fully polarized (though with reduced intensity)
    # 2) still horizontally polarized
    a1 = M_local @ spectrum_from_stokes([1, +1, 0, 0])
    assert ek.allclose(a1[0, 0], ek.abs(a1[1, 0]), atol=1e-3)  # 1)
    a1 /= a1[0, 0]
    assert ek.allclose(a1, spectrum_from_stokes([1, 1, 0, 0]), atol=1e-3)  # 2)

    # Apply to vertically polarized light (linear at 90˚)
    # Test that it is..
    # 1) still fully polarized (though with reduced intensity)
    # 2) still vertically polarized
    a2 = M_local @ spectrum_from_stokes([1, -1, 0, 0])
    assert ek.allclose(a2[0, 0], ek.abs(a2[1, 0]), atol=1e-3)  # 1)
    a2 /= a2[0, 0]
    assert ek.allclose(a2, spectrum_from_stokes([1, -1, 0, 0]),
                       atol=1e-3)  # 2)

    # Apply to (positive) diagonally polarized light (linear at +45˚)
    # Test that..
    # 1) The polarization is flipped to -45˚
    # 2) There is now also some (left) circular polarization
    a3 = M_local @ spectrum_from_stokes([1, 0, +1, 0])
    assert ek.all(a3[2, 0] < UnpolarizedSpectrum(0.0))
    assert ek.all(a3[3, 0] < UnpolarizedSpectrum(0.0))

    # Apply to (negative) diagonally polarized light (linear at -45˚)
    # Test that..
    # 1) The polarization is flipped to +45˚
    # 2) There is now also some (right) circular polarization
    a4 = M_local @ spectrum_from_stokes([1, 0, -1, 0])
    assert ek.all(a4[2, 0] > UnpolarizedSpectrum(0.0))
    assert ek.all(a4[3, 0] > UnpolarizedSpectrum(0.0))

    # Apply to right circularly polarized light
    # Test that the polarization is flipped to left circular
    a5 = M_local @ spectrum_from_stokes([1, 0, 0, +1])
    assert ek.all(a5[3, 0] < UnpolarizedSpectrum(0.0))

    # Apply to left circularly polarized light
    # Test that the polarization is flipped to right circular
    a6 = M_local @ spectrum_from_stokes([1, 0, 0, -1])
    assert ek.all(a6[3, 0] > UnpolarizedSpectrum(0.0))
Beispiel #26
0
 def instantiate(args):
     wi = [0, 0, 1]
     if len(args) == 1:
         angle = args[0] * ek.pi / 180
         wi = [ek.sin(angle), 0, ek.cos(angle)]
     return MicrofacetDistribution(md_type, alpha, sample_visible), wi
Beispiel #27
0
def y_1_0(colors, theta, phi):
    K = ek.sqrt(3.0 / (4 * ek.pi))
    return K * ek.cos(theta) * colors
 def sample_cone(sample, cos_theta_max):
     cos_theta = (1 - sample[1]) + sample[1] * cos_theta_max
     sin_theta = ek.sqrt(1 - cos_theta * cos_theta)
     phi = 2 * ek.pi * sample[0]
     s, c = ek.sin(phi), ek.cos(phi)
     return [c * sin_theta, s * sin_theta, cos_theta]
Beispiel #29
0
def test02_eval_pdf_beckmann(variant_packet_rgb):
    from mitsuba.core import Vector3f
    from mitsuba.render import MicrofacetDistribution, MicrofacetType

    # Compare against data obtained from previous Mitsuba v0.6 implementation
    mdf = MicrofacetDistribution(MicrofacetType.Beckmann, 0.1, 0.3, False)
    mdf_i = MicrofacetDistribution(MicrofacetType.Beckmann, 0.1, False)
    assert not mdf.is_isotropic()
    assert mdf.is_anisotropic()
    assert mdf_i.is_isotropic()
    assert not mdf_i.is_anisotropic()

    steps = 20
    theta = ek.linspace(Float, 0, ek.pi, steps)
    phi = Float.full(ek.pi / 2, steps)
    cos_theta, sin_theta = ek.cos(theta), ek.sin(theta)
    cos_phi, sin_phi = ek.cos(phi), ek.sin(phi)
    v = [cos_phi * sin_theta, sin_phi * sin_theta, cos_theta]

    wi = Vector3f(0, 0, 1)
    ek.set_slices(wi, steps)

    assert ek.allclose(mdf.eval(v), [
        1.06103287e+01, 8.22650051e+00, 3.57923722e+00, 6.84863329e-01,
        3.26460004e-02, 1.01964230e-04, 5.87322635e-10, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00
    ])

    assert ek.allclose(mdf.pdf(wi, v), [
        1.06103287e+01, 8.11430168e+00, 3.38530421e+00, 6.02319300e-01,
        2.57622823e-02, 6.90584930e-05, 3.21235011e-10, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, -0.00000000e+00, -0.00000000e+00,
        -0.00000000e+00, -0.00000000e+00, -0.00000000e+00, -0.00000000e+00,
        -0.00000000e+00, -0.00000000e+00, -0.00000000e+00, -0.00000000e+00
    ])

    assert ek.allclose(mdf_i.eval(v), [
        3.18309879e+01, 2.07673073e+00, 3.02855828e-04, 1.01591990e-11,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00
    ])

    assert ek.allclose(mdf_i.pdf(wi, v), [
        3.18309879e+01, 2.04840684e+00, 2.86446273e-04, 8.93474877e-12,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, -0.00000000e+00, -0.00000000e+00,
        -0.00000000e+00, -0.00000000e+00, -0.00000000e+00, -0.00000000e+00,
        -0.00000000e+00, -0.00000000e+00, -0.00000000e+00, -0.00000000e+00
    ])

    theta = Float.full(0.1, steps)
    phi = ek.linspace(Float, 0, 2 * ek.pi, steps)
    cos_theta, sin_theta = ek.cos(theta), ek.sin(theta)
    cos_phi, sin_phi = ek.cos(phi), ek.sin(phi)
    v = [cos_phi * sin_theta, sin_phi * sin_theta, cos_theta]

    assert ek.allclose(mdf.eval(v), [
        3.95569706, 4.34706259, 5.54415846, 7.4061389, 9.17129803, 9.62056446,
        8.37803268, 6.42071199, 4.84459257, 4.05276537, 4.05276537, 4.84459257,
        6.42071199, 8.37803268, 9.62056446, 9.17129803, 7.4061389, 5.54415846,
        4.34706259, 3.95569706
    ])

    assert ek.allclose(
        mdf.pdf(wi, v),
        Float([
            3.95569706, 4.34706259, 5.54415846, 7.4061389, 9.17129803,
            9.62056446, 8.37803268, 6.42071199, 4.84459257, 4.05276537,
            4.05276537, 4.84459257, 6.42071199, 8.37803268, 9.62056446,
            9.17129803, 7.4061389, 5.54415846, 4.34706259, 3.95569706
        ]) * ek.cos(0.1))

    assert ek.allclose(mdf_i.eval(v), Float.full(11.86709118, steps))
    assert ek.allclose(mdf_i.pdf(wi, v),
                       Float.full(11.86709118 * ek.cos(0.1), steps))