def max_(a0, a1): ar, sr = _check2(a0, a1) if not a0.IsArithmetic: raise Exception("max(): requires arithmetic operands!") for i in range(sr): ar[i] = _ek.max(a0[i], a1[i]) return ar
def __init__(self, domain, sample_func, pdf_func, sample_dim=2, sample_count=1000000, res=101, ires=4): from mitsuba.core import ScalarVector2u if ires < 2: raise Exception("The 'ires' parameter must be >= 2!") self.domain = domain self.sample_func = sample_func self.pdf_func = pdf_func self.sample_dim = sample_dim self.sample_count = sample_count self.res = ek.max(ScalarVector2u(res, int(res * domain.aspect())), 1) self.ires = ires self.bounds = domain.bounds() self.pdf = None self.histogram = None self.p_value = None self.messages = '' self.fail = False
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)
def __init__(self, domain, sample_func, pdf_func, sample_dim=2, sample_count=1000000, res=101, ires=4): from mitsuba.core import ScalarVector2u assert res > 0 assert ires >= 2, "The 'ires' parameter must be >= 2!" self.domain = domain self.sample_func = sample_func self.pdf_func = pdf_func self.sample_dim = sample_dim self.sample_count = sample_count if domain.aspect() is None: self.res = ScalarVector2u(res, 1) else: self.res = ek.max(ScalarVector2u(int(res / domain.aspect()), res), 1) self.ires = ires self.bounds = domain.bounds() self.pdf = None self.histogram = None self.p_value = None self.messages = '' self.fail = False
def hmax_(a0): size = len(a0) if size == 0: raise Exception("hmax(): zero-sized array!") value = a0[0] for i in range(1, size): value = _ek.max(value, a0[i]) return value
def visible_ndf(D, sigma, theta_i, phi_i, isotropic): from mitsuba.core import MarginalContinuous2D0, Vector2f # Construct projected surface area interpolant data structure m_sigma = MarginalContinuous2D0(sigma, normalize=False) # Create uniform samples and warp by G2 mapping if isotropic: n_theta = n_phi = D.shape[1] else: n_phi = D.shape[0] n_theta = D.shape[1] # Check dimensions of micro-facet model Dvis = np.zeros((phi_i.size, theta_i.size, n_phi, n_theta)) theta = u2theta(np.linspace(0, 1, n_theta)) phi = u2phi(np.linspace(0, 1, n_phi)) # Calculate projected area of micro-facets for i in range(Dvis.shape[0]): # incident elevation for j in range(Dvis.shape[1]): # incident azimuth # Postion for sigma samples sample = Vector2f(theta2u(theta_i[j]), phi2u(phi_i[i])) sigma_i = m_sigma.eval(sample) # Incident direction omega_i = spherical2cartesian(theta_i[j], phi_i[i]) #print(np.degrees(theta_i[j]), np.degrees(phi_i[i])) for k in range(Dvis.shape[2]): # observation azimuth # Observation direction omega = spherical2cartesian(theta, phi[k]) sample = Vector2f(theta2u(theta), phi2u(phi[k])) # NDF at observation directions if isotropic: D_m = D[0] else: D_m = D[k] # Bidirectional NDF Dvis[i, j, k] = ek.max(0, ek.dot(omega, omega_i)) * D_m / sigma_i return Dvis
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)
def projected_area(D, isotropic, projected=True): from mitsuba.core import MarginalContinuous2D0, Vector2f, Vector3f # Check dimensions of micro-facet model sigma = np.zeros(D.shape) # Construct projected surface area interpolant data structure m_D = MarginalContinuous2D0(D, normalize=False) # Create uniform samples and warp by G2 mapping if isotropic: n_theta = n_phi = D.shape[1] else: n_phi = D.shape[0] n_theta = D.shape[1] theta = u2theta(np.linspace(0, 1, n_theta)) phi = u2phi(np.linspace(0, 1, n_phi)) # Temporary values for surface area calculation theta_mean = np.zeros(n_theta + 1) for i in range(n_theta - 1): theta_mean[i + 1] = (theta[i + 1] - theta[i]) / 2. + theta[i] theta_mean[-1] = theta[-1] theta_mean[0] = theta[0] """ Surface area portion of unit sphere. Conditioning better for non vectorized approach. a = sphere_surface_patch(1, theta_next, Vector2f(phi[0], phi[1])) """ a = np.zeros(n_theta) for i in range(n_theta): a[i] = sphere_surface_patch(1, theta_mean[i:i + 2], phi[-3:-1]) # Calculate constants for integration for j in range(n_phi): # Interpolation points o = spherical2cartesian(theta, phi[j]) # Postion for NDF samples u0 = theta2u(theta) u1 = np.ones(n_theta) * phi2u(phi[j]) if j == 0: omega = o u_0 = u0 u_1 = u1 area = a / 2 else: omega = np.concatenate((omega, o)) u_0 = np.concatenate((u_0, u0)) u_1 = np.concatenate((u_1, u1)) if j == n_phi - 1: area = np.concatenate((area, a / 2)) else: area = np.concatenate((area, a)) sample = Vector2f(u_0, u_1) D_s = m_D.eval(sample) omega = Vector3f(omega) P = 1. # Calculate projected area of micro-facets for i in range(sigma.shape[0] - 1): for j in range(sigma.shape[1]): # Get projection factor from incident and outgoind direction if projected: # Incident direction omega_i = spherical2cartesian(theta[j], phi[i]) P = ek.max(0, ek.dot(omega, omega_i)) # Integrate over sphere F = P * D_s sigma[i, j] = np.dot(F, area) if projected: # Normalise sigma[i] = sigma[i] / sigma[i, 0] # TODO: Check for anisotropic case if isotropic: sigma[1] = sigma[0] return sigma