Exemple #1
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)]])
Exemple #2
0
def test16_sin(m):
    x = ek.linspace(m.Float, 0, 10, 10)
    ek.enable_grad(x)
    y = ek.sin(x)
    ek.backward(y)
    assert ek.allclose(ek.detach(y), ek.sin(ek.detach(x)))
    assert ek.allclose(ek.grad(x), ek.cos(ek.detach(x)))
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])
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)
Exemple #5
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))
Exemple #6
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)
Exemple #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))
Exemple #8
0
def csc_(a0):
    if not a0.IsFloat:
        raise Exception("csc(): requires floating point operands!")
    if not a0.IsSpecial:
        ar, sr = _check1(a0)
        for i in range(sr):
            ar[i] = _ek.csc(a0[i])
    else:
        return 1 / _ek.sin(a0)
    return ar
Exemple #9
0
def sin_(a0):
    if not a0.IsFloat:
        raise Exception("sin(): requires floating point operands!")
    ar, sr = _check1(a0)
    if not a0.IsSpecial:
        for i in range(sr):
            ar[i] = _ek.sin(a0[i])
    elif a0.IsComplex:
        s, c = _ek.sincos(a0.real)
        sh, ch = _ek.sincosh(a0.imag)
        ar.real = s * ch
        ar.imag = c * sh
    else:
        raise Exception("sin(): unsupported array type!")
    return ar
Exemple #10
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)
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 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]
Exemple #13
0
 def K(self, x, m_):
     return ek.rsqrt(1 - m_ * ek.sqr(ek.sin(x)))
Exemple #14
0
def y_1_n1(colors, theta, phi):
    K = ek.sqrt(3.0 / (4 * ek.pi))
    return K * ek.sin(phi) * -ek.sin(theta) * colors
def test15_differentiable_surface_interaction_params_forward(
        variant_gpu_autodiff_rgb):
    from mitsuba.core import xml, Float, Ray3f, Vector3f, UInt32, Transform4f

    # Convert flat array into a vector of arrays (will be included in next enoki release)
    def ravel(buf, dim=3):
        idx = dim * UInt32.arange(ek.slices(buf) // dim)
        if dim == 2:
            return Vector2f(ek.gather(buf, idx), ek.gather(buf, idx + 1))
        elif dim == 3:
            return Vector3f(ek.gather(buf, idx), ek.gather(buf, idx + 1),
                            ek.gather(buf, idx + 2))

    # Return contiguous flattened array (will be included in next enoki release)
    def unravel(source, target, dim=3):
        idx = UInt32.arange(ek.slices(source))
        for i in range(dim):
            ek.scatter(target, source[i], dim * idx + i)

    scene = xml.load_string('''
        <scene version="2.0.0">
            <shape type="obj" id="rect">
                <string name="filename" value="resources/data/common/meshes/rectangle.obj"/>
            </shape>
        </scene>
    ''')

    params = traverse(scene)
    shape_param_key = 'rect.vertex_positions_buf'
    positions_buf = params[shape_param_key]
    positions_initial = ravel(positions_buf)

    # Create differential parameter to be optimized
    diff_vector = Vector3f(0.0)
    ek.set_requires_gradient(diff_vector)

    # Apply the transformation to mesh vertex position and update scene
    def apply_transformation(trasfo):
        trasfo = trasfo(diff_vector)
        new_positions = trasfo.transform_point(positions_initial)
        unravel(new_positions, params[shape_param_key])
        params.set_dirty(shape_param_key)
        params.update()

    # ---------------------------------------
    # Test translation

    ray = Ray3f(Vector3f(-0.2, -0.3, -10.0), Vector3f(0.0, 0.0, 1.0), 0, [])
    pi = scene.ray_intersect_preliminary(ray)

    # # If the vertices are shifted along z-axis, so does si.t
    apply_transformation(lambda v: Transform4f.translate(v))
    si = pi.compute_surface_interaction(ray)
    ek.forward(diff_vector.z)
    assert ek.allclose(ek.gradient(si.t), 1)

    # If the vertices are shifted along z-axis, so does si.p
    apply_transformation(lambda v: Transform4f.translate(v))
    si = pi.compute_surface_interaction(ray)
    ek.forward(diff_vector.z)
    assert ek.allclose(ek.gradient(si.p), [0.0, 0.0, 1.0])

    # If the vertices are shifted along x-axis, so does si.uv (times 0.5)
    apply_transformation(lambda v: Transform4f.translate(v))
    si = pi.compute_surface_interaction(ray)
    ek.forward(diff_vector.x)
    assert ek.allclose(ek.gradient(si.uv), [-0.5, 0.0])

    # If the vertices are shifted along y-axis, so does si.uv (times 0.5)
    apply_transformation(lambda v: Transform4f.translate(v))
    si = pi.compute_surface_interaction(ray)
    ek.forward(diff_vector.y)
    assert ek.allclose(ek.gradient(si.uv), [0.0, -0.5])

    # ---------------------------------------
    # Test rotation

    ray = Ray3f(Vector3f(-0.99999, -0.99999, -10.0), Vector3f(0.0, 0.0, 1.0),
                0, [])
    pi = scene.ray_intersect_preliminary(ray)

    # If the vertices are rotated around the center, so does si.uv (times 0.5)
    apply_transformation(lambda v: Transform4f.rotate([0, 0, 1], v.x))
    si = pi.compute_surface_interaction(ray)
    ek.forward(diff_vector.x)
    du = 0.5 * ek.sin(2 * ek.pi / 360.0)
    assert ek.allclose(ek.gradient(si.uv), [-du, du], atol=1e-6)
Exemple #16
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
Exemple #17
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
Exemple #18
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
Exemple #19
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))
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))
Exemple #21
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