Example #1
0
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
Example #2
0
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)
Example #3
0
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
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #7
0
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)
Example #8
0
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