def check_vectorization(func_str, wrapper = (lambda f: lambda x: f(x)) , resolution = 2): """ Helper routine which compares evaluations of the vectorized and non-vectorized version of a warping routine """ import importlib mitsuba.set_variant('scalar_rgb') func = wrapper(getattr(importlib.import_module('mitsuba.core').warp, func_str)) pdf_func = wrapper(getattr(importlib.import_module('mitsuba.core').warp, func_str + "_pdf")) try: mitsuba.set_variant('packet_rgb') except: pytest.skip("packet_rgb mode not enabled") func_vec = wrapper(getattr(importlib.import_module('mitsuba.core').warp, func_str)) pdf_func_vec = wrapper(getattr(importlib.import_module('mitsuba.core').warp, func_str + "_pdf")) from mitsuba.core import Vector2f # Generate resolution^2 test points on a 2D grid t = ek.linspace(Float, 1e-3, 1, resolution) x, y = ek.meshgrid(t, t) samples = Vector2f(x, y) # Run the sampling routine result = func_vec(samples) # Evaluate the PDF pdf = pdf_func_vec(result) # Check against the scalar version for i in range(resolution): assert ek.allclose(result.numpy()[i, :], func(samples.numpy()[i, :]), atol=1e-4) assert ek.allclose(pdf.numpy()[i], pdf_func(result.numpy()[i, :]), atol=1e-6)
def test05_sample_ggx(variant_packet_rgb): from mitsuba.render import MicrofacetDistribution, MicrofacetType mdf = MicrofacetDistribution(MicrofacetType.GGX, 0.1, 0.3, False) # Compare against data obtained from previous Mitsuba v0.6 implementation steps = 6 u = ek.linspace(Float, 0, 1, steps) u1, u2 = ek.meshgrid(u, u) u = [u1, u2] wi = np.tile([0, 0, 1], (steps * steps, 1)) result = mdf.sample(wi, u) ref = ((np.array([[0.00000000e+00, 0.00000000e+00, 1.00000000e+00], [4.99384739e-02, 1.30972797e-08, 9.98752296e-01], [8.13788623e-02, 2.13430980e-08, 9.96683240e-01], [1.21566132e-01, 3.18829443e-08, 9.92583334e-01], [1.96116075e-01, 5.14350340e-08, 9.80580688e-01], [1.00000000e+00, 2.62268316e-07, 0.00000000e+00], [0.00000000e+00, 0.00000000e+00, 1.00000000e+00], [1.52942007e-02, 1.41212299e-01, 9.89861190e-01], [2.45656986e-02, 2.26816610e-01, 9.73627627e-01], [3.57053429e-02, 3.29669625e-01, 9.43420947e-01], [5.36015145e-02, 4.94906068e-01, 8.67291689e-01], [1.07676744e-01, 9.94185984e-01, 0.00000000e+00], [-0.00000000e+00, 0.00000000e+00, 1.00000000e+00], [-4.02617380e-02, 8.77555013e-02, 9.95328069e-01], [-6.52425364e-02, 1.42204270e-01, 9.87684846e-01], [-9.64000970e-02, 2.10116088e-01, 9.72912252e-01], [-1.50845990e-01, 3.28787714e-01, 9.32278991e-01], [-4.17001039e-01, 9.08905983e-01, 0.00000000e+00], [-0.00000000e+00, -0.00000000e+00, 1.00000000e+00], [-4.02616598e-02, -8.77555385e-02, 9.95328069e-01], [-6.52425662e-02, -1.42204687e-01, 9.87684786e-01], [-9.64000225e-02, -2.10116416e-01, 9.72912192e-01], [-1.50845826e-01, -3.28788161e-01, 9.32278872e-01], [-4.17000234e-01, -9.08906400e-01, 0.00000000e+00], [0.00000000e+00, -0.00000000e+00, 1.00000000e+00], [1.52942603e-02, -1.41212285e-01, 9.89861190e-01], [2.45657954e-02, -2.26816595e-01, 9.73627627e-01], [3.57054621e-02, -3.29669416e-01, 9.43421006e-01], [5.36017120e-02, -4.94905949e-01, 8.67291749e-01], [1.07677162e-01, -9.94185925e-01, 0.00000000e+00], [0.00000000e+00, 0.00000000e+00, 1.00000000e+00], [4.99384739e-02, 8.73152040e-09, 9.98752296e-01], [8.13788623e-02, 1.42287320e-08, 9.96683240e-01], [1.21566132e-01, 2.12552980e-08, 9.92583334e-01], [1.96116075e-01, 3.42900250e-08, 9.80580688e-01], [1.00000000e+00, 1.74845553e-07, 0.00000000e+00]]), np.array([ 10.61032867, 6.81609201, 3.85797882, 1.73599267, 0.45013079, 0., 10.61032867, 7.00141668, 4.13859272, 2.02177191, 0.65056872, 0., 10.61032867, 6.88668203, 3.96438813, 1.84343493, 0.52378261, 0., 10.61032867, 6.88668203, 3.96438861, 1.84343517, 0.52378279, 0., 10.61032867, 7.00141668, 4.13859272, 2.02177191, 0.65056866, 0., 10.61032867, 6.81609201, 3.85797882, 1.73599267, 0.45013079, 0. ]))) assert ek.allclose(ref[0], result[0], atol=5e-4) assert ek.allclose(ref[1], result[1], atol=1e-4)
def test10_meshgrid(cname): t = get_class(cname) import numpy as np a = ek.linspace(t, 0, 1, 3) b = ek.linspace(t, 0, 1, 4) c, d = ek.meshgrid(a, b) ek.schedule(c, d) cn, dn = np.meshgrid(a.numpy(), b.numpy()) assert ek.allclose(c.numpy(), cn.ravel()) assert ek.allclose(d.numpy(), dn.ravel())
def get_bxdf_i(args): # parallel get_bxdf_s ret = np.zeros((args.ti[2], args.pi[2], args.ts[2], args.ps[2]), dtype=float) d2r = ek.pi / 180 theta_i, phi_i = ek.meshgrid( ek.linspace(Float, d2r * args.ti[0], d2r * args.ti[1], args.ti[2]), ek.linspace(Float, d2r * args.pi[0], d2r * args.pi[1], args.pi[2])) for i in range(args.ti[2]): for j in range(args.pi[2]): k = get_bxdf_s(args, theta_i[i], phi_i[j]) ret[i, j, :, :] = k return ret
def tabulate_pdf(self): """ Numerically integrate the provided probability density function over each cell to generate an array resembling the histogram computed by ``tabulate_histogram()``. The function uses the trapezoid rule over intervals discretized into ``self.ires`` separate function evaluations. """ from mitsuba.core import Float, Vector2f, ScalarVector2f extents = self.bounds.extents() endpoint = self.bounds.max - extents / ScalarVector2f(self.res) # Compute a set of nodes where the PDF should be evaluated x, y = ek.meshgrid( ek.linspace(Float, self.bounds.min.x, endpoint.x, self.res.x), ek.linspace(Float, self.bounds.min.y, endpoint.y, self.res.y)) endpoint = extents / ScalarVector2f(self.res) eps = 1e-4 nx = ek.linspace(Float, eps, endpoint.x * (1 - eps), self.ires) ny = ek.linspace(Float, eps, endpoint.y * (1 - eps), self.ires) wx = [1 / (self.ires - 1)] * self.ires wy = [1 / (self.ires - 1)] * self.ires wx[0] = wx[-1] = wx[0] * .5 wy[0] = wy[-1] = wy[0] * .5 integral = 0 self.histogram_start = time.time() for yi, dy in enumerate(ny): for xi, dx in enumerate(nx): xy = self.domain.map_forward(Vector2f(x + dx, y + dy)) pdf = self.pdf_func(xy) integral = ek.fmadd(pdf, wx[xi] * wy[yi], integral) self.histogram_end = time.time() self.pdf = integral * (ek.hprod(extents / ScalarVector2f(self.res)) * self.sample_count) # A few sanity checks pdf_min = ek.hmin(self.pdf) / self.sample_count if not pdf_min >= 0: self._log('Failure: Encountered a cell with a ' 'negative PDF value: %f' % pdf_min) self.fail = True self.pdf_sum = ek.hsum(self.pdf) / self.sample_count if self.pdf_sum > 1.1: self._log('Failure: PDF integrates to a value greater ' 'than 1.0: %f' % self.pdf_sum) self.fail = True
def get_bxdf_s(args, theta_i, phi_i): # Load desired BSDF plugin bsdf = load_string(args.material) # Create a (dummy) surface interaction to use for the evaluation si = SurfaceInteraction3f() # Specify an incident direction with 45 degrees elevation si.wi = sph_dir(theta_i, phi_i) # Create grid in spherical coordinates and map it onto the sphere d2r = ek.pi / 180 theta_s, phi_s = ek.meshgrid( ek.linspace(Float, d2r * args.ts[0], d2r * args.ts[1], args.ts[2]), ek.linspace(Float, d2r * args.ps[0], d2r * args.ps[1], args.ps[2])) ws = sph_dir(theta_s, phi_s) # Evaluate the whole array (18000 directions) at once values = bsdf.eval(BSDFContext(), si, ws) values_r = np.array(values)[:, 0] values_r = values_r.reshape(args.ts[2], args.ps[2]).T return values_r
def test10_meshgrid(cname): Int = get_class(cname) assert ek.meshgrid() == () assert ek.meshgrid(Int(1, 2), indexing='ij') == Int(1, 2) assert ek.meshgrid(Int(1, 2), indexing='xy') == Int(1, 2) assert ek.meshgrid(Int(1, 2), Int(3, 4, 5)) == \ (Int(1, 2, 1, 2, 1, 2), Int(3, 3, 4, 4, 5, 5)) assert ek.meshgrid(Int(1, 2), Int(3, 4, 5), indexing='ij') == \ (Int(1, 1, 1, 2, 2, 2), Int(3, 4, 5, 3, 4, 5)) assert ek.meshgrid(Int(1, 2), Int(3, 4, 5), Int(5, 6), indexing='xy') == \ (Int(1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2), Int(3, 3, 4, 4, 5, 5, 3, 3, 4, 4, 5, 5), Int(5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6)) assert ek.meshgrid(Int(1, 2), Int(3, 4, 5), Int(5, 6), indexing='ij') == \ (Int(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2), Int(3, 3, 4, 4, 5, 5, 3, 3, 4, 4, 5, 5), Int(5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6))
def test04_sample_beckmann(variant_packet_rgb): from mitsuba.core import Vector3f from mitsuba.render import MicrofacetDistribution, MicrofacetType mdf = MicrofacetDistribution(MicrofacetType.Beckmann, 0.1, 0.3, False) # Compare against data obtained from previous Mitsuba v0.6 implementation steps = 6 u = ek.linspace(Float, 0, 1, steps) u1, u2 = ek.meshgrid(u, u) u = [u1, u2] wi = Vector3f(0, 0, 1) ek.set_slices(wi, steps * steps) result = mdf.sample(wi, u) ref = (np.array([[0.00000000e+00, 0.00000000e+00, 1.00000000e+00], [4.71862517e-02, 1.23754589e-08, 9.98886108e-01], [7.12896436e-02, 1.86970155e-08, 9.97455657e-01], [9.52876359e-02, 2.49909284e-08, 9.95449781e-01], [1.25854731e-01, 3.30077086e-08, 9.92048681e-01], [1.00000000e+00, 2.62268316e-07, 0.00000000e+00], [0.00000000e+00, 0.00000000e+00, 1.00000000e+00], [1.44650340e-02, 1.33556545e-01, 9.90935624e-01], [2.16356069e-02, 1.99762881e-01, 9.79605377e-01], [2.85233315e-02, 2.63357669e-01, 9.64276493e-01], [3.68374363e-02, 3.40122312e-01, 9.39659417e-01], [1.07676744e-01, 9.94185984e-01, 0.00000000e+00], [-0.00000000e+00, 0.00000000e+00, 1.00000000e+00], [-3.80569659e-02, 8.29499215e-02, 9.95826781e-01], [-5.72742373e-02, 1.24836378e-01, 9.90522861e-01], [-7.61397704e-02, 1.65956154e-01, 9.83189344e-01], [-9.96606201e-02, 2.17222810e-01, 9.71021116e-01], [-4.17001039e-01, 9.08905983e-01, 0.00000000e+00], [-0.00000000e+00, -0.00000000e+00, 1.00000000e+00], [-3.80568914e-02, -8.29499587e-02, 9.95826781e-01], [-5.72741292e-02, -1.24836430e-01, 9.90522861e-01], [-7.61396214e-02, -1.65956244e-01, 9.83189344e-01], [-9.96605307e-02, -2.17223123e-01, 9.71021056e-01], [-4.17000234e-01, -9.08906400e-01, 0.00000000e+00], [0.00000000e+00, -0.00000000e+00, 1.00000000e+00], [1.44650899e-02, -1.33556545e-01, 9.90935624e-01], [2.16356907e-02, -1.99762881e-01, 9.79605377e-01], [2.85234209e-02, -2.63357460e-01, 9.64276552e-01], [3.68375629e-02, -3.40122133e-01, 9.39659476e-01], [1.07677162e-01, -9.94185925e-01, 0.00000000e+00], [0.00000000e+00, 0.00000000e+00, 1.00000000e+00], [4.71862517e-02, 8.25030622e-09, 9.98886108e-01], [7.12896436e-02, 1.24646773e-08, 9.97455657e-01], [9.52876359e-02, 1.66606196e-08, 9.95449781e-01], [1.25854731e-01, 2.20051408e-08, 9.92048681e-01], [1.00000000e+00, 1.74845553e-07, 0.00000000e+00]]), np.array([ 10.61032867, 8.51669121, 6.41503906, 4.302598, 2.17350101, 0., 10.61032867, 8.72333431, 6.77215099, 4.7335186, 2.55768704, 0., 10.61032867, 8.59542656, 6.55068302, 4.46557426, 2.31778312, 0., 10.61032867, 8.59542656, 6.55068302, 4.46557426, 2.31778359, 0., 10.61032867, 8.72333431, 6.77215099, 4.73351765, 2.55768657, 0., 10.61032867, 8.51669121, 6.41503906, 4.302598, 2.17350101, 0. ])) assert ek.allclose(ref[0], result[0], atol=5e-4) assert ek.allclose(ref[1], result[1], atol=1e-4)
# Load desired BSDF plugin bsdf = load_string("""<bsdf version='2.0.0' type='roughconductor'> <float name="alpha" value="0.2"/> <string name="distribution" value="ggx"/> </bsdf>""") # Create a (dummy) surface interaction to use for the evaluation si = SurfaceInteraction3f() # Specify an incident direction with 45 degrees elevation si.wi = sph_dir(ek.pi * 45 / 180, 0.0) # Create grid in spherical coordinates and map it onto the sphere res = 300 theta_o, phi_o = ek.meshgrid(ek.linspace(Float, 0, ek.pi, res), ek.linspace(Float, 0, 2 * ek.pi, 2 * res)) wo = sph_dir(theta_o, phi_o) # Evaluate the whole array (18000 directions) at once values = bsdf.eval(BSDFContext(), si, wo) import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import make_axes_locatable # Extract red channel of BRDF values and reshape into 2D grid values_r = np.array(values)[:, 0] values_r = values_r.reshape(2 * res, res).T # Plot values for spherical coordinates fig, ax = plt.subplots(figsize=(12, 7))