def atest_material_manager(self): sam_mgr = SampledManager() register_rgb_shadepoint() runtimes = [Runtime(), Runtime()] mat = Material() mat.load('lambertian', sam_mgr, spectral=False) mat.set_value('diffuse', RGBSpectrum(0.2, 0.3, 0.4)) mgr = MaterialManager() mgr.add('material1', mat) mgr.compile_shaders(sam_mgr, spectral=False) mgr.prepare_shaders(runtimes) code = """ hp = HitPoint() sp = ShadePoint() material_reflectance(hp, sp, 0) spec = sp.material_reflectance """ spec = RGBArg('spec', RGBSpectrum(0.5, 0.5, 0.5)) shader = Shader(code=code, args=[spec]) shader.compile(shaders=[mgr.ref_shader]) shader.prepare(runtimes) shader.execute() s = shader.get_value('spec') ls = RGBSpectrum(0.2, 0.3, 0.4) * (1.0 / math.pi) self.assertAlmostEqual(s.r, ls.r) self.assertAlmostEqual(s.g, ls.g) self.assertAlmostEqual(s.b, ls.b)
class SampleFilter: def __init__(self, xwidth=1.0, ywidth=1.0): path = os.path.dirname(__file__) path = os.path.join(path, 'flt_shaders') self._loader = Loader([path]) self.xwidth = xwidth self.ywidth = ywidth def load(self, shader_name): args = [] text = self._loader.load(shader_name, 'props.txt') if text is not None: args = parse_args(text) args.append(FloatArg('xwidth', self.xwidth)) args.append(FloatArg('ywidth', self.ywidth)) code = self._loader.load(shader_name, 'code.py') if code is None: raise ValueError("code.py in %s shader dont exist!" % shader_name) func_args = [StructArgPtr('sample', Sample.factory())] self.shader = Shader(code=code, args=args, name='filter_sample', func_args=func_args, is_func=True) def compile(self, shaders=[]): self.shader.compile(shaders) def prepare(self, runtimes): self.shader.prepare(runtimes)
def test_isect_b_sph(self): sph_shader = Sphere.isect_b_shader('isect_b_sphere') sph_shader.compile() runtimes = [Runtime()] sph_shader.prepare(runtimes) code = """ min_dist = 99999.0 p1 = isect_b_sphere(ray, sphere, min_dist) """ direction = Vector3(-1.0, -1.0, -1.0) direction.normalize() ray = Ray(Vector3(5.0, 5.0, 5.0), direction) sphere = Sphere(Vector3(0.0, 0.0, 0.0), 2.0, 0) r_arg = StructArg('ray', ray) sph_arg = StructArg('sphere', sphere) p1 = IntArg('p1', 6) args = [r_arg, sph_arg, p1] shader = Shader(code=code, args=args) shader.compile([sph_shader.shader]) shader.prepare(runtimes) shader.execute() result = shader.get_value('p1') self.assertEqual(result, 1)
def test_mesh_b(mesh, nrays=1): dep_shader = type(mesh).isect_b_shader('ray_flat_mesh_b_isect') dep_shader.compile() runtimes = [Runtime()] dep_shader.prepare(runtimes) code = """ min_dist = 99999.0 ret = ray_flat_mesh_b_isect(ray, mesh, min_dist) """ origin = calculate_origin(mesh) rpoint = random_in_bbox(mesh._grid.bbox) direction = rpoint - origin direction.normalize() ray = Ray(origin, direction) r_arg = StructArg('ray', ray) mesh_arg = StructArg('mesh', mesh) ret = IntArg('ret', 6) args = [r_arg, mesh_arg, ret] shader = Shader(code=code, args=args) shader.compile([dep_shader.shader]) shader.prepare(runtimes) hp = mesh.isect_b(ray) shader.execute() print("Bool isect", hp, shader.get_value('ret'))
def test_sampled_to_rgb(self): runtimes = [Runtime()] color_mgr = SampledManager() s_to_rgb = spectrum_to_rgb_shader(color_mgr) s_to_rgb.compile(color_mgr=color_mgr) s_to_rgb.prepare(runtimes) code = """ value = spectrum_to_rgb(color) """ spec = RGBSpectrum(0.3, 0.5, 0.4) spec = color_mgr.rgb_to_sampled(spec) col = SampledArg('color', spec) val = Vec3Arg('value', Vector3(0.0, 0.0, 0.0)) shader = Shader(code=code, args=[col, val]) shader.compile(shaders=[s_to_rgb], color_mgr=color_mgr) shader.prepare(runtimes) shader.execute() value = shader.get_value('value') vv = color_mgr.sampled_to_rgb(spec) self.assertAlmostEqual(value.x, vv.r) self.assertAlmostEqual(value.y, vv.g) self.assertAlmostEqual(value.z, vv.b, places=6)
def test_isect_b_rect(self): rect_shader = Rectangle.isect_b_shader('isect_b_rectangle') rect_shader.compile() runtimes = [Runtime()] rect_shader.prepare(runtimes) code = """ min_dist = 99999.0 p1 = isect_b_rectangle(ray, rectangle, min_dist) """ origin = Vector3(3.0, 2.5, 0.0) direction = Vector3(0.0, 0.1, 0.88) direction.normalize() ray = Ray(origin, direction) point = Vector3(0.0, 0.0, 55.92) e1 = Vector3(55.28, 0.0, 0.0) e2 = Vector3(0.0, 54.88, 0.0) normal = Vector3(0.0, 0.0, -1.0) rectangle = Rectangle(point, e1, e2, normal) r_arg = StructArg('ray', ray) sph_arg = StructArg('rectangle', rectangle) p1 = IntArg('p1', 6) args = [r_arg, sph_arg, p1] shader = Shader(code=code, args=args) shader.compile([rect_shader.shader]) shader.prepare(runtimes) shader.execute() result = shader.get_value('p1') self.assertEqual(result, 1)
class SamplerGenerator(): def __init__(self, sampler): self.sampler = sampler self.prepare_standalone() def prepare_standalone(self): self.sampler.create_shader() runtimes = [Runtime()] self.sampler.compile() self.sampler.prepare(runtimes) code = """ ret = generate_sample(sample) """ args = [StructArg('sample', Sample.factory()), IntArg('ret', 11)] self._standalone = Shader(code=code, args=args) self._standalone.compile([self.sampler.shader]) self._standalone.prepare(runtimes) def generate_sample(self): self._standalone.execute() ret = self._standalone.get_value('ret') if ret == 0: return False sample = self._standalone.get_value('sample') return sample
def test_rgb_area_light(self): sam_mgr = SampledManager() register_rgb_shadepoint() point = Vector3(0.0, 0.0, 55.92) e1 = Vector3(55.28, 0.0, 0.0) e2 = Vector3(0.0, 54.88, 0.0) normal = Vector3(0.0, 0.0, -1.0) rectangle = Rectangle(point, e1, e2, normal) material = Material() material.load('lambertian_emiter', sam_mgr) e = RGBSpectrum(0.5, 0.5, 0.5) material.set_value('emission', e) runtimes = [Runtime()] lgt = AreaLight(shape=rectangle, material=material) lgt.load('general', sam_mgr, spectral=False) lgt.compile() lgt.prepare(runtimes) ptrs = lgt.shader.get_ptrs() ptr_func = PointerArg('ptr_func', ptrs[0]) spec = RGBArg('spec', RGBSpectrum(0.5, 0.5, 0.5)) wi = Vec3Arg('wi', Vector3(0.0, 0.0, 0.0)) pos = Vec3Arg('position', Vector3(0.0, 0.0, 0.0)) n = Vec3Arg('normal', Vector3(0.0, 0.0, 0.0)) pdf = FloatArg('pdf', 0.0) emission = RGBArg('emission', RGBSpectrum(0.0, 0.0, 0.0)) code = """ hp = HitPoint() hp.hit = (4.0, 5, 6) sp = ShadePoint() __light_radiance(hp, sp, ptr_func) spec = sp.light_intensity wi = sp.wi position = sp.light_position normal = sp.light_normal pdf = sp.light_pdf emission = sp.material_emission """ shader = Shader(code=code, args=[ptr_func, wi, spec, pos, n, pdf, emission]) shader.compile() shader.prepare(runtimes) shader.execute() print("Position ", shader.get_value('position')) print("Normal ", shader.get_value('normal')) print("Light pdf ", shader.get_value('pdf')) print("Emission ", shader.get_value('emission')) print("Wi ", shader.get_value('wi')) print("Intensity ", shader.get_value('spec'))
class Tmo: def __init__(self): path = os.path.dirname(__file__) path = os.path.join(path, 'shaders') self._loader = Loader([path]) self._shader = None self._runtime = None @property def shader(self): return self._shader def load(self, name): props = self._loader.load(name, 'props.txt') args = [] if props is not None: args = parse_args(props) in_img = StructArg('input_image', ImagePRGBA(1, 1)) out_img = StructArg('output_image', ImagePRGBA(1, 1)) args.extend([in_img, out_img]) code = self._loader.load(name, 'code.py') self._shader = Shader(code=code, args=args) self._shader.compile() self._runtime = Runtime() self._shader.prepare([self._runtime]) def tmo(self, in_img, out_img): """ Perform tone mapping on input image Args: in_img: Input image out_img: Output image """ if self._shader is None: raise ValueError("Shader is not loaded.") if not isinstance(in_img, ImagePRGBA) and not isinstance( out_img, ImagePRGBA): raise ValueError("ImagePRGBA is expected insted of", in_img, out_img) w1, h1 = in_img.size() w2, h2 = out_img.size() if w1 != w2 or h1 != h2: raise ValueError("Input and output image must be same size!") self._shader.set_value('input_image', in_img) self._shader.set_value('output_image', out_img) self._shader.execute()
def test_linear(self): sphere = Sphere(Vector3(0.0, 0.0, 0.0), 2.0, 0) mgr = ShapeManager() mgr.add('sph1', sphere) sphere2 = Sphere(Vector3(0.0, 2.0, 0.0), 3.0, 0) mgr.add('sph2', sphere2) isector = LinearIsect(mgr) runtimes = [Runtime()] direction = Vector3(-1.0, -1.0, -1.0) direction.normalize() ray = Ray(Vector3(5.0, 5.0, 5.0), direction) isector.compile() isector.prepare(runtimes) code = """ min_dist = 99999.0 p1 = isect_scene(ray, hitpoint, min_dist) """ direction = Vector3(-1.0, -1.0, -1.0) direction.normalize() ray = Ray(Vector3(5.0, 5.0, 5.0), direction) hitpoint = HitPoint(0.0, Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, 0.0), 6, 0.0, 0.0) r_arg = StructArg('ray', ray) harg = StructArg('hitpoint', hitpoint) p1 = IntArg('p1', 6) args = [r_arg, harg, p1] shader = Shader(code=code, args=args) shader.compile([isector.shader]) shader.prepare(runtimes) hp2 = isector.isect(ray) shader.execute() hitpoint = shader.get_value('hitpoint') self.assertAlmostEqual(hp2.t, hitpoint.t, places=5) self.assertEqual(hp2.mat_idx, hitpoint.mat_idx) n1 = hp2.normal n2 = hitpoint.normal self.assertAlmostEqual(n1.x, n2.x) self.assertAlmostEqual(n1.y, n2.y, places=6) self.assertAlmostEqual(n1.z, n2.z) self.assertAlmostEqual(hitpoint.hit.x, hp2.hit.x, places=6) self.assertAlmostEqual(hitpoint.hit.y, hp2.hit.y, places=6) self.assertAlmostEqual(hitpoint.hit.z, hp2.hit.z, places=6) result = shader.get_value('p1') self.assertEqual(result, 1)
def test_isect_rect(self): rect_shader = Rectangle.isect_shader('isect_rectangle') rect_shader.compile() runtimes = [Runtime()] rect_shader.prepare(runtimes) code = """ min_dist = 99999.0 p1 = isect_rectangle(ray, rectangle, hitpoint, min_dist) """ origin = Vector3(3.0, 2.5, 0.0) direction = Vector3(0.0, 0.1, 0.88) direction.normalize() ray = Ray(origin, direction) point = Vector3(0.0, 0.0, 55.92) e1 = Vector3(55.28, 0.0, 0.0) e2 = Vector3(0.0, 54.88, 0.0) normal = Vector3(0.0, 0.0, -1.0) rectangle = Rectangle(point, e1, e2, normal) hitpoint = HitPoint.factory() hitpoint.mat_idx = 5 r_arg = StructArg('ray', ray) sph_arg = StructArg('rectangle', rectangle) harg = StructArg('hitpoint', hitpoint) p1 = IntArg('p1', 6) args = [r_arg, sph_arg, harg, p1] shader = Shader(code=code, args=args) shader.compile([rect_shader.shader]) shader.prepare(runtimes) shader.execute() hp2 = rectangle.isect(ray) hitpoint = shader.get_value('hitpoint') self.assertAlmostEqual(hp2.t, hitpoint.t, places=5) self.assertEqual(hp2.mat_idx, hitpoint.mat_idx) n1 = hp2.normal n2 = hitpoint.normal self.assertAlmostEqual(n1.x, n2.x) self.assertAlmostEqual(n1.y, n2.y) self.assertAlmostEqual(n1.z, n2.z) self.assertAlmostEqual(hitpoint.hit.x, hp2.hit.x, places=5) self.assertAlmostEqual(hitpoint.hit.y, hp2.hit.y, places=5) self.assertAlmostEqual(hitpoint.hit.z, hp2.hit.z, places=5) result = shader.get_value('p1') self.assertEqual(result, 1)
class Tmo: def __init__(self): path = os.path.dirname(__file__) path = os.path.join(path, 'shaders') self._loader = Loader([path]) self._shader = None self._runtime = None @property def shader(self): return self._shader def load(self, name): props = self._loader.load(name, 'props.txt') args = [] if props is not None: args = parse_args(props) in_img = StructArg('input_image', ImagePRGBA(1, 1)) out_img = StructArg('output_image', ImagePRGBA(1, 1)) args.extend([in_img, out_img]) code = self._loader.load(name, 'code.py') self._shader = Shader(code=code, args=args) self._shader.compile() self._runtime = Runtime() self._shader.prepare([self._runtime]) def tmo(self, in_img, out_img): """ Perform tone mapping on input image Args: in_img: Input image out_img: Output image """ if self._shader is None: raise ValueError("Shader is not loaded.") if not isinstance(in_img, ImagePRGBA) and not isinstance(out_img, ImagePRGBA): raise ValueError("ImagePRGBA is expected insted of", in_img, out_img) w1, h1 = in_img.size() w2, h2 = out_img.size() if w1 != w2 or h1 != h2: raise ValueError("Input and output image must be same size!") self._shader.set_value('input_image', in_img) self._shader.set_value('output_image', out_img) self._shader.execute()
def test_mesh(mesh, nrays=1): dep_shader = type(mesh).isect_shader('ray_flat_mesh_isect') dep_shader.compile() runtimes = [Runtime()] dep_shader.prepare(runtimes) code = """ min_dist = 99999.0 ret = ray_flat_mesh_isect(ray, mesh, hitpoint, min_dist) """ ray = generate_ray(mesh) hitpoint = HitPoint(0.0, Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, 0.0), 6, 0.0, 0.0) r_arg = StructArg('ray', ray) mesh_arg = StructArg('mesh', mesh) harg = StructArg('hitpoint', hitpoint) ret = IntArg('ret', 6) args = [r_arg, mesh_arg, harg, ret] shader = Shader(code=code, args=args) shader.compile([dep_shader.shader]) shader.prepare(runtimes) for i in range(nrays): ray = generate_ray(mesh) # origin = Vector3(-0.21099534597992897,-0.02090535280108452,-0.09716709856688976) # direction = Vector3(0.7856996643888073,0.4629769683728137,0.4102783983292736) # ray = Ray(origin, direction) shader.set_value('ray', ray) hp2 = mesh.isect(ray) hp, index = isect_ray_mesh(ray, mesh) shader.execute() # print(hp, shader.get_value('ret')) if hp: ret = shader.get_value('ret') hp_new = shader.get_value('hitpoint') if round(hp.t - hp_new.t, 5) != 0: print(hp.t, hp_new.t, ret, index, hp2.t) print(ray.origin) print(ray.direction) p0, p1, p2 = mesh.get_points(index) print(p0) print(p1) print(p2) print('------------------------------------------')
def test_isect_flat_triangle1(self): runtimes = [Runtime()] tri_shader = FlatTriangle.isect_shader('isect_flat_triangle') tri_shader.compile() tri_shader.prepare(runtimes) p0 = Vector3(-0.0831229984, 0.0591476, -0.03213749) p1 = Vector3(-0.082775, 0.059025, -0.031787) p2 = Vector3(-0.0831229, 0.0591773, -0.031787) origin = Vector3(-0.21276909825205803, -0.021492251798510553, -0.09822520208358765) direction = Vector3(0.7788769269741005, 0.4843782624535974, 0.3984073687694737) ray = Ray(origin, direction) hitpoint = HitPoint(0.0, Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, 0.0), 6, 0.0, 0.0) t = FlatTriangle(p0, p1, p2) code = """ min_dist = 150.0 ret = isect_flat_triangle(ray, triangle, hitpoint, min_dist) """ r_arg = StructArg('ray', ray) tri_arg = StructArg('triangle', t) harg = StructArg('hitpoint', hitpoint) ret = IntArg('ret', 6) args = [r_arg, tri_arg, harg, ret] shader = Shader(code=code, args=args) shader.compile([tri_shader.shader]) shader.prepare(runtimes) shader.execute() min_dist = 150.0 hit = t.isect(ray, min_dist) hp = shader.get_value('hitpoint') self.assertAlmostEqual(hit.t, hp.t, places=6) self._almost_equal_vec3(hit.hit, hp.hit, places=6) self._almost_equal_vec3(hit.normal, hp.normal, places=6) self.assertEqual(hit.mat_idx, hp.mat_idx) self.assertAlmostEqual(hit.u, hp.u) self.assertAlmostEqual(hit.v, hp.v)
def test_sampled_point_light(self): sam_mgr = SampledManager() register_sampled_shadepoint(sam_mgr) runtimes = [Runtime()] lgt = GeneralLight() lgt.load('point', sam_mgr, spectral=True) lgt.set_value('intensity', RGBSpectrum(0.3, 0.3, 0.3)) lgt.set_value('position', Vector3(2.0, 2.0, 2.0)) lgt.compile() lgt.prepare(runtimes) ptrs = lgt.shader.get_ptrs() ptr_func = PointerArg('ptr_func', ptrs[0]) spec = SampledArg('spec', sam_mgr.zero()) wi = Vec3Arg('wi', Vector3(0.0, 0.0, 0.0)) pos = Vec3Arg('position', Vector3(0.0, 0.0, 0.0)) code = """ hp = HitPoint() hp.hit = (4.0, 5, 6) sp = ShadePoint() __light_radiance(hp, sp, ptr_func) spec = sp.light_intensity wi = sp.wi position = sp.light_position """ shader = Shader(code=code, args=[ptr_func, wi, spec, pos]) shader.compile() shader.prepare(runtimes) shader.execute() wi = Vector3(2.0, 2.0, 2.0) - Vector3(4.0, 5.0, 6.0) wi.normalize() wi_s = shader.get_value('wi') self.assertAlmostEqual(wi.x, wi_s.x) self.assertAlmostEqual(wi.y, wi_s.y) self.assertAlmostEqual(wi.z, wi_s.z) p = Vector3(2.0, 2.0, 2.0) p_s = shader.get_value('position') self.assertAlmostEqual(p.x, p_s.x) self.assertAlmostEqual(p.y, p_s.y) self.assertAlmostEqual(p.z, p_s.z) s = sam_mgr.rgb_to_sampled(RGBSpectrum(0.3, 0.3, 0.3), illum=True) s_s = shader.get_value('spec') for i in range(len(s.samples)): self.assertAlmostEqual(s.samples[i], s_s.samples[i])
def test_isect_flat_triangle(self): runtimes = [Runtime()] tri_shader = FlatTriangle.isect_shader('isect_flat_triangle') tri_shader.compile() tri_shader.prepare(runtimes) p0 = Vector3(2.2, 4.4, 6.6) p1 = Vector3(1.1, 1.1, 1.1) p2 = Vector3(5.1, -1.1, 5.1) origin = Vector3(0.0, 0.0, 0.0) direction = Vector3(3, 3.0, 3.01) direction.normalize() ray = Ray(origin, direction) hitpoint = HitPoint(0.0, Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, 0.0), 6, 0.0, 0.0) t = FlatTriangle(p0, p1, p2) code = """ min_dist = 150.0 ret = isect_flat_triangle(ray, triangle, hitpoint, min_dist) """ r_arg = StructArg('ray', ray) tri_arg = StructArg('triangle', t) harg = StructArg('hitpoint', hitpoint) ret = IntArg('ret', 6) args = [r_arg, tri_arg, harg, ret] shader = Shader(code=code, args=args) shader.compile([tri_shader.shader]) shader.prepare(runtimes) shader.execute() min_dist = 150.0 hit = t.isect(ray, min_dist) hp = shader.get_value('hitpoint') self.assertAlmostEqual(hit.t, hp.t, places=6) self._almost_equal_vec3(hit.hit, hp.hit, places=6) self._almost_equal_vec3(hit.normal, hp.normal, places=6) self.assertEqual(hit.mat_idx, hp.mat_idx) self.assertAlmostEqual(hit.u, hp.u) self.assertAlmostEqual(hit.v, hp.v)
def test_isect_flat_triangle1(self): runtimes = [Runtime()] tri_shader = FlatTriangle.isect_shader('isect_flat_triangle') tri_shader.compile() tri_shader.prepare(runtimes) p0 = Vector3(-0.0831229984, 0.0591476, -0.03213749) p1 = Vector3(-0.082775, 0.059025, -0.031787) p2 = Vector3(-0.0831229, 0.0591773, -0.031787) origin = Vector3(-0.21276909825205803,-0.021492251798510553,-0.09822520208358765) direction = Vector3(0.7788769269741005,0.4843782624535974,0.3984073687694737) ray = Ray(origin, direction) hitpoint = HitPoint(0.0, Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, 0.0), 6, 0.0, 0.0) t = FlatTriangle(p0, p1, p2) code = """ min_dist = 150.0 ret = isect_flat_triangle(ray, triangle, hitpoint, min_dist) """ r_arg = StructArg('ray', ray) tri_arg = StructArg('triangle', t) harg = StructArg('hitpoint', hitpoint) ret = IntArg('ret', 6) args = [r_arg, tri_arg, harg, ret] shader = Shader(code=code, args=args) shader.compile([tri_shader.shader]) shader.prepare(runtimes) shader.execute() min_dist = 150.0 hit = t.isect(ray, min_dist) hp = shader.get_value('hitpoint') self.assertAlmostEqual(hit.t, hp.t, places=6) self._almost_equal_vec3(hit.hit, hp.hit, places=6) self._almost_equal_vec3(hit.normal, hp.normal, places=6) self.assertEqual(hit.mat_idx, hp.mat_idx) self.assertAlmostEqual(hit.u, hp.u) self.assertAlmostEqual(hit.v, hp.v)
def test_isect_b_flat_triangle(self): runtimes = [Runtime()] tri_shader = FlatTriangle.isect_b_shader('isect_b_flat_triangle') tri_shader.compile() tri_shader.prepare(runtimes) p0 = Vector3(2.2, 4.4, 6.6) p1 = Vector3(1.1, 1.1, 1.1) p2 = Vector3(5.1, -1.1, 5.1) origin = Vector3(0.0, 0.0, 0.0) direction = Vector3(3, 3.0, 3.01) direction.normalize() ray = Ray(origin, direction) t = FlatTriangle(p0, p1, p2) code = """ min_dist = 150.0 ret = isect_b_flat_triangle(ray, triangle, min_dist) """ r_arg = StructArg('ray', ray) tri_arg = StructArg('triangle', t) ret = IntArg('ret', 6) args = [r_arg, tri_arg, ret] shader = Shader(code=code, args=args) shader.compile([tri_shader.shader]) shader.prepare(runtimes) shader.execute() min_dist = 150.0 hit = t.isect_b(ray, min_dist) hit2 = shader.get_value('ret') if hit2 == 0: hit2 = False elif hit2 == 1: hit2 = True else: raise ValueError("Unexpected value for isect flat triangle ", hit2) self.assertEqual(hit, hit2)
def test_isect_sph(self): sph_shader = Sphere.isect_shader('isect_sphere') sph_shader.compile() runtimes = [Runtime()] sph_shader.prepare(runtimes) code = """ min_dist = 99999.0 p1 = isect_sphere(ray, sphere, hitpoint, min_dist) """ direction = Vector3(-1.0, -1.0, -1.0) direction.normalize() ray = Ray(Vector3(5.0, 5.0, 5.0), direction) sphere = Sphere(Vector3(0.0, 0.0, 0.0), 2.0, 0) hitpoint = HitPoint(0.0, Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, 0.0), 6, 0.0, 0.0) r_arg = StructArg('ray', ray) sph_arg = StructArg('sphere', sphere) harg = StructArg('hitpoint', hitpoint) p1 = IntArg('p1', 6) args = [r_arg, sph_arg, harg, p1] shader = Shader(code=code, args=args) shader.compile([sph_shader.shader]) shader.prepare(runtimes) shader.execute() hp2 = sphere.isect(ray) hitpoint = shader.get_value('hitpoint') self.assertAlmostEqual(hp2.t, hitpoint.t) self.assertEqual(hp2.mat_idx, hitpoint.mat_idx) n1 = hp2.normal n2 = hitpoint.normal self.assertAlmostEqual(n1.x, n2.x) self.assertAlmostEqual(n1.y, n2.y) self.assertAlmostEqual(n1.z, n2.z) self.assertAlmostEqual(hitpoint.hit.x, hp2.hit.x) self.assertAlmostEqual(hitpoint.hit.y, hp2.hit.y) self.assertAlmostEqual(hitpoint.hit.z, hp2.hit.z) result = shader.get_value('p1') self.assertEqual(result, 1)
def test_light_manager(self): sam_mgr = SampledManager() register_rgb_shadepoint() runtimes = [Runtime(), Runtime()] lgt = GeneralLight() lgt.load('point', sam_mgr, spectral=False) lgt2 = GeneralLight() lgt2.load('point', sam_mgr, spectral=False) lgt2.set_value('intensity', RGBSpectrum(0.3, 0.3, 0.3)) lgt2.set_value('position', Vector3(2.0, 2.0, 2.0)) mgr = LightManager() mgr.add('light1', lgt) mgr.add('light2', lgt2) mgr.compile_shaders(sam_mgr, spectral=False) mgr.prepare_shaders(runtimes) code = """ hp = HitPoint() hp.hit = (4.0, 5, 6) sp = ShadePoint() light_radiance(hp, sp, 1) wi = sp.wi n = number_of_lights() """ wi = Vec3Arg('wi', Vector3(0.0, 0.0, 0.0)) nlights = IntArg('n', 999) shader = Shader(code=code, args=[wi, nlights]) shader.compile(shaders=[mgr.rad_shader, mgr.nlights_shader]) shader.prepare(runtimes) shader.execute() wi = Vector3(2.0, 2.0, 2.0) - Vector3(4.0, 5.0, 6.0) wi.normalize() wi_s = shader.get_value('wi') self.assertAlmostEqual(wi.x, wi_s.x) self.assertAlmostEqual(wi.y, wi_s.y) self.assertAlmostEqual(wi.z, wi_s.z) self.assertEqual(2, shader.get_value('n'))
def test_material_sampling_manager(self): sam_mgr = SampledManager() register_rgb_shadepoint() runtimes = [Runtime(), Runtime()] mat = Material() mat.load('lambertian', sam_mgr, spectral=False) mat.set_value('diffuse', RGBSpectrum(0.2, 0.3, 0.4)) mgr = MaterialManager() mgr.add('material1', mat) mgr.compile_shaders(sam_mgr, spectral=False) mgr.prepare_shaders(runtimes) code = """ hp = HitPoint() hp.normal = (0.1, 0.4, 0.66) hp.normal = normalize(hp.normal) sp = ShadePoint() material_sampling(hp, sp, 0) pdf = sp.pdf wi = sp.wi spec = sp.material_reflectance """ pdf = FloatArg('pdf', 0.0) wi = Vec3Arg('wi', Vector3(0.0, 0.0, 0.0)) spec = RGBArg('spec', RGBSpectrum(0.5, 0.5, 0.5)) shader = Shader(code=code, args=[pdf, wi, spec]) shader.compile(shaders=[mgr.sampling_shader]) shader.prepare(runtimes) shader.execute() s = shader.get_value('pdf') print(s) s = shader.get_value('wi') print(s) s = shader.get_value('spec') print(s) normal = Vector3(0.1, 0.4, 0.66) normal.normalize() print(cos_hemisphere(r1=0.1, r2=0.06, normal=normal, e=1.0))
def test_material_sampling_manager(self): sam_mgr = SampledManager() register_rgb_shadepoint() runtimes = [Runtime(), Runtime()] mat = Material() mat.load('lambertian', sam_mgr, spectral=False) mat.set_value('diffuse', RGBSpectrum(0.2, 0.3, 0.4)) mgr = MaterialManager() mgr.add('material1', mat) mgr.compile_shaders(sam_mgr, spectral=False) mgr.prepare_shaders(runtimes) code = """ hp = HitPoint() hp.normal = (0.1, 0.4, 0.66) hp.normal = normalize(hp.normal) sp = ShadePoint() material_sampling(hp, sp, 0) pdf = sp.pdf wi = sp.wi spec = sp.material_reflectance """ pdf = FloatArg('pdf', 0.0) wi = Vec3Arg('wi', Vector3(0.0, 0.0, 0.0)) spec = RGBArg('spec', RGBSpectrum(0.5, 0.5, 0.5)) shader = Shader(code=code, args=[pdf, wi, spec]) shader.compile(shaders=[mgr.sampling_shader]) shader.prepare(runtimes) shader.execute() s = shader.get_value('pdf') print(s) s = shader.get_value('wi') print(s) s = shader.get_value('spec') print(s) normal = Vector3(0.1, 0.4, 0.66) normal.normalize() print(cos_hemisphere(r1=0.1, r2=0.06, normal=normal,e=1.0))
class Integrator: def __init__(self): path = os.path.dirname(__file__) path = os.path.join(path, 'int_shaders') self._loader = Loader([path]) def load(self, shader_name, color_mgr): text = self._loader.load(shader_name, 'props.txt') args = [] if text is not None: args = parse_args(text) code = self._loader.load(shader_name, 'code.py') if code is None: raise ValueError("Integrator %s code is missing!" % shader_name) #array of shadepoints for debuging purpose sp = ShadePoint.factory(color_mgr.zero()) arr = ObjArray(sp) for i in range(10): arr.append(sp) arg = ArrayArg('path_array', arr) args.append(arg) hdr_buffer = StructArg('hdr_buffer', ImagePRGBA(1, 1)) args.append(hdr_buffer) self.shader = Shader(code=code, args=args) self._color_mgr = color_mgr def compile(self, shaders=[]): self.shader.compile(shaders, color_mgr=self._color_mgr) def prepare(self, runtimes): self.shader.prepare(runtimes) def execute(self, hdr_buffer): self.shader.set_value('hdr_buffer', hdr_buffer) self.shader.execute()
def test_rgb_luminance(self): runtimes = [Runtime()] color_mgr = RGBManager() lum_shader = luminance_shader(color_mgr) lum_shader.compile(color_mgr=color_mgr) lum_shader.prepare(runtimes) code = """ value = luminance(color) """ spec = RGBSpectrum(0.3, 0.5, 0.7) col = RGBArg('color', spec) val = FloatArg('value', 0.0) shader = Shader(code=code, args=[col, val]) shader.compile(shaders=[lum_shader], color_mgr=color_mgr) shader.prepare(runtimes) shader.execute() value = shader.get_value('value') vv = color_mgr.luminance(spec) self.assertAlmostEqual(value, vv)
def test_linear_visiblity(self): sphere = Sphere(Vector3(0.0, 0.0, 0.0), 2.0, 0) mgr = ShapeManager() mgr.add('sph1', sphere) sphere2 = Sphere(Vector3(0.0, 2.0, 0.0), 3.0, 0) mgr.add('sph2', sphere2) isector = LinearIsect(mgr) runtimes = [Runtime()] direction = Vector3(-1.0, -1.0, -1.0) direction.normalize() ray = Ray(Vector3(5.0, 5.0, 5.0), direction) isector.compile() isector.prepare(runtimes) code = """ p1 = (9, 8, 7) p2 = (-2, -5, -3) ret = visibility(p1, p2) """ ret = IntArg('ret', 6) args = [ret] shader = Shader(code=code, args=args) shader.compile([isector.visible_shader]) shader.prepare(runtimes) p1 = Vector3(9.0, 8.0, 7.0) p2 = Vector3(-2.0, -5.0, -3.0) ret = isector.visibility(p1, p2) shader.execute() ret_s = shader.get_value('ret') if ret is True and ret_s == 0: raise ValueError("Linear visiblity is calculated wrong", ret, ret_s) if ret is False and ret_s == 1: raise ValueError("Linear visiblity is calculated wrong", ret, ret_s)
def test_rgb_to_rgb(self): runtimes = [Runtime()] color_mgr = RGBManager() s_to_rgb = spectrum_to_rgb_shader(color_mgr) s_to_rgb.compile(color_mgr=color_mgr) s_to_rgb.prepare(runtimes) code = """ value = spectrum_to_rgb(color) """ spec = RGBSpectrum(0.3, 0.5, 0.4) col = RGBArg('color', spec) val = Vec3Arg('value', Vector3(0.0, 0.0, 0.0)) shader = Shader(code=code, args=[col, val]) shader.compile(shaders=[s_to_rgb], color_mgr=color_mgr) shader.prepare(runtimes) shader.execute() value = shader.get_value('value') self.assertAlmostEqual(value.x, 0.3) self.assertAlmostEqual(value.y, 0.5) self.assertAlmostEqual(value.z, 0.4)
def test_rgb_to_rgb_spectrum(self): runtimes = [Runtime()] color_mgr = RGBManager() rgb_to_spec = rgb_to_spectrum_shader(color_mgr) rgb_to_spec.compile(color_mgr=color_mgr) rgb_to_spec.prepare(runtimes) code = """ spec = rgb_to_spectrum(color) """ val = Vector3(0.3, 0.5, 0.7) col = Vec3Arg('color', val) spec = RGBArg('spec', RGBSpectrum(0.0, 0.0, 0.0)) shader = Shader(code=code, args=[col, spec]) shader.compile(shaders=[rgb_to_spec], color_mgr=color_mgr) shader.prepare(runtimes) shader.execute() value = shader.get_value('spec') self.assertAlmostEqual(value.r, val.x) self.assertAlmostEqual(value.g, val.y) self.assertAlmostEqual(value.b, val.z)
def test_rgb_to_sampled_spectrum(self): runtimes = [Runtime()] color_mgr = SampledManager() rgb_to_spec = rgb_to_spectrum_shader(color_mgr) rgb_to_spec.compile(color_mgr=color_mgr) rgb_to_spec.prepare(runtimes) code = """ spec = rgb_to_spectrum(color) """ val = Vector3(0.3, 0.5, 0.7) col = Vec3Arg('color', val) spec = SampledArg('spec', color_mgr.zero()) shader = Shader(code=code, args=[col, spec]) shader.compile(shaders=[rgb_to_spec], color_mgr=color_mgr) shader.prepare(runtimes) shader.execute() value = shader.get_value('spec') vv = color_mgr.rgb_to_sampled(RGBSpectrum(val.x, val.y, val.z)) for i in range(len(value.samples)): self.assertAlmostEqual(value.samples[i], vv.samples[i], places=6)
class Material: def __init__(self): path = os.path.dirname(__file__) path = os.path.join(path, 'mat_shaders') self._loader = Loader([path]) self._bsdf_shader = None self._sampling_shader = None self._shader_name = None def is_emissive(self): if self._shader_name is None: return False return self._loader.exist(self._shader_name, 'emission.py') def _func_args(self, spectrum): func_args = [ StructArgPtr('hitpoint', HitPoint.factory()), StructArgPtr('shadepoint', ShadePoint.factory(spectrum)) ] return func_args def _load_args(self): args = [] text = self._loader.load(self._shader_name, 'props.txt') if text is not None: args = parse_args(text, self._color_mgr, image_factory=self._image_factory) return args def load(self, shader_name, color_mgr, image_factory=None): self._color_mgr = color_mgr self._shader_name = shader_name self._image_factory = image_factory code = self._loader.load(shader_name, 'bsdf.py') if code is None: raise ValueError("bsdf.py in %s doesnt exist!" % shader_name) args = self._load_args() name = 'material_%i' % id(args) s = color_mgr.zero() func_args = self._func_args(s) self._bsdf_shader = Shader(code=code, args=args, name=name, func_args=func_args, is_func=True) #Sampling shader code = self._loader.load(self._shader_name, 'sample.py') if code is None: code = self._default_sampling() args = self._load_args() ptr_mat_bsdf = PointerArg('ptr_mat_bsdf', 0) ptr_mat_pdf = PointerArg('ptr_mat_pdf', 0) ptr_bsdf = ArgList('ptr_mat_bsdf', [ptr_mat_bsdf]) ptr_pdf = ArgList('ptr_mat_pdf', [ptr_mat_pdf]) args.append(ptr_bsdf) args.append(ptr_pdf) name = 'material_sampling_%i' % id(args) func_args = self._func_args(s) self._sampling_shader = Shader(code=code, args=args, name=name, func_args=func_args, is_func=True) #material pdf code = self._loader.load(self._shader_name, 'pdf.py') if code is None: code = self._default_pdf() args = self._load_args() name = 'material_pdf_%i' % id(args) func_args = self._func_args(s) self._pdf_shader = Shader(code=code, args=args, name=name, func_args=func_args, is_func=True) def _default_sampling(self): code = """ r1 = random() r2 = random() e = 1.0 phi = 2.0 * 3.14159 * r1 exponent = 1.0 / (e + 1.0) cos_theta = pow(r2, exponent) tmp = 1.0 - cos_theta * cos_theta sin_theta = sqrt(tmp) sin_phi = sin(phi) cos_phi = cos(phi) pu = sin_theta * cos_phi pv = sin_theta * sin_phi pw = cos_theta w = hitpoint.normal tv = (0.0034, 1.0, 0.0071) v = cross(tv, w) v = normalize(v) u = cross(v, w) ndir = u * pu + v * pv + w * pw shadepoint.wi = normalize(ndir) __material_pdf(hitpoint, shadepoint, ptr_mat_pdf) __material_reflectance(hitpoint, shadepoint, ptr_mat_bsdf) """ return code def _default_pdf(self): code = """ shadepoint.pdf = dot(hitpoint.normal, shadepoint.wi) * 0.318309886 """ return code def compile(self, shaders=[]): self._bsdf_shader.compile(shaders, color_mgr=self._color_mgr) self._sampling_shader.compile(shaders, color_mgr=self._color_mgr) self._pdf_shader.compile(shaders, color_mgr=self._color_mgr) def prepare(self, runtimes): self._bsdf_shader.prepare(runtimes) self._pdf_shader.prepare(runtimes) ptrs = self._bsdf_shader.get_ptrs() args = [PointerArg('ptr_mat_bsdf', p) for p in ptrs] ptr_bsdf = self._sampling_shader._get_arg('ptr_mat_bsdf') ptr_bsdf.resize(args) ptrs = self._pdf_shader.get_ptrs() args = [PointerArg('ptr_mat_pdf', p) for p in ptrs] ptr_pdf = self._sampling_shader._get_arg('ptr_mat_pdf') ptr_pdf.resize(args) self._sampling_shader.prepare(runtimes) def emission_shader(self, shaders=[]): args = self._load_args() code = self._loader.load(self._shader_name, 'emission.py') if code is None: raise ValueError("emission.py in %s dont exist!" % self._shader_name) name = 'material_emission_%i' % id(args) s = self._color_mgr.zero() func_args = self._func_args(s) emission_shader = Shader(code=code, args=args, name=name, func_args=func_args, is_func=True) return emission_shader def sync_shader_props(self, shader): for arg in shader.args: val = self.get_value(arg.name) shader.set_value(arg.name, val) def set_value(self, name, val): if self._bsdf_shader is None: raise ValueError("Material shader is not loaded!") if isinstance(val, (RGBSpectrum, SampledSpectrum)): val = self._color_mgr.convert_spectrum(val) self._bsdf_shader.set_value(name, val) self._sampling_shader.set_value(name, val) self._pdf_shader.set_value(name, val) def get_value(self, name): if self._bsdf_shader is None: raise ValueError("Material shader is not loaded!") return self._bsdf_shader.get_value(name) def output(self, name): txt = 'Material\n' txt += 'type = %s\n' % self._shader_name txt += 'name = %s\n' % name args = self._load_args() for arg in args: value = self.get_value(arg.name) txt += output_arg(arg.name, value) txt += 'End\n' return txt
class Camera: def __init__(self, eye, lookat, distance): self._eye = eye self._lookat = lookat self._up = Vector3(0.0, 1.0, 0.0) self._distance = float(distance) # distance of image plane form eye self._compute_uvw() path = os.path.dirname(__file__) path = os.path.join(path, 'cam_shaders') self._loader = Loader([path]) self._standalone = None self._shader_name = None def _compute_uvw(self): self._w = self._eye - self._lookat # w is in oposite direction of view self._w.normalize() self._u = self._up.cross(self._w) self._u.normalize() self._v = self._w.cross(self._u) #singularity if self._eye.x == self._lookat.x and self._eye.z == self._lookat.z\ and self._eye.y > self._lookat.y: # looking vertically down self._u = Vector3(0.0, 0.0, 1.0) self._v = Vector3(1.0, 0.0, 0.0) self._w = Vector3(0.0, 1.0, 0.0) if self._eye.x == self._lookat.x and self._eye.z == self._lookat.z\ and self._eye.y < self._lookat.y: # looking vertically up self._u = Vector3(1.0, 0.0, 0.0) self._v = Vector3(0.0, 0.0, 1.0) self._w = Vector3(0.0, -1.0, 0.0) def load(self, shader_name): args = [] text = self._loader.load(shader_name, 'props.txt') if text is not None: args = parse_args(text) w = Vec3Arg('w', self._w) u = Vec3Arg('u', self._u) v = Vec3Arg('v', self._v) distance = FloatArg('distance', self._distance) eye = Vec3Arg('eye', self._eye) lookat = Vec3Arg('lookat', self._lookat) args.extend([w, u, v, distance, eye, lookat]) code = self._loader.load(shader_name, 'code.py') if code is None: raise ValueError("code.py in %s shader dont exist!" % shader_name) func_args = [StructArgPtr('ray', Ray.factory()), StructArgPtr('sample', Sample.factory())] self._shader_name = shader_name self.shader = Shader(code=code, args=args, name='generate_ray', func_args=func_args, is_func=True) def compile(self, shaders=[]): self.shader.compile(shaders) def prepare(self, runtimes): self.shader.prepare(runtimes) def prepare_standalone(self): runtimes = [Runtime()] self.compile() self.prepare(runtimes) code = """ ray = Ray() generate_ray(ray, sample) origin = ray.origin direction = ray.direction """ origin = Vec3Arg('origin', Vector3(0.0, 0.0, 0.0)) direction = Vec3Arg('direction', Vector3(0.0, 0.0, 0.0)) sample = Sample(0.0, 0.0, 0.0, 0.0, 0, 0, 0.0) sample_arg = StructArg('sample', sample) args = [origin, direction, sample_arg] self._standalone = shader = Shader(code=code, args=args) shader.compile([self.shader]) shader.prepare(runtimes) def generate_ray(self, sample): self._standalone.set_value('sample', sample) self._standalone.execute() origin = self._standalone.get_value('origin') direction = self._standalone.get_value('direction') ray = Ray(origin, direction) return ray def output(self): type_name = 'Unknown' if self._shader_name is None else self._shader_name txt = 'Camera\n' txt += 'type = %s\n' % type_name txt += 'eye = %f, %f, %f\n' % (self._eye.x, self._eye.y, self._eye.z) txt += 'lookat = %f, %f, %f\n' % (self._lookat.x, self._lookat.y, self._lookat.z) txt += 'distance = %f\n' % self._distance txt += 'End\n' return txt
class MaterialManager: def __init__(self): self._materials = [] self._materials_d = {} self._materials_idx = {} def add(self, name, material): if name in self._materials_d: raise ValueError("Material %s allready exist!" % name) if not isinstance(material, Material): raise ValueError("Type error. Material is expected!", material) self._materials_idx[len(self._materials)] = name self._materials.append(material) self._materials_d[name] = material def _func_args(self, spectrum): func_args = [StructArgPtr('hitpoint', HitPoint.factory()), StructArgPtr('shadepoint', ShadePoint.factory(spectrum)), IntArg('mat_idx', 0)] return func_args def _mtl_reflectance(self, color_mgr): code = """ ptr_func = mtl_ptrs[mat_idx] __material_reflectance(hitpoint, shadepoint, ptr_func) """ ref_ptrs = ArrayArg('mtl_ptrs', PtrsArray()) al = ArgList('mtl_ptrs', [ref_ptrs]) func_args = self._func_args(color_mgr.zero()) args = [al] self.ref_shader = Shader(code=code, args=args, name='material_reflectance', func_args=func_args, is_func=True) def _mtl_sampling(self, color_mgr): code = """ ptr_func = mtl_sampling_ptrs[mat_idx] __material_sampling(hitpoint, shadepoint, ptr_func) """ sampling_ptrs = ArrayArg('mtl_sampling_ptrs', PtrsArray()) al = ArgList('mtl_sampling_ptrs', [sampling_ptrs]) func_args = self._func_args(color_mgr.zero()) args = [al] self.sampling_shader = Shader(code=code, args=args, name='material_sampling', func_args=func_args, is_func=True) def _mtl_pdf(self, color_mgr): code = """ ptr_func = mtl_pdf_ptrs[mat_idx] __material_pdf(hitpoint, shadepoint, ptr_func) """ pdf_ptrs = ArrayArg('mtl_pdf_ptrs', PtrsArray()) al = ArgList('mtl_pdf_ptrs', [pdf_ptrs]) func_args = self._func_args(color_mgr.zero()) args = [al] self.pdf_shader = Shader(code=code, args=args, name='material_pdf', func_args=func_args, is_func=True) def compile_shaders(self, color_mgr, shaders=[]): for m in self._materials: m.compile(shaders) self._mtl_reflectance(color_mgr) self.ref_shader.compile(shaders, color_mgr=color_mgr) self._mtl_sampling(color_mgr) self.sampling_shader.compile(shaders, color_mgr=color_mgr) self._mtl_pdf(color_mgr) self.pdf_shader.compile(shaders, color_mgr=color_mgr) def prepare_shaders(self, runtimes): for m in self._materials: m.prepare(runtimes) args = self._pointer_args('_bsdf_shader', 'mtl_ptrs', runtimes) aal = self.ref_shader._get_arg('mtl_ptrs') aal.resize(args) self.ref_shader.prepare(runtimes) args = self._pointer_args('_sampling_shader', 'mtl_sampling_ptrs', runtimes) aal = self.sampling_shader._get_arg('mtl_sampling_ptrs') aal.resize(args) self.sampling_shader.prepare(runtimes) args = self._pointer_args('_pdf_shader', 'mtl_pdf_ptrs', runtimes) aal = self.pdf_shader._get_arg('mtl_pdf_ptrs') aal.resize(args) self.pdf_shader.prepare(runtimes) def _pointer_args(self, shader_name, arg_name, runtimes): ptrs = [] for m in self._materials: shader = getattr(m, shader_name) p = shader.get_ptrs() ptrs.append(p) args = [] for i in range(len(runtimes)): pa = PtrsArray() for v in ptrs: pa.append(v[i]) args.append(ArrayArg(arg_name, pa)) return args def index(self, name): if name not in self._materials_d: raise ValueError("Material %s doesn't exist!" % name) m = self._materials_d[name] return self._materials.index(m) def material(self, index=None, name=None): if index is None and name is None: raise ValueError("Index or Name of material is required") if name is not None: return self._materials_d[name] return self._materials[index] def name(self, index): return self._materials_idx[index] def output(self): txt = '' for index, mat in enumerate(self._materials): txt += mat.output(self.name(index)) + '\n' return txt
class LightManager: def __init__(self): self._lights = [] self._lights_d = {} self._env_light = None self.env_shader = None def add(self, name, light): if name in self._lights_d: raise ValueError("Light %s allready exist!" % name) if not isinstance(light, Light): raise ValueError("Type error. Light is expected!", light) #TODO -- implement check not to add environment light more than once if isinstance(light, EnvironmentLight): self._env_light = light else: self._lights.append(light) self._lights_d[name] = light def remove(self, name=None, light=None): if name is None and light is None: raise ValueError("Name or Light argument is required") if name is not None and name not in self._lights_d: raise ValueError("Light %s doesn't exist!" % name) if name is not None: light = self._lights_d[name] del self._lights_d[name] self._lights.remove(light) elif light is not None: for name in self._lights_d.keys(): if light is self._lights_d[name]: del self._lights_d[name] self._lights.remove(light) def light_idx(self, name): if name not in self._lights_d: raise ValueError("Light %s doesn't exist!" % name) light = self._lights_d[name] return self._lights.index(light) def _func_args(self, spectrum): func_args = [ StructArgPtr('hitpoint', HitPoint.factory()), StructArgPtr('shadepoint', ShadePoint.factory(spectrum)), IntArg('mat_idx', 0) ] return func_args def _lgt_radiance(self, color_mgr): code = """ ptr_func = lgt_ptrs[mat_idx] __light_radiance(hitpoint, shadepoint, ptr_func) """ lgt_ptrs = ArrayArg('lgt_ptrs', PtrsArray()) al = ArgList('lgt_ptrs', [lgt_ptrs]) func_args = self._func_args(color_mgr.zero()) args = [al] self.rad_shader = Shader(code=code, args=args, name='light_radiance', func_args=func_args, is_func=True) def _lgt_emission(self, color_mgr): code = """ if light_id < 0: shadepoint.light_intensity = Spectrum(0.0) shadepoint.light_pdf = 1.0 else: ptr_func = lgt_ptrs[light_id] __light_emission(hitpoint, shadepoint, ptr_func) """ lgt_ptrs = ArrayArg('lgt_ptrs', PtrsArray()) al = ArgList('lgt_ptrs', [lgt_ptrs]) spec = color_mgr.zero() func_args = [ StructArgPtr('hitpoint', HitPoint.factory()), StructArgPtr('shadepoint', ShadePoint.factory(spec)), IntArg('light_id', -1) ] args = [al] self.emission_shader = Shader(code=code, args=args, name='light_emission', func_args=func_args, is_func=True) def compile_shaders(self, color_mgr, shaders=[]): for l in self._lights: l.compile(shaders) self._lgt_radiance(color_mgr) self.rad_shader.compile(shaders, color_mgr=color_mgr) self._lgt_emission(color_mgr) self.emission_shader.compile(shaders, color_mgr=color_mgr) code = "return %i\n" % len(self._lights) self.nlights_shader = Shader(code=code, name='number_of_lights', is_func=True) self.nlights_shader.compile() self._compile_environment(color_mgr, shaders) def _compile_environment(self, color_mgr, shaders=[]): if self._env_light is not None: self.env_shader = self._env_light.env_shader self.env_shader.compile(shaders, color_mgr=color_mgr) return # We create dummy shader for environment emission code = ''' shadepoint.light_intensity = Spectrum(0.0) shadepoint.light_pdf = 1.0 ''' spec = color_mgr.zero() func_args = [ StructArgPtr('hitpoint', HitPoint.factory()), StructArgPtr('shadepoint', ShadePoint.factory(spec)) ] self.env_shader = Shader(code=code, name='environment_emission', func_args=func_args, is_func=True) self.env_shader.compile(shaders, color_mgr=color_mgr) def prepare_shaders(self, runtimes): for l in self._lights: l.prepare(runtimes) ptrs = [] for l in self._lights: p = l.shader.get_ptrs() ptrs.append(p) args = [] for i in range(len(runtimes)): pa = PtrsArray() for v in ptrs: pa.append(v[i]) args.append(ArrayArg('lgt_ptrs', pa)) aal = self.rad_shader._get_arg('lgt_ptrs') aal.resize(args) self.rad_shader.prepare(runtimes) self.nlights_shader.prepare(runtimes) self.env_shader.prepare(runtimes) ##### emission shader ptrs = [] for l in self._lights: if isinstance(l, AreaLight): p = l.emission_shader.get_ptrs() ptrs.append(p) args = [] for i in range(len(runtimes)): pa = PtrsArray() for v in ptrs: pa.append(v[i]) args.append(ArrayArg('lgt_ptrs', pa)) aal = self.emission_shader._get_arg('lgt_ptrs') aal.resize(args) self.emission_shader.prepare(runtimes) self.update_light_ids() def update_light_ids(self): idx = 0 for l in self._lights: if isinstance(l, AreaLight): l.shape.light_id = idx idx += 1 def shapes_to_update(self): shapes = [] for l in self._lights: if isinstance(l, AreaLight): shapes.append(l.shape) return shapes def arealight(self, shape): for light in self._lights: if isinstance(light, AreaLight) and light.shape is shape: return light return None def output(self): txt = '' for name, light in self._lights_d.items(): if isinstance(light, AreaLight): continue txt += light.output(name) + '\n' return txt
class Material: def __init__(self): path = os.path.dirname(__file__) path = os.path.join(path, 'mat_shaders') self._loader = Loader([path]) self._bsdf_shader = None self._sampling_shader = None self._shader_name = None def is_emissive(self): if self._shader_name is None: return False return self._loader.exist(self._shader_name, 'emission.py') def _func_args(self, spectrum): func_args = [StructArgPtr('hitpoint', HitPoint.factory()), StructArgPtr('shadepoint', ShadePoint.factory(spectrum))] return func_args def _load_args(self): args = [] text = self._loader.load(self._shader_name, 'props.txt') if text is not None: args = parse_args(text, self._color_mgr, image_factory=self._image_factory) return args def load(self, shader_name, color_mgr, image_factory=None): self._color_mgr = color_mgr self._shader_name = shader_name self._image_factory = image_factory code = self._loader.load(shader_name, 'bsdf.py') if code is None: raise ValueError("bsdf.py in %s doesnt exist!" % shader_name) args = self._load_args() name = 'material_%i' % id(args) s = color_mgr.zero() func_args = self._func_args(s) self._bsdf_shader = Shader(code=code, args=args, name=name, func_args=func_args, is_func=True) #Sampling shader code = self._loader.load(self._shader_name, 'sample.py') if code is None: code = self._default_sampling() args = self._load_args() ptr_mat_bsdf = PointerArg('ptr_mat_bsdf', 0) ptr_mat_pdf = PointerArg('ptr_mat_pdf', 0) ptr_bsdf = ArgList('ptr_mat_bsdf', [ptr_mat_bsdf]) ptr_pdf = ArgList('ptr_mat_pdf', [ptr_mat_pdf]) args.append(ptr_bsdf) args.append(ptr_pdf) name = 'material_sampling_%i' % id(args) func_args = self._func_args(s) self._sampling_shader = Shader(code=code, args=args, name=name, func_args=func_args, is_func=True) #material pdf code = self._loader.load(self._shader_name, 'pdf.py') if code is None: code = self._default_pdf() args = self._load_args() name = 'material_pdf_%i' % id(args) func_args = self._func_args(s) self._pdf_shader = Shader(code=code, args=args, name=name, func_args=func_args, is_func=True) def _default_sampling(self): code = """ r1 = random() r2 = random() e = 1.0 phi = 2.0 * 3.14159 * r1 exponent = 1.0 / (e + 1.0) cos_theta = pow(r2, exponent) tmp = 1.0 - cos_theta * cos_theta sin_theta = sqrt(tmp) sin_phi = sin(phi) cos_phi = cos(phi) pu = sin_theta * cos_phi pv = sin_theta * sin_phi pw = cos_theta w = hitpoint.normal tv = (0.0034, 1.0, 0.0071) v = cross(tv, w) v = normalize(v) u = cross(v, w) ndir = u * pu + v * pv + w * pw shadepoint.wi = normalize(ndir) __material_pdf(hitpoint, shadepoint, ptr_mat_pdf) __material_reflectance(hitpoint, shadepoint, ptr_mat_bsdf) """ return code def _default_pdf(self): code = """ shadepoint.pdf = dot(hitpoint.normal, shadepoint.wi) * 0.318309886 """ return code def compile(self, shaders=[]): self._bsdf_shader.compile(shaders, color_mgr=self._color_mgr) self._sampling_shader.compile(shaders, color_mgr=self._color_mgr) self._pdf_shader.compile(shaders, color_mgr=self._color_mgr) def prepare(self, runtimes): self._bsdf_shader.prepare(runtimes) self._pdf_shader.prepare(runtimes) ptrs = self._bsdf_shader.get_ptrs() args = [PointerArg('ptr_mat_bsdf', p) for p in ptrs] ptr_bsdf = self._sampling_shader._get_arg('ptr_mat_bsdf') ptr_bsdf.resize(args) ptrs = self._pdf_shader.get_ptrs() args = [PointerArg('ptr_mat_pdf', p) for p in ptrs] ptr_pdf = self._sampling_shader._get_arg('ptr_mat_pdf') ptr_pdf.resize(args) self._sampling_shader.prepare(runtimes) def emission_shader(self, shaders=[]): args = self._load_args() code = self._loader.load(self._shader_name, 'emission.py') if code is None: raise ValueError("emission.py in %s dont exist!" % self._shader_name) name = 'material_emission_%i' % id(args) s = self._color_mgr.zero() func_args = self._func_args(s) emission_shader = Shader(code=code, args=args, name=name, func_args=func_args, is_func=True) return emission_shader def sync_shader_props(self, shader): for arg in shader.args: val = self.get_value(arg.name) shader.set_value(arg.name, val) def set_value(self, name, val): if self._bsdf_shader is None: raise ValueError("Material shader is not loaded!") if isinstance(val, (RGBSpectrum, SampledSpectrum)): val = self._color_mgr.convert_spectrum(val) self._bsdf_shader.set_value(name, val) self._sampling_shader.set_value(name, val) self._pdf_shader.set_value(name, val) def get_value(self, name): if self._bsdf_shader is None: raise ValueError("Material shader is not loaded!") return self._bsdf_shader.get_value(name) def output(self, name): txt = 'Material\n' txt += 'type = %s\n' % self._shader_name txt += 'name = %s\n' % name args = self._load_args() for arg in args: value = self.get_value(arg.name) txt += output_arg(arg.name, value) txt += 'End\n' return txt
class GeneralLight(Light): def __init__(self): path = os.path.dirname(__file__) path = os.path.join(path, 'light_shaders') self._loader = Loader([path]) self.shader = None def _func_args(self, spectrum): func_args = [ StructArgPtr('hitpoint', HitPoint.factory()), StructArgPtr('shadepoint', ShadePoint.factory(spectrum)) ] return func_args def load(self, shader_name, color_mgr): args = [] text = self._loader.load(shader_name, 'props.txt') if text is not None: args = parse_args(text, color_mgr) code = self._loader.load(shader_name, 'code.py') if code is None: raise ValueError("code.py in %s shader dont exist!" % shader_name) name = 'light_%i' % id(args) func_args = self._func_args(color_mgr.zero()) self.shader = Shader(code=code, args=args, name=name, func_args=func_args, is_func=True) self._color_mgr = color_mgr self._shader_name = shader_name def compile(self, shaders=[]): self.shader.compile(shaders, color_mgr=self._color_mgr) def prepare(self, runtimes): self.shader.prepare(runtimes) def get_value(self, name): if self.shader is None: raise ValueError("Light shader is not loaded!") return self.shader.get_value(name) def set_value(self, name, val): if self.shader is None: raise ValueError("Light shader is not loaded!") if isinstance(val, (RGBSpectrum, SampledSpectrum)): val = self._color_mgr.convert_spectrum(val, illum=True) self.shader.set_value(name, val) def output(self, name): txt = 'Light\n' txt += 'type = %s\n' % self._shader_name txt += 'name = %s\n' % name args = [] text = self._loader.load(self._shader_name, 'props.txt') if text is not None: args = parse_args(text) for arg in args: value = self.get_value(arg.name) txt += output_arg(arg.name, value) txt += 'End\n' return txt
class AreaLight(Light): def __init__(self, shape, material): path = os.path.dirname(__file__) path = os.path.join(path, 'area_light_shaders') self._loader = Loader([path]) self.shape = shape self.material = material self.shader = None def _func_args(self, spectrum): func_args = [ StructArgPtr('hitpoint', HitPoint.factory()), StructArgPtr('shadepoint', ShadePoint.factory(spectrum)) ] return func_args def _load_args(self): args = [] text = self._loader.load(self._shader_name, 'props.txt') if text is not None: args = parse_args(text, self._color_mgr) return args def load(self, shader_name, color_mgr): self._color_mgr = color_mgr self._shader_name = shader_name args = self._load_args() ptr_lgt_sample = PointerArg('ptr_light_sample', 0) lgt_sample = ArgList('ptr_light_sample', [ptr_lgt_sample]) args.append(lgt_sample) ptr_mat_emission = PointerArg('ptr_mat_emission', 0) mat_emission = ArgList('ptr_mat_emission', [ptr_mat_emission]) args.append(mat_emission) code = self._loader.load(shader_name, 'code.py') if code is None: raise ValueError("code.py in %s shader dont exist!" % shader_name) name = 'light_%i' % id(args) func_args = self._func_args(color_mgr.zero()) self.shader = Shader(code=code, args=args, name=name, func_args=func_args, is_func=True) # area light emission shader name = 'light_emission%i' % id(args) func_args = self._func_args(color_mgr.zero()) args = [] ptr_lgt_pdf = PointerArg('ptr_light_pdf', 0) lgt_pdf = ArgList('ptr_light_pdf', [ptr_lgt_pdf]) args.append(lgt_pdf) ptr_mat_emission = PointerArg('ptr_mat_emission', 0) mat_emission = ArgList('ptr_mat_emission', [ptr_mat_emission]) args.append(mat_emission) code = """ __light_pdf(hitpoint, shadepoint, ptr_light_pdf) __material_emission(hitpoint, shadepoint, ptr_mat_emission) """ self.emission_shader = Shader(code=code, args=args, name=name, func_args=func_args, is_func=True) def compile(self, shaders=[]): self.shader.compile(shaders, color_mgr=self._color_mgr) self.emission_shader.compile(shaders, color_mgr=self._color_mgr) spec = self._color_mgr.zero() self.light_sample_shader = self.shape.light_sample(spec) self.light_sample_shader.compile(shaders, color_mgr=self._color_mgr) self.light_pdf_shader = self.shape.light_pdf(spec) self.light_pdf_shader.compile(shaders, color_mgr=self._color_mgr) self._emission_shader = self.material.emission_shader() self._emission_shader.compile(shaders, color_mgr=self._color_mgr) def prepare(self, runtimes): self.light_sample_shader.prepare(runtimes) ptrs = self.light_sample_shader.get_ptrs() args = [PointerArg('ptr_light_sample', p) for p in ptrs] lgt_sample = self.shader._get_arg('ptr_light_sample') lgt_sample.resize(args) self.light_pdf_shader.prepare(runtimes) ptrs = self.light_pdf_shader.get_ptrs() args = [PointerArg('ptr_light_pdf', p) for p in ptrs] lgt_pdf = self.emission_shader._get_arg('ptr_light_pdf') lgt_pdf.resize(args) self._emission_shader.prepare(runtimes) self.material.sync_shader_props(self._emission_shader) ptrs = self._emission_shader.get_ptrs() args = [PointerArg('ptr_mat_emission', p) for p in ptrs] ptr_emission = self.shader._get_arg('ptr_mat_emission') ptr_emission.resize(args) args = [PointerArg('ptr_mat_emission', p) for p in ptrs] ptr_emission = self.emission_shader._get_arg('ptr_mat_emission') ptr_emission.resize(args) self.shader.prepare(runtimes) self.emission_shader.prepare(runtimes) def get_value(self, name): if self.shader is None: raise ValueError("Light shader is not loaded!") return self.shader.get_value(name) def set_value(self, name, val): if self.shader is None: raise ValueError("Light shader is not loaded!") if isinstance(val, (RGBSpectrum, SampledSpectrum)): val = self._color_mgr.convert_spectrum(val, illum=True) self.shader.set_value(name, val)
class Sampler: def __init__(self, width, height, pixelsize=1.0, nthreads=1): self._width = width self._height = height self._pixelsize = pixelsize self._nthreads = nthreads self._pass = 0 self.shader = None @property def nthreads(self): return self._nthreads def get_resolution(self): return (self._width, self._height) def args(self): self._tiles = tiles = create_tiles(self._width, self._height, self._nthreads) n = self.nsamples() subx, suby = self._subpixel_location() args = [IntArg('width', self._width), IntArg('height', self._height), FloatArg('pixelsize', self._pixelsize), IntArg('nsamples', n), IntArg('npass', self._pass), IntArg('subx', subx), IntArg('suby', suby)] targs = [StructArg('tile', tile) for tile in tiles] targ = ArgList('tile', targs) args.append(targ) curx_args = [IntArg('curx', 0) for tile in tiles] curx_arg = ArgList('curx', curx_args) args.append(curx_arg) cury_args = [IntArg('cury', tile.y) for tile in tiles] cury_arg = ArgList('cury', cury_args) args.append(cury_arg) endx_args = [IntArg('endx', tile.width) for tile in tiles] endx_arg = ArgList('endx', endx_args) args.append(endx_arg) endy_args = [IntArg('endy', tile.y + tile.height) for tile in tiles] endy_arg = ArgList('endy', endy_args) args.append(endy_arg) return args def create_shader(self): raise NotImplementedError() def compile(self, shaders=[]): if self.shader is not None: self.shader.compile(shaders) def prepare(self, runtimes): if self._nthreads != len(runtimes): raise ValueError("Expected %i runtimes and got %i!" % (self._nthreads, len(runtimes))) if self.shader is not None: self.shader.prepare(runtimes) def reset(self): self._pass = 0 self._update_shader_values() def _subpixel_location(self): n = self.nsamples() subx = self._pass // int(math.sqrt(n)) suby = self._pass % int(math.sqrt(n)) return (subx, suby) def _update_shader_values(self): if self.shader is not None: self.shader.set_value('npass', self._pass) subx, suby = self._subpixel_location() self.shader.set_value('subx', subx) self.shader.set_value('suby', suby) curx = [0 for tile in self._tiles] self.shader.set_value('curx', curx) cury = [tile.y for tile in self._tiles] self.shader.set_value('cury', cury) def increment_pass(self): self._pass += 1 self._update_shader_values() def has_more_samples(self): if self._pass >= self.nsamples(): return False return True def nsamples(self): return 1 def prepare_standalone(self): runtimes = [Runtime()] self.compile() self.prepare(runtimes) code = """ ret = generate_sample(sample) """ args = [StructArg('sample', Sample.factory()), IntArg('ret', 11)] self._standalone = Shader(code=code, args=args) self._standalone.compile([self.shader]) self._standalone.prepare(runtimes) def generate_sample(self): self._standalone.execute() ret = self._standalone.get_value('ret') if ret == 0: return False sample = self._standalone.get_value('sample') return sample def output(self): txt = 'Sampler\n' txt += 'type = %s\n' % self.type_name() txt += 'width = %i\n' % self._width txt += 'height = %i\n' % self._height txt += 'nsamples = %i\n' % self.nsamples() txt += 'nthreads = %i\n' % self._nthreads txt += 'pixelsize = %f\n' % self._pixelsize txt += 'End\n' return txt def type_name(self): raise NotImplementedError()
class MaterialManager: def __init__(self): self._materials = [] self._materials_d = {} self._materials_idx = {} def add(self, name, material): if name in self._materials_d: raise ValueError("Material %s allready exist!" % name) if not isinstance(material, Material): raise ValueError("Type error. Material is expected!", material) self._materials_idx[len(self._materials)] = name self._materials.append(material) self._materials_d[name] = material def _func_args(self, spectrum): func_args = [ StructArgPtr('hitpoint', HitPoint.factory()), StructArgPtr('shadepoint', ShadePoint.factory(spectrum)), IntArg('mat_idx', 0) ] return func_args def _mtl_reflectance(self, color_mgr): code = """ ptr_func = mtl_ptrs[mat_idx] __material_reflectance(hitpoint, shadepoint, ptr_func) """ ref_ptrs = ArrayArg('mtl_ptrs', PtrsArray()) al = ArgList('mtl_ptrs', [ref_ptrs]) func_args = self._func_args(color_mgr.zero()) args = [al] self.ref_shader = Shader(code=code, args=args, name='material_reflectance', func_args=func_args, is_func=True) def _mtl_sampling(self, color_mgr): code = """ ptr_func = mtl_sampling_ptrs[mat_idx] __material_sampling(hitpoint, shadepoint, ptr_func) """ sampling_ptrs = ArrayArg('mtl_sampling_ptrs', PtrsArray()) al = ArgList('mtl_sampling_ptrs', [sampling_ptrs]) func_args = self._func_args(color_mgr.zero()) args = [al] self.sampling_shader = Shader(code=code, args=args, name='material_sampling', func_args=func_args, is_func=True) def _mtl_pdf(self, color_mgr): code = """ ptr_func = mtl_pdf_ptrs[mat_idx] __material_pdf(hitpoint, shadepoint, ptr_func) """ pdf_ptrs = ArrayArg('mtl_pdf_ptrs', PtrsArray()) al = ArgList('mtl_pdf_ptrs', [pdf_ptrs]) func_args = self._func_args(color_mgr.zero()) args = [al] self.pdf_shader = Shader(code=code, args=args, name='material_pdf', func_args=func_args, is_func=True) def compile_shaders(self, color_mgr, shaders=[]): for m in self._materials: m.compile(shaders) self._mtl_reflectance(color_mgr) self.ref_shader.compile(shaders, color_mgr=color_mgr) self._mtl_sampling(color_mgr) self.sampling_shader.compile(shaders, color_mgr=color_mgr) self._mtl_pdf(color_mgr) self.pdf_shader.compile(shaders, color_mgr=color_mgr) def prepare_shaders(self, runtimes): for m in self._materials: m.prepare(runtimes) args = self._pointer_args('_bsdf_shader', 'mtl_ptrs', runtimes) aal = self.ref_shader._get_arg('mtl_ptrs') aal.resize(args) self.ref_shader.prepare(runtimes) args = self._pointer_args('_sampling_shader', 'mtl_sampling_ptrs', runtimes) aal = self.sampling_shader._get_arg('mtl_sampling_ptrs') aal.resize(args) self.sampling_shader.prepare(runtimes) args = self._pointer_args('_pdf_shader', 'mtl_pdf_ptrs', runtimes) aal = self.pdf_shader._get_arg('mtl_pdf_ptrs') aal.resize(args) self.pdf_shader.prepare(runtimes) def _pointer_args(self, shader_name, arg_name, runtimes): ptrs = [] for m in self._materials: shader = getattr(m, shader_name) p = shader.get_ptrs() ptrs.append(p) args = [] for i in range(len(runtimes)): pa = PtrsArray() for v in ptrs: pa.append(v[i]) args.append(ArrayArg(arg_name, pa)) return args def index(self, name): if name not in self._materials_d: raise ValueError("Material %s doesn't exist!" % name) m = self._materials_d[name] return self._materials.index(m) def material(self, index=None, name=None): if index is None and name is None: raise ValueError("Index or Name of material is required") if name is not None: return self._materials_d[name] return self._materials[index] def name(self, index): return self._materials_idx[index] def output(self): txt = '' for index, mat in enumerate(self._materials): txt += mat.output(self.name(index)) + '\n' return txt
def atest_material_glass(self): sam_mgr = SampledManager() register_rgb_shadepoint() runtimes = [Runtime()] mat = Material() mat.load('glass', sam_mgr, spectral=False) mat.set_value('ior', 1.5) mgr = MaterialManager() mgr.add('material1', mat) shaders = shaders_functions() for shader in shaders: shader.compile() shader.prepare(runtimes) mgr.compile_shaders(sam_mgr, spectral=False, shaders=shaders) mgr.prepare_shaders(runtimes) code = """ hp = HitPoint() hp.normal = normal sp = ShadePoint() sp.wo = wo material_sampling(hp, sp, 0) pdf = sp.pdf wi = sp.wi spec = sp.material_reflectance """ pdf = FloatArg('pdf', 0.0) wi = Vec3Arg('wi', Vector3(0.0, 0.0, 0.0)) ww = Vector3(5.0, 1.0, 0.0) ww.normalize() wo = Vec3Arg('wo', ww) nn = Vector3(0.0, 1.0, 0.0) nn.normalize() normal = Vec3Arg('normal', nn) spec = RGBArg('spec', RGBSpectrum(0.5, 0.5, 0.5)) shader = Shader(code=code, args=[pdf, wi, wo, normal, spec]) shader.compile(shaders=[mgr.sampling_shader]) shader.prepare(runtimes) shader.execute() s = shader.get_value('wi') print(s) s = shader.get_value('pdf') print(s) s = shader.get_value('spec') print(s) print('------------------------------') print('wo', ww) wi, pdf, ref = sampling_glass(1.5, ww, nn) print("wi", wi) print("pdf", pdf) print("ref", ref) ndotwi = abs(nn.dot(wi)) print("ndotwi", ndotwi) tmp = ndotwi / pdf path_weight = ref * tmp print("path weight", path_weight)