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 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