def test02_point_sample_direction(variant_scalar_spectral, spectrum_key): # Check the correctness of the sample_direction() method from mitsuba.render import SurfaceInteraction3f emitter_pos = [10, -1, 2] emitter, spectrum = create_emitter_and_spectrum(emitter_pos, spectrum_key) # Direction sampling it = SurfaceInteraction3f.zero() it.p = [0.0, -2.0, 4.5] # Some position it.time = 0.3 # Direction from the position to the point emitter d = -it.p + emitter_pos dist = ek.norm(d) d /= dist # Sample a direction on the emitter sample = [0.1, 0.5] ds, res = emitter.sample_direction(it, sample) assert ds.time == it.time assert ds.pdf == 1.0 assert ds.delta assert ek.allclose(ds.d, d) # Evalutate the spectrum spec = spectrum.eval(it) / (dist**2) assert ek.allclose(res, spec)
def test03_point_sample_direction_vec(variant_packet_spectral, spectrum_key): from mitsuba.render import SurfaceInteraction3f emitter_pos = [10, -1, 2] emitter, spectrum = create_emitter_and_spectrum(emitter_pos, spectrum_key) # Direction sampling it = SurfaceInteraction3f.zero(3) it.p = [[0.0, 0.0, 0.0], [-2.0, 0.0, -2.0], [4.5, 4.5, 0.0]] # Some positions it.time = [0.3, 0.3, 0.3] # Direction from the position to the point emitter d = -it.p + emitter_pos dist = ek.norm(d) d /= dist # Sample direction on the emitter sample = [0.1, 0.5] ds, res = emitter.sample_direction(it, sample) assert ek.all(ds.time == it.time) assert ek.all(ds.pdf == 1.0) assert ek.all(ds.delta) assert ek.allclose(ds.d, d / ek.norm(d)) # Evalutate the spectrum spec = spectrum.eval(it) / (dist**2) assert ek.allclose(res, spec)
def test04_direction_sample_construction_single(variant_scalar_rgb): from mitsuba.render import Interaction3f, DirectionSample3f, SurfaceInteraction3f # Default constructor record = DirectionSample3f() record.p = [1, 2, 3] record.n = [4, 5, 6] record.uv = [7, 8] record.d = [0, 42, -1] record.pdf = 0.002 record.dist = 0.13 assert ek.allclose(record.d, [0, 42, -1]) assert str(record) == """DirectionSample3f[ p = [1, 2, 3], n = [4, 5, 6], uv = [7, 8], time = 0, pdf = 0.002, delta = 0, object = nullptr, d = [0, 42, -1], dist = 0.13 ]""" # Construct from two interactions: ds.d should start from the reference its. its = SurfaceInteraction3f.zero() its.p = [20, 3, 40.02] its.t = 1 ref = Interaction3f.zero() ref.p = [1.6, -2, 35] record = DirectionSample3f(its, ref) d = (its.p - ref.p) / ek.norm(its.p - ref.p) assert ek.allclose(record.d, d)
def test01_point_sample_ray(variant_packet_spectral, spectrum_key): # Check the correctness of the sample_ray() method from mitsuba.core import Vector3f, warp, sample_shifted from mitsuba.render import SurfaceInteraction3f emitter_pos = [10, -1, 2] emitter, spectrum = create_emitter_and_spectrum(emitter_pos, spectrum_key) time = 0.5 wavelength_sample = [0.5, 0.33, 0.1] dir_sample = [[0.4, 0.5, 0.3], [0.1, 0.4, 0.9]] pos_sample = dir_sample # not being used anyway # Sample a ray (position, direction, wavelengths) on the emitter ray, res = emitter.sample_ray(time, wavelength_sample, pos_sample, dir_sample) # Sample wavelengths on the spectrum it = SurfaceInteraction3f.zero(3) wav, spec = spectrum.sample_spectrum(it, sample_shifted(wavelength_sample)) assert ek.allclose(res, spec * 4 * ek.pi) assert ek.allclose(ray.time, time) assert ek.allclose(ray.wavelengths, wav) assert ek.allclose(ray.d, warp.square_to_uniform_sphere(dir_sample)) assert ek.allclose(ray.o, Vector3f(emitter_pos))
def test03_sample_ray(variant_packet_spectral, spectrum_key): # Check the correctness of the sample_ray() method from mitsuba.core import warp, Frame3f, sample_shifted from mitsuba.render import SurfaceInteraction3f shape, spectrum = create_emitter_and_spectrum(spectrum_key) emitter = shape.emitter() time = 0.5 wavelength_sample = [0.5, 0.33, 0.1] pos_sample = [[0.2, 0.1, 0.2], [0.6, 0.9, 0.2]] dir_sample = [[0.4, 0.5, 0.3], [0.1, 0.4, 0.9]] # Sample a ray (position, direction, wavelengths) on the emitter ray, res = emitter.sample_ray(time, wavelength_sample, pos_sample, dir_sample) # Sample wavelengths on the spectrum it = SurfaceInteraction3f.zero(3) wav, spec = spectrum.sample_spectrum(it, sample_shifted(wavelength_sample)) # Sample a position on the shape ps = shape.sample_position(time, pos_sample) assert ek.allclose(res, spec * shape.surface_area() * ek.pi) assert ek.allclose(ray.time, time) assert ek.allclose(ray.wavelengths, wav) assert ek.allclose(ray.o, ps.p) assert ek.allclose( ray.d, Frame3f(ps.n).to_world(warp.square_to_cosine_hemisphere(dir_sample)))
def test_sample_direction(variant_scalar_spectral, spectrum_key, direction): # Check correctness of sample_direction() and pdf_direction() methods from mitsuba.render import SurfaceInteraction3f from mitsuba.core import Vector3f direction = Vector3f(direction) emitter = make_emitter(direction, spectrum_key) spectrum = make_spectrum(spectrum_key) it = SurfaceInteraction3f.zero() # Some position inside the unit sphere (i.e. within the emitter's default bounding sphere) it.p = [-0.5, 0.3, -0.1] it.time = 1.0 # Sample direction samples = [0.85, 0.13] ds, res = emitter.sample_direction(it, samples) # Direction should point *towards* the illuminated direction assert ek.allclose(ds.d, -direction / ek.norm(direction)) assert ek.allclose(ds.pdf, 1.) assert ek.allclose(emitter.pdf_direction(it, ds), 0.) assert ek.allclose(ds.time, it.time) # Check spectrum (no attenuation vs distance) spec = spectrum.eval(it) assert ek.allclose(res, spec)
def test04_sample_direction(variant_packet_spectral, spectrum_key): # Check the correctness of the sample_direction() and pdf_direction() methods from mitsuba.render import SurfaceInteraction3f shape, spectrum = create_emitter_and_spectrum(spectrum_key) emitter = shape.emitter() # Direction sampling is conditioned on a sampled position it = SurfaceInteraction3f.zero(3) it.p = [[0.2, 0.1, 0.2], [0.6, -0.9, 0.2], [0.4, 0.9, -0.2]] # Some positions it.time = 1.0 # Sample direction on the emitter samples = [[0.4, 0.5, 0.3], [0.1, 0.4, 0.9]] ds, res = emitter.sample_direction(it, samples) # Sample direction on the shape shape_ds = shape.sample_direction(it, samples) assert ek.allclose(ds.pdf, shape_ds.pdf) assert ek.allclose(ds.pdf, emitter.pdf_direction(it, ds)) assert ek.allclose(ds.d, shape_ds.d) assert ek.allclose(ds.time, it.time) # Evalutate the spectrum (divide by the pdf) spec = spectrum.eval(it) / ds.pdf assert ek.allclose(res, spec)
def test03_sample_direction(variant_packet_spectral): # Check the correctness of the sample_direction() and pdf_direction() methods from mitsuba.core import warp from mitsuba.core.math import InvFourPi from mitsuba.render import SurfaceInteraction3f emitter, spectrum = create_emitter_and_spectrum() it = SurfaceInteraction3f.zero(3) # Some positions inside the unit sphere it.p = [[-0.5, 0.3, -0.1], [0.8, -0.3, -0.2], [-0.2, 0.6, -0.6]] it.time = 1.0 # Sample direction on the emitter samples = [[0.4, 0.5, 0.3], [0.1, 0.4, 0.9]] ds, res = emitter.sample_direction(it, samples) assert ek.allclose(ds.pdf, InvFourPi) assert ek.allclose(ds.d, warp.square_to_uniform_sphere(samples)) assert ek.allclose(emitter.pdf_direction(it, ds), InvFourPi) assert ek.allclose(ds.time, it.time) # Evaluate the spectrum (divide by the pdf) spec = spectrum.eval(it) / warp.square_to_uniform_sphere_pdf(ds.d) assert ek.allclose(res, spec)
def test01_eval(variant_packet_spectral, spectrum_key): # Check the correctness of the eval() method from mitsuba.core import warp from mitsuba.core.math import InvFourPi from mitsuba.render import SurfaceInteraction3f emitter, spectrum = create_emitter_and_spectrum(spectrum_key) it = SurfaceInteraction3f.zero() assert ek.allclose(emitter.eval(it), spectrum.eval(it))
def test_eval(variant_packet_spectral, spectrum_key, lookat, cutoff_angle): # Check the correctness of the eval() method from mitsuba.render import SurfaceInteraction3f emitter, spectrum = create_emitter_and_spectrum(lookat, cutoff_angle, spectrum_key) # Check that incident direction in the illuminated direction is zero (because hitting a delta light is impossible) it = SurfaceInteraction3f.zero(3) it.wi = [0, 1, 0] assert ek.allclose(emitter.eval(it), 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))
def test02_eval(variant_packet_spectral, spectrum_key): # Check that eval() return the same values as the 'radiance' spectrum from mitsuba.render import SurfaceInteraction3f shape, spectrum = create_emitter_and_spectrum(spectrum_key) emitter = shape.emitter() it = SurfaceInteraction3f.zero(3) assert ek.allclose(emitter.eval(it), spectrum.eval(it)) # Check that eval return 0.0 when direction points inside the shape it.wi = ek.normalize([0.2, 0.2, -0.5]) assert ek.allclose(emitter.eval(it), 0.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"])
def test_sample_ray(variant_scalar_spectral, direction, spectrum_key): from mitsuba.core import Vector2f, Vector3f, sample_shifted from mitsuba.render import SurfaceInteraction3f emitter = make_emitter(direction=direction, spectrum_key=spectrum_key) spectrum = make_spectrum(spectrum_key) direction = Vector3f(direction) time = 1.0 for wavelength_sample, spatial_sample, directional_sample in zip( cycle([0.3, 0.7]), [ [0.85, 0.13], [0.16, 0.50], [0.00, 1.00], [0.32, 0.87], [0.16, 0.44], [0.17, 0.44], [0.22, 0.81], [0.12, 0.82], [0.99, 0.42], [0.72, 0.40], [0.01, 0.61], ], cycle([[0.3, 0.2]]) ): ray, _ = emitter.sample_ray( time, wavelength_sample, spatial_sample, directional_sample) # Check that ray direction is what is expected assert ek.allclose(ray.d, direction / ek.norm(direction)) # Check that ray origin is outside of bounding sphere # Bounding sphere is centered at world origin and has radius 1 without scene assert ek.norm(ray.o) >= 1. # Check that passed irradiance spectrum is used for wavelength sampling it = SurfaceInteraction3f.zero() wav, spec = spectrum.sample_spectrum( it, sample_shifted(wavelength_sample)) assert ek.allclose(ray.wavelengths, wav)
def test02_position_sample_construction_dynamic(variant_packet_rgb): from mitsuba.render import PositionSample3f, SurfaceInteraction3f n_records = 5 records = PositionSample3f.zero(n_records) # Set properties for all records at once (SoA style) # records.n = np.zeros(shape=(n_records, 3)) # records.pdf = np.zeros(shape=(n_records,)) # records.uv = np.zeros(shape=(n_records, 2)) # records.delta = np.zeros(shape=(n_records,), dtype=np.bool) records.p = np.array([[1.0, 1.0, 1.0], [0.9, 0.9, 0.9], [0.7, 0.7, 0.7], [1.2, 1.5, 1.1], [1.5, 1.5, 1.5]]) records.time = [0.0, 0.5, 0.7, 1.0, 1.5] assert str(records) == """PositionSample3fX[ p = [[1, 1, 1], [0.9, 0.9, 0.9], [0.7, 0.7, 0.7], [1.2, 1.5, 1.1], [1.5, 1.5, 1.5]], n = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]], uv = [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], time = [0, 0.5, 0.7, 1, 1.5], pdf = [0, 0, 0, 0, 0], delta = [0, 0, 0, 0, 0], object = [nullptr, nullptr, nullptr, nullptr, nullptr] ]""" # SurfaceInteraction constructor si = SurfaceInteraction3f.zero(n_records) si.time = [0.0, 0.5, 0.7, 1.0, 1.5] records = PositionSample3f(si) assert ek.all(records.time == si.time)
# Create a texture with the reference displacement map disp_tex_1 = xml.load_dict({ "type" : "bitmap", "filename": "diffuser_surface_1.jpg", "to_uv" : ScalarTransform4f.scale([1, -1, 1]) # texture is upside-down }).expand()[0] # Create a texture with another displacement map disp_tex_2 = xml.load_dict({ "type" : "bitmap", "filename": "diffuser_surface_2.jpg", "to_uv" : ScalarTransform4f.scale([1, -1, 1]) # texture is upside-down }).expand()[0] # Create a fake surface interaction with an entry per vertex on the mesh mesh_si = SurfaceInteraction3f.zero(vertex_count) mesh_si.uv = ravel(params['grid_mesh.vertex_texcoords_buf'], dim=2) # Evaluate the displacement map for the entire mesh disp_tex_diffuser_1 = disp_tex_1.eval_1(mesh_si) disp_tex_diffuser_2 = disp_tex_2.eval_1(mesh_si) # Apply displacement to mesh vertex positions and update scene (e.g. OptiX BVH) def apply_displacement(disp, amplitude = 0.05): new_positions = disp.eval_1(mesh_si) * normals_initial * amplitude + positions_initial unravel(new_positions, params['grid_mesh.vertex_positions_buf']) params.set_dirty('grid_mesh.vertex_positions_buf') params.update() # Change amp to adjust the magnitude of displacement amp = 0.1
def pdf_functor(w, *args): plugin = instantiate(args) si = SurfaceInteraction3f.zero(ek.slices(w)) si.wavelengths = w return plugin.pdf(si)[0]
def sample_functor(sample, *args): plugin = instantiate(args) si = SurfaceInteraction3f.zero(ek.slices(sample)) wavelength, weight = plugin.sample(si, sample_shifted(sample[0])) return Vector1f(wavelength[0])
def make_context(n): si = SurfaceInteraction3f.zero(n) si.wi = wi ek.set_slices(si.wi, n) si.wavelengths = [] return (si, ctx)