def wrangle_sampler(obj, wrangler, now): node = wrangle_node_parm(obj, "sampler_node", now) if node is not None: return node.type_and_paramset parm_selection = { "sampler": SohoPBRT("sampler", "string", ["halton"], False), "pixelsamples": SohoPBRT("pixelsamples", "integer", [16], False), "jitter": SohoPBRT("jitter", "bool", [1], False), "samples": SohoPBRT("samples", "integer", [4, 4], False), "dimensions": SohoPBRT("dimensions", "integer", [4], False), } parms = obj.evaluate(parm_selection, now) sampler_name = parms["sampler"].Value[0] paramset = ParamSet() if sampler_name == "stratified": xsamples = parms["samples"].Value[0] ysamples = parms["samples"].Value[1] paramset.add(PBRTParam("integer", "xsamples", xsamples)) paramset.add(PBRTParam("integer", "ysamples", ysamples)) paramset.add(parms["jitter"].to_pbrt()) paramset.add(parms["dimensions"].to_pbrt()) else: paramset.add(parms["pixelsamples"].to_pbrt()) return (sampler_name, paramset)
def wrangle_sampler(obj, wrangler, now): node = wrangle_node_parm(obj, "sampler_node", now) if node is not None: return node.type_and_paramset parm_selection = { "sampler": SohoPBRT("sampler", "string", ["pmj02bn"], False), "pixelsamples": SohoPBRT("pixelsamples", "integer", [16], False), "randomization": SohoPBRT("randomization", "string", ["fastowen"], True), "jitter": SohoPBRT("jitter", "bool", [1], True), "samples": SohoPBRT("samples", "integer", [4, 4], False), } parms = obj.evaluate(parm_selection, now) sampler_name = parms["sampler"].Value[0] paramset = ParamSet() if sampler_name == "stratified": xsamples = parms["samples"].Value[0] ysamples = parms["samples"].Value[1] paramset.add(PBRTParam("integer", "xsamples", xsamples)) paramset.add(PBRTParam("integer", "ysamples", ysamples)) if "jitter" in parms: paramset.add(parms["jitter"].to_pbrt()) else: if (sampler_name in ("sobol", "paddedsobol", "zsobol", "halton") and "randomization" in parms): # NOTE: If the halton sampler is picked, it is not compatible with the # randomization "fastowen". paramset.add(parms["randomization"].to_pbrt()) paramset.add(parms["pixelsamples"].to_pbrt()) return (sampler_name, paramset)
def wrangle_film(obj, wrangler, now): node = wrangle_node_parm(obj, 'film_node', now) if node is not None: return node.type_and_paramset paramset = ParamSet() parm_selection = { 'filename' : SohoPBRT('filename', 'string', ['pbrt.exr'], False), 'maxsampleluminance' : SohoPBRT('maxsampleluminance', 'float', [1e38], True), 'diagonal' : SohoPBRT('diagonal', 'float', [35], True), } parms = obj.evaluate(parm_selection, now) for parm_name, parm in parms.iteritems(): paramset.add(parm.to_pbrt()) parm_selection = { 'res' : SohoPBRT('res', 'integer', [1280, 720], False), } parms = obj.evaluate(parm_selection, now) paramset.add(PBRTParam('integer', 'xresolution', parms['res'].Value[0])) paramset.add(PBRTParam('integer', 'yresolution', parms['res'].Value[1])) crop_region = obj.getCameraCropWindow(wrangler, now) if crop_region != [0.0, 1.0, 0.0, 1.0]: paramset.add(PBRTParam('float', 'cropwindow', crop_region)) return ('image', paramset)
def wrangle_sampler(obj, wrangler, now): node = wrangle_node_parm(obj, 'sampler_node', now) if node is not None: return node.type_and_paramset parm_selection = { 'sampler' : SohoPBRT('sampler', 'string', ['halton'], False), 'pixelsamples' : SohoPBRT('pixelsamples', 'integer', [16], False), 'jitter' : SohoPBRT('jitter', 'bool', [1], False), 'samples' : SohoPBRT('samples', 'integer', [4, 4], False), 'dimensions' : SohoPBRT('dimensions', 'integer', [4], False), } parms = obj.evaluate(parm_selection, now) sampler_name = parms['sampler'].Value[0] paramset = ParamSet() if sampler_name == 'stratified': xsamples = parms['samples'].Value[0] ysamples = parms['samples'].Value[1] paramset.add(PBRTParam('integer', 'xsamples', xsamples)) paramset.add(PBRTParam('integer', 'ysamples', ysamples)) paramset.add(parms['jitter'].to_pbrt()) paramset.add(parms['dimensions'].to_pbrt()) else: paramset.add(parms['pixelsamples'].to_pbrt()) return (sampler_name, paramset)
def wrangle_film(obj, wrangler, now): node = wrangle_node_parm(obj, "film_node", now) if node is not None: return node.type_and_paramset paramset = ParamSet() parm_selection = { "filename": SohoPBRT("filename", "string", ["pbrt.exr"], False), "maxsampleluminance": SohoPBRT("maxsampleluminance", "float", [1e38], True), "diagonal": SohoPBRT("diagonal", "float", [35], True), } parms = obj.evaluate(parm_selection, now) for parm_name, parm in parms.iteritems(): paramset.add(parm.to_pbrt()) parm_selection = {"res": SohoPBRT("res", "integer", [1280, 720], False)} parms = obj.evaluate(parm_selection, now) paramset.add(PBRTParam("integer", "xresolution", parms["res"].Value[0])) paramset.add(PBRTParam("integer", "yresolution", parms["res"].Value[1])) crop_region = obj.getCameraCropWindow(wrangler, now) if crop_region != [0.0, 1.0, 0.0, 1.0]: paramset.add(PBRTParam("float", "cropwindow", crop_region)) return ("image", paramset)
def wrangle_accelerator(obj, wrangler, now): node = wrangle_node_parm(obj, "accelerator_node", now) if node is not None: return node.type_and_paramset parm_selection = {"accelerator": SohoPBRT("accelerator", "string", ["bvh"], False)} parms = obj.evaluate(parm_selection, now) accelerator_name = parms["accelerator"].Value[0] if accelerator_name == "bvh": parm_selection = { "maxnodeprims": SohoPBRT("maxnodeprims", "integer", [4], True), "splitmethod": SohoPBRT("splitmethod", "string", ["sah"], True), } else: parm_selection = { "intersectcost": SohoPBRT("intersectcost", "integer", [80], True), "traversalcostcost": SohoPBRT("traversalcost", "integer", [1], True), "emptybonus": SohoPBRT("emptybonus", "float", [0.2], True), "maxprims": SohoPBRT("maxprims", "integer", [1], True), "kdtree_maxdepth": SohoPBRT( "kdtree_maxdepth", "integer", [1], True, key="maxdepth" ), } parms = obj.evaluate(parm_selection, now) paramset = ParamSet() for parm in parms: paramset.add(parms[parm].to_pbrt()) return (accelerator_name, paramset)
def wrangle_film(obj, wrangler, now): node = wrangle_node_parm(obj, "film_node", now) if node is not None: return node.type_and_paramset paramset = ParamSet() parm_selection = { "filename": SohoPBRT("filename", "string", ["pbrt.exr"], False), "maxcomponentvalue": SohoPBRT("maxcomponentvalue", "float", [1e38], True), "diagonal": SohoPBRT("diagonal", "float", [35], True), "savefp16": SohoPBRT("savefp16", "bool", [1], True), } parms = obj.evaluate(parm_selection, now) for parm in parms.values(): paramset.add(parm.to_pbrt()) parm_selection = { "film": SohoPBRT("film", "string", ["rgb"], False), "res": SohoPBRT("res", "integer", [1280, 720], False), } parms = obj.evaluate(parm_selection, now) film_name = parms["film"].Value[0] paramset.add(PBRTParam("integer", "xresolution", parms["res"].Value[0])) paramset.add(PBRTParam("integer", "yresolution", parms["res"].Value[1])) crop_region = obj.getCameraCropWindow(wrangler, now) if crop_region != [0.0, 1.0, 0.0, 1.0]: paramset.add(PBRTParam("float", "cropwindow", crop_region)) parm_selection = { "iso": SohoPBRT("iso", "float", [100], True), "whitebalance": SohoPBRT("whitebalance", "float", [0], True), "sensor": SohoPBRT("sensor", "string", ["cie1931"], True), } if film_name == "spectral": parm_selection["buckets"] = SohoPBRT("buckets", "integer", [16], True) parms = obj.evaluate(parm_selection, now) for parm in parms.values(): paramset.add(parm.to_pbrt()) return (film_name, paramset)
def wrangle_node_parm(obj, parm_name, now): parm_selection = {parm_name: SohoPBRT(parm_name, "string", [""], False)} parms = obj.evaluate(parm_selection, now) if not parms: return None node_path = parms[parm_name].Value[0] if not node_path: return None return BaseNode(node_path)
def wrangle_filter(obj, wrangler, now): node = wrangle_node_parm(obj, 'filter_node', now) if node is not None: return node.type_and_paramset parm_selection = { 'filter' : SohoPBRT('filter', 'string', ['gaussian'], False), 'filter_width' : SohoPBRT('filter_width', 'float', [2.0, 2.0], False), 'alpha' : SohoPBRT('gauss_alpha', 'float', [2.0], True, key='alpha'), 'B' : SohoPBRT('mitchell_B', 'float', [0.333333], True, key='B'), 'C' : SohoPBRT('mitchell_C', 'float', [0.333333], True, key='C'), 'tau' : SohoPBRT('sinc_tau', 'float', [3], True, key='tau'), } parms = obj.evaluate(parm_selection, now) filter_name = parms['filter'].Value[0] paramset = ParamSet() xwidth = parms['filter_width'].Value[0] ywidth = parms['filter_width'].Value[1] paramset.add(PBRTParam('float', 'xwidth', xwidth)) paramset.add(PBRTParam('float', 'ywidth', ywidth)) if filter_name == 'gaussian' and 'alpha' in parms: paramset.add(parms['alpha'].to_pbrt()) if filter_name == 'mitchell' and 'mitchell_B' in parms: paramset.add(parms['B'].to_pbrt()) if filter_name == 'mitchell' and 'mitchell_C' in parms: paramset.add(parms['C'].to_pbrt()) if filter_name == 'sinc' and 'tau' in parms: paramset.add(parms['tau'].to_pbrt()) return (filter_name, paramset)
def wrangle_filter(obj, wrangler, now): node = wrangle_node_parm(obj, "filter_node", now) if node is not None: return node.type_and_paramset parm_selection = { "filter": SohoPBRT("filter", "string", ["gaussian"], False), "filter_width": SohoPBRT("filter_width", "float", [2.0, 2.0], False), "alpha": SohoPBRT("gauss_alpha", "float", [2.0], True, key="alpha"), "B": SohoPBRT("mitchell_B", "float", [0.333333], True, key="B"), "C": SohoPBRT("mitchell_C", "float", [0.333333], True, key="C"), "tau": SohoPBRT("sinc_tau", "float", [3], True, key="tau"), } parms = obj.evaluate(parm_selection, now) filter_name = parms["filter"].Value[0] paramset = ParamSet() xwidth = parms["filter_width"].Value[0] ywidth = parms["filter_width"].Value[1] paramset.add(PBRTParam("float", "xwidth", xwidth)) paramset.add(PBRTParam("float", "ywidth", ywidth)) if filter_name == "gaussian" and "alpha" in parms: paramset.add(parms["alpha"].to_pbrt()) if filter_name == "mitchell" and "B" in parms: paramset.add(parms["B"].to_pbrt()) if filter_name == "mitchell" and "C" in parms: paramset.add(parms["C"].to_pbrt()) if filter_name == "sinc" and "tau" in parms: paramset.add(parms["tau"].to_pbrt()) return (filter_name, paramset)
def wrangle_accelerator(obj, wrangler, now): node = wrangle_node_parm(obj, 'accelerator_node', now) if node is not None: return node.type_and_paramset parm_selection = { 'accelerator' : SohoPBRT('accelerator', 'string', ['bvh'], False), } parms = obj.evaluate(parm_selection, now) accelerator_name = parms['accelerator'].Value[0] if accelerator_name == 'bvh': parm_selection = { 'maxnodeprims' : SohoPBRT('maxnodeprims', 'integer', [4], True), 'splitmethod' : SohoPBRT('splitmethod', 'string', ['sah'], True), } else: parm_selection = { 'intersectcost' : SohoPBRT('intersectcost', 'integer', [80], True), 'traversalcostcost' : SohoPBRT('traversalcost', 'integer', [1], True), 'emptybonus' : SohoPBRT('emptybonus', 'float', [0.2], True), 'maxprims' : SohoPBRT('maxprims', 'integer', [1], True), 'kdtree_maxdepth' : SohoPBRT('kdtree_maxdepth', 'integer', [1], True, key='maxdepth') } parms = obj.evaluate(parm_selection, now) paramset = ParamSet() for parm in parms: paramset.add(parms[parm].to_pbrt()) return (accelerator_name, paramset)
def wrangle_geo(obj, wrangler, now): parm_selection = { 'object:soppath' : SohoPBRT('object:soppath', 'string', [''], skipdefault=False), # NOTE: In order for shop_materialpath to evaluate correctly when using (full) instancing # shop_materialpath needs to be a 'shaderhandle' and not a 'string' # TODO: However this does not seem to apply to shop_materialpaths on the instance points. 'shop_materialpath' : SohoPBRT('shop_materialpath', 'shaderhandle', skipdefault=False), 'pbrt_rendersubd' : SohoPBRT('pbrt_rendersubd', 'bool', [False], False), 'pbrt_subdlevels' : SohoPBRT('pbrt_subdlevels', 'integer', [3], False, key='levels'), 'pbrt_computeN' : SohoPBRT('pbrt_computeN', 'bool', [True], False), # The combination of None as a default as well as ignore defaults being False is # important. 'None' implying the parm is missing and not available, and '' meaning # a vacuum medium. # We can't ignore defaults since a default might be the only way to set a medium # back to a vacuum. 'pbrt_interior' : SohoPBRT('pbrt_interior', 'string', [None], False), 'pbrt_exterior' : SohoPBRT('pbrt_exterior', 'string', [None], False), 'pbrt_ignorevolumes' : SohoPBRT('pbrt_ignorevolumes', 'bool', [False], True), 'pbrt_ignorematerials' : SohoPBRT('pbrt_ignorematerials', 'bool', [False], True), 'pbrt_splitdepth' : SohoPBRT('pbrt_splitdepth', 'integer', [3], True, key='splitdepth'), # We don't use the key=type since its a bit too generic of a name 'pbrt_curvetype' : SohoPBRT('pbrt_curvetype', 'string', ['flat'], True), 'pbrt_include' : SohoPBRT('pbrt_include', 'string', [''], False), 'pbrt_alpha_texture' : SohoPBRT('pbrt_alpha_texture', 'string', [''], skipdefault=False, key='alpha'), 'pbrt_shadowalpha_texture' : SohoPBRT('pbrt_shadowalpha_texture', 'string', [''], skipdefault=False, key='shadowalpha'), # TODO, Tesselation options? } properties = obj.evaluate(parm_selection, now) if 'shop_materialpath' not in properties: shop = '' else: shop = properties['shop_materialpath'].Value[0] if shop and shop in scene_state.shading_nodes: api.NamedMaterial(shop) interior = None exterior = None if 'pbrt_interior' in properties: interior = properties['pbrt_interior'].Value[0] if 'pbrt_exterior' in properties: exterior = properties['pbrt_exterior'].Value[0] # We only output a MediumInterface if one or both of the parms exist if interior is not None or exterior is not None: interior = '' if interior is None else interior exterior = '' if exterior is None else exterior api.MediumInterface(interior, exterior) for prop in ('alpha', 'shadowalpha'): alpha_tex = properties[prop].Value[0] alpha_node = BaseNode.from_node(alpha_tex) if ( alpha_node and alpha_node.directive == 'texture' and alpha_node.output_type == 'float'): if alpha_node.path not in scene_state.shading_nodes: wrangle_shading_network(alpha_node.path, saved_nodes=set()) else: # If the passed in alpha_texture wasn't valid, clear it so we don't add # it to the geometry if alpha_tex: api.Comment('%s is an invalid float texture' % alpha_tex) properties[prop].Value[0] = '' if properties['pbrt_include'].Value[0]: # If we have included a file, skip output any geo. api.Include(properties['pbrt_include'].Value[0]) return soppath = properties['object:soppath'].Value[0] if not soppath: api.Comment('Can not find soppath for object') return Geo.output_geo(soppath, now, properties) return
def wrangle_light(light, wrangler, now): # NOTE: Lights do not support motion blur so we disable it when # outputs the xforms node = wrangle_node_parm(light, 'light_node', now) parm_selection = { 'light_wrangler' : SohoPBRT('light_wrangler', 'string', [''], False), 'light_color' : SohoPBRT('light_color', 'float', [1, 1, 1], False), 'light_intensity' : SohoPBRT('light_intensity', 'float', [1], False), 'light_exposure' : SohoPBRT('light_exposure', 'float', [0], False), } parms = light.evaluate(parm_selection, now) light_wrangler = parms['light_wrangler'].Value[0] paramset = ParamSet() paramset.add(_to_light_scale(parms)) if light_wrangler == 'HoudiniEnvLight': env_map = [] paramset.add(PBRTParam('rgb', 'L', parms['light_color'].Value)) if light.evalString('env_map', now, env_map): paramset.add(PBRTParam('string', 'mapname', env_map)) output_xform(light, now, no_motionblur=True) api.Scale(1, 1, -1) api.Rotate(90, 0, 0, 1) api.Rotate(90, 0, 1, 0) _light_api_wrapper('infinite', paramset, node) return elif light_wrangler != 'HoudiniLight': api.Comment('This light type, %s, is unsupported' % light_wrangler) return # We are dealing with a standard HoudiniLight type. light_type = light.wrangleString(wrangler, 'light_type', now, ['point'])[0] if light_type in ('sphere', 'disk', 'grid', 'tube', 'geo'): single_sided = light.wrangleInt(wrangler, 'singlesided', now, [0])[0] visible = light.wrangleInt(wrangler, 'light_contribprimary', now, [0])[0] size = light.wrangleFloat(wrangler, 'areasize', now, [1, 1]) paramset.add(PBRTParam('rgb', 'L', parms['light_color'].Value)) paramset.add(PBRTParam('bool', 'twosided', [not single_sided])) # TODO, Possibly get the xform's scale and scale the geo, not the light. # (for example, further multiplying down the radius) xform = get_transform(light, now) xform_to_api_srt(xform, scale=False) _light_api_wrapper('diffuse', paramset, node) api.AttributeBegin() # PBRT only supports uniform scales for non-mesh area lights # this is in part due to explicit light's area scaling factor. if light_type in ('grid', 'geo'): api.Scale(size[0], size[1], size[0]) # The visibility only applies to hits on the non-emissive side of the light. # the emissive side will still be rendered if not visible: api.Material('none') if light_type == 'sphere': # We apply the scale to the radius instead of using a api.Scale api.Shape('sphere', [PBRTParam('float', 'radius', 0.5*size[0])]) elif light_type == 'tube': api.Rotate(90, 0, 1, 0) api.Shape('cylinder', [PBRTParam('float', 'radius', 0.075*size[1]), PBRTParam('float', 'zmin', -0.5*size[0]), PBRTParam('float', 'zmax', 0.5*size[0])]) elif light_type == 'disk': # A bug was introduced with Issue #154 which requires a -z scale # on disk area lights # See issue #183 # api.Scale(1,1,-1) api.Shape('disk', [PBRTParam('float', 'radius', 0.5*size[0])]) elif light_type == 'grid': api.Shape('trianglemesh', [PBRTParam('integer', 'indices', [0, 3, 1, 0, 2, 3]), PBRTParam('point', 'P', [-0.5, -0.5, 0, 0.5, -0.5, 0, -0.5, 0.5, 0, 0.5, 0.5, 0])]) elif light_type == 'geo': areageo_parm = hou.node(light.getName()).parm('areageometry') if not areageo_parm: api.Comment('No "areageometry" parm on light') return area_geo_node = areageo_parm.evalAsNode() if not area_geo_node: api.Comment('Skipping, no geometry object specified') return obj = soho.getObject(area_geo_node.path()) api.Comment('Light geo from %s' % obj.getName()) # TODO: The area light scale ('areasize') happens *after* the wrangle_obj's xform # when 'intothisobject' is enabled. into_this_obj = light.wrangleInt(wrangler, 'intothisobject', now, [0])[0] ignore_xform = not into_this_obj wrangle_obj(obj, None, now, ignore_xform=ignore_xform) api.AttributeEnd() return cone_enable = light.wrangleInt(wrangler, 'coneenable', now, [0])[0] projmap = light.wrangleString(wrangler, 'projmap', now, [''])[0] areamap = light.wrangleString(wrangler, 'areamap', now, [''])[0] api_calls = [] api_calls.append(_apiclosure(output_xform, light, now, no_motionblur=True)) api_calls.append(_apiclosure(api.Scale, 1, 1, -1)) api_calls.append(_apiclosure(api.Scale, 1, -1, 1)) if light_type == 'point': paramset.add(PBRTParam('rgb', 'I', parms['light_color'].Value)) if areamap: light_name = 'goniometric' paramset.add(PBRTParam('string', 'mapname', [areamap])) api_calls = [] api_calls.append(_apiclosure(output_xform, light, now, no_motionblur=True)) api_calls.append(_apiclosure(api.Scale, 1, -1, 1)) api_calls.append(_apiclosure(api.Rotate, 90, 0, 1, 0)) elif not cone_enable: light_name = 'point' else: conedelta = light.wrangleFloat(wrangler, 'conedelta', now, [10])[0] coneangle = light.wrangleFloat(wrangler, 'coneangle', now, [45])[0] if projmap: light_name = 'projection' paramset.add(PBRTParam('float', 'fov', [coneangle])) paramset.add(PBRTParam('string', 'mapname', [projmap])) else: light_name = 'spot' coneangle *= 0.5 coneangle += conedelta paramset.add(PBRTParam('float', 'coneangle', [coneangle])) paramset.add(PBRTParam('float', 'conedeltaangle', [conedelta])) elif light_type == 'distant': light_name = light_type paramset.add(PBRTParam('rgb', 'L', parms['light_color'].Value)) else: api.Comment('Light Type, %s, not supported' % light_type) return for api_call in api_calls: api_call() _light_api_wrapper(light_name, paramset, node) return
def wrangle_camera(obj, wrangler, now): node = wrangle_node_parm(obj, 'camera_node', now) if node is not None: output_cam_xform(obj, node.directive_type, now) return node.type_and_paramset paramset = ParamSet() window = obj.getCameraScreenWindow(wrangler, now) parm_selection = { 'projection' : SohoPBRT('projection', 'string', ['perspective'], False), 'focal' : SohoPBRT('focal', 'float', [50], False), 'focalunits' : SohoPBRT('focalunits', 'string', ['mm'], False), 'aperture' : SohoPBRT('aperture', 'float', [41.4214], False), 'orthowidth' : SohoPBRT('orthowidth', 'float', [2], False), 'res' : SohoPBRT('res', 'integer', [1280, 720], False), 'aspect' : SohoPBRT('aspect', 'float', [1], False), 'fstop' : SohoPBRT('fstop', 'float', [5.6], False), 'focaldistance' : SohoPBRT('focus', 'float', [5], False, key='focaldistance'), 'pbrt_dof' : SohoPBRT('pbrt_dof', 'integer', [0], False), } parms = obj.evaluate(parm_selection, now) aspect = parms['aspect'].Value[0] aspectfix = aspect * float(parms['res'].Value[0]) / float(parms['res'].Value[1]) projection = parms['projection'].Value[0] if parms['pbrt_dof'].Value[0]: paramset.add(parms['focaldistance'].to_pbrt()) # to convert from f-stop to lens radius # FStop = FocalLength / (Radius * 2) # Radius = FocalLength/(FStop * 2) focal = parms['focal'].Value[0] fstop = parms['fstop'].Value[0] units = parms['focalunits'].Value[0] focal = soho.houdiniUnitLength(focal, units) lens_radius = focal/(fstop*2.0) paramset.add(PBRTParam('float', 'lensradius', lens_radius)) if projection == 'perspective': projection_name = 'perspective' focal = parms['focal'].Value[0] aperture = parms['aperture'].Value[0] fov = 2.0 * focal / aperture fov = 2.0 * math.degrees(math.atan2(1.0, fov)) paramset.add(PBRTParam('float', 'fov', [fov])) screen = [(window[0] - 0.5) * 2.0, (window[1] - 0.5) * 2.0, (window[2] - 0.5) * 2.0 / aspectfix, (window[3] - 0.5) * 2.0 / aspectfix] paramset.add(PBRTParam('float', 'screenwindow', screen)) elif projection == 'ortho': projection_name = 'orthographic' width = parms['orthowidth'].Value[0] screen = [(window[0] - 0.5) * width, (window[1] - 0.5) * width, (window[2] - 0.5) * width / aspectfix, (window[3] - 0.5) * width / aspectfix] paramset.add(PBRTParam('float', 'screenwindow', screen)) elif projection == 'sphere': projection_name = 'environment' else: soho.error('Camera projection setting of %s not supported by PBRT' % projection) output_cam_xform(obj, projection_name, now) return (projection_name, paramset)
def wrangle_integrator(obj, wrangler, now): node = wrangle_node_parm(obj, 'integrator_node', now) if node is not None: return node.type_and_paramset parm_selection = { 'integrator' : SohoPBRT('integrator', 'string', ['path'], False), 'maxdepth' : SohoPBRT('maxdepth', 'integer', [5], False), 'rrthreshold' : SohoPBRT('rrthreshold', 'float', [1], True), 'lightsamplestrategy' : SohoPBRT('lightsamplestrategy', 'string', ['spatial'], True), 'visualizestrategies' : SohoPBRT('visualizestrategies', 'toggle', [False], True), 'visualizeweights' : SohoPBRT('visualizeweights', 'toggle', [False], True), 'iterations' : SohoPBRT('iterations', 'integer', [64], True), 'photonsperiterations' : SohoPBRT('photonsperiterations', 'integer', [-1], True), 'imagewritefrequency' : SohoPBRT('imagewritefrequency', 'integer', [2.14748e+09], True), 'radius' : SohoPBRT('radius', 'float', [1], True), 'bootstrapsamples' : SohoPBRT('bootstrapsamples', 'integer', [100000], True), 'chains' : SohoPBRT('chains', 'integer', [1000], True), 'mutationsperpixel' : SohoPBRT('mutataionsperpixel', 'integer', [100], True), 'largestepprobability' : SohoPBRT('largestepprobability', 'float', [0.3], True), 'sigma' : SohoPBRT('sigma', 'float', [0.01], True), 'strategy' : SohoPBRT('strategy', 'string', ['all'], True), 'nsamples' : SohoPBRT('nsamples', 'integer', ['64'], True), 'cossample' : SohoPBRT('cossample', 'toggle', [True], True), } integrator_parms = { 'ao' : ['nsamples', 'cossample'], 'path' : ['maxdepth', 'rrthreshold', 'lightsamplestrategy'], 'bdpt' : ['maxdepth', 'rrthreshold', 'lightsamplestrategy', 'visualizestrategies', 'visualizeweights'], 'mlt' : ['maxdepth', 'bootstrapsamples', 'chains', 'mutationsperpixel', 'largestepprobability', 'sigma'], 'sppm' : ['maxdepth', 'iterations', 'photonsperiteration', 'imagewritefrequency', 'radius'], 'whitted' : ['maxdepth'], 'volpath' : ['maxdepth', 'rrthreshold', 'lightsamplestrategy'], 'directlighting' : ['maxdepth', 'strategy'], } parms = obj.evaluate(parm_selection, now) integrator_name = parms['integrator'].Value[0] paramset = ParamSet() for parm_name in integrator_parms[integrator_name]: if parm_name not in parms: continue paramset.add(parms[parm_name].to_pbrt()) return (integrator_name, paramset)
def wrangle_options(obj, wrangler, now): parm_selection = { "disabletexturefiltering": SohoPBRT( "disabletexturefiltering", "bool", [False], True ), "disablepixeljitter": SohoPBRT("disablepixeljitter", "bool", [False], True), "disablewavelengthjitter": SohoPBRT( "disablewavelengthjitter", "bool", [False], True ), "msereferenceimage": SohoPBRT("msereferenceimage", "string", [""], True), "msereferenceout": SohoPBRT("msereferenceout", "string", [""], True), # NOTE: # The PBRT default is "cameraworld" but this can cause instancing interpolation issues # For now we'll use the PBRT default and expect the user to switch to world, but depending # on the resolution of https://github.com/mmp/pbrt-v4/issues/206 we may need to default # this to "world" "rendercoordsys": SohoPBRT("rendercoordsys", "string", ["cameraworld"], True), "seed": SohoPBRT("seed", "integer", [0], True), "displacementedgescale": SohoPBRT( "displacementedgescale", "float", [1.0], True ), "forcediffuse": SohoPBRT("forcediffuse", "bool", [False], True), "pixelstats": SohoPBRT("pixelstats", "bool", [False], True), "wavefront": SohoPBRT("wavefront", "bool", [False], True), } parms = obj.evaluate(parm_selection, now) for parm in parms: yield (parm, parms[parm].to_pbrt())
def wrangle_integrator(obj, wrangler, now): node = wrangle_node_parm(obj, "integrator_node", now) if node is not None: return node.type_and_paramset parm_selection = { "integrator": SohoPBRT("integrator", "string", ["path"], False), "maxdepth": SohoPBRT("maxdepth", "integer", [5], False), "regularize": SohoPBRT("regularize", "bool", [False], True), "lightsampler": SohoPBRT("lightsampler", "string", ["bvh"], True), "visualizestrategies": SohoPBRT("visualizestrategies", "bool", [False], True), "visualizeweights": SohoPBRT("visualizeweights", "bool", [False], True), "iterations": SohoPBRT("iterations", "integer", [64], True), "photonsperiteration": SohoPBRT("photonsperiteration", "integer", [-1], True), "seed": SohoPBRT("sppm_seed", "integer", [6502], True, key="seed"), "radius": SohoPBRT("radius", "float", [1], True), "bootstrapsamples": SohoPBRT("bootstrapsamples", "integer", [100000], True), "chains": SohoPBRT("chains", "integer", [1000], True), "mutationsperpixel": SohoPBRT("mutationsperpixel", "integer", [100], True), "largestepprobability": SohoPBRT("largestepprobability", "float", [0.3], True), "sigma": SohoPBRT("sigma", "float", [0.01], True), "maxdistance": SohoPBRT("maxdistance", "float", ["1e38"], True), "cossample": SohoPBRT("cossample", "bool", [True], True), "samplelights": SohoPBRT("samplelights", "bool", [True], True), "samplebsdf": SohoPBRT("samplebsdf", "bool", [True], True), } integrator_parms = { "ambientocclusion": ["maxdistance", "cossample"], "path": ["maxdepth", "regularize", "lightsampler"], "bdpt": ["maxdepth", "regularize", "visualizestrategies", "visualizeweights"], "mlt": [ "maxdepth", "bootstrapsamples", "chains", "mutationsperpixel", "largestepprobability", "sigma", "regularize", ], "sppm": [ "maxdepth", "iterations", "photonsperiteration", "seed", "radius", "regularize", ], "lightpath": ["maxdepth"], "randomwalk": ["maxdepth"], "simplepath": ["maxdepth", "samplelights", "samplebsdf"], "simplevolpath": ["maxdepth"], "volpath": ["maxdepth", "lightsampler", "regularize"], } parms = obj.evaluate(parm_selection, now) integrator_name = parms["integrator"].Value[0] paramset = ParamSet() for parm_name in integrator_parms[integrator_name]: if parm_name not in parms: continue paramset.add(parms[parm_name].to_pbrt()) return (integrator_name, paramset)
def wrangle_geo(obj, wrangler, now): parm_selection = { "object:soppath": SohoPBRT("object:soppath", "string", [""], skipdefault=False), "ptinstance": SohoPBRT("ptinstance", "integer", [0], skipdefault=False), # NOTE: In order for shop_materialpath to evaluate correctly when using # (full) instancing shop_materialpath needs to be a 'shaderhandle' # and not a 'string' # NOTE: However this does not seem to apply to shop_materialpaths on the # instance points and has to be done manually "shop_materialpath": SohoPBRT( "shop_materialpath", "shaderhandle", skipdefault=False ), "pbrt_rendersubd": SohoPBRT("pbrt_rendersubd", "bool", [False], False), "pbrt_subdlevels": SohoPBRT( "pbrt_subdlevels", "integer", [3], False, key="levels" ), "pbrt_computeN": SohoPBRT("pbrt_computeN", "bool", [True], False), "pbrt_reverseorientation": SohoPBRT( "pbrt_reverseorientation", "bool", [False], True ), # The combination of None as a default as well as ignore defaults being False # is important. 'None' implying the parm is missing and not available, # and '' meaning a vacuum medium. # We can't ignore defaults since a default might be the only way to set a # medium back to a vacuum. "pbrt_interior": SohoPBRT("pbrt_interior", "string", [None], False), "pbrt_exterior": SohoPBRT("pbrt_exterior", "string", [None], False), "pbrt_ignorevolumes": SohoPBRT("pbrt_ignorevolumes", "bool", [False], True), "pbrt_ignorematerials": SohoPBRT("pbrt_ignorematerials", "bool", [False], True), "pbrt_splitdepth": SohoPBRT( "pbrt_splitdepth", "integer", [3], True, key="splitdepth" ), # We don't use the key=type since its a bit too generic of a name "pbrt_curvetype": SohoPBRT("pbrt_curvetype", "string", ["flat"], True), "pbrt_include": SohoPBRT("pbrt_include", "string", [""], False), "pbrt_alpha_texture": SohoPBRT( "pbrt_alpha_texture", "string", [""], skipdefault=False, key="alpha" ), "pbrt_shadowalpha_texture": SohoPBRT( "pbrt_shadowalpha_texture", "string", [""], skipdefault=False, key="shadowalpha", ), # TODO, Tesselation options? } properties = obj.evaluate(parm_selection, now) if "shop_materialpath" not in properties: shop = "" else: shop = properties["shop_materialpath"].Value[0] # NOTE: Having to track down shop_materialpaths does not seem to be a requirement # with Mantra or RenderMan. Either its because I'm missing some # logic/initialization either in Soho or in the Shading HDAs. Or there is # some hardcoding in the Houdini libs that know how to translate # shop_materialpath point aassignments to shaders directly through a # SohoParm. Until that is figured out, we'll have to do it manually. interior = None exterior = None if "pbrt_interior" in properties: interior = properties["pbrt_interior"].Value[0] if "pbrt_exterior" in properties: exterior = properties["pbrt_exterior"].Value[0] if "pbrt_reverseorientation" in properties: if properties["pbrt_reverseorientation"].Value[0]: api.ReverseOrientation() pt_shop_found = False if properties["ptinstance"].Value[0] == 1: instance_info = Instancing.get_full_instance_info(obj, now) properties[".instance_info"] = instance_info if instance_info is not None: pt_shop_found = process_full_pt_instance_material(instance_info) interior, interior_paramset = process_full_pt_instance_medium( instance_info, "interior" ) exterior, exterior_paramset = process_full_pt_instance_medium( instance_info, "exterior" ) if interior_paramset is not None: properties[".interior_overrides"] = interior_paramset # If we found a point shop, don't output the default one here. if shop in scene_state.shading_nodes and not pt_shop_found: api.NamedMaterial(shop) # We only output a MediumInterface if one or both of the parms exist if interior is not None or exterior is not None: interior = "" if interior is None else interior exterior = "" if exterior is None else exterior api.MediumInterface(interior, exterior) for prop in ("alpha", "shadowalpha"): alpha_tex = properties[prop].Value[0] alpha_node = BaseNode.from_node(alpha_tex) if ( alpha_node and alpha_node.directive == "texture" and alpha_node.output_type == "float" ): if alpha_node.path not in scene_state.shading_nodes: wrangle_shading_network(alpha_node.path, saved_nodes=set()) else: # If the passed in alpha_texture wasn't valid, clear it so we don't add # it to the geometry if alpha_tex: api.Comment("%s is an invalid float texture" % alpha_tex) properties[prop].Value[0] = "" if properties["pbrt_include"].Value[0]: # If we have included a file, skip output any geo. api.Include(properties["pbrt_include"].Value[0]) return soppath = properties["object:soppath"].Value[0] if not soppath: api.Comment("Can not find soppath for object") return Geo.output_geo(soppath, now, properties) return
def wrangle_light(light, wrangler, now): # NOTE: Lights do not support motion blur so we disable it when # outputs the xforms node = wrangle_node_parm(light, "light_node", now) parm_selection = { "light_wrangler": SohoPBRT("light_wrangler", "string", [""], False), "light_color": SohoPBRT("light_color", "float", [1, 1, 1], False), "light_intensity": SohoPBRT("light_intensity", "float", [1], False), "light_exposure": SohoPBRT("light_exposure", "float", [0], False), } parms = light.evaluate(parm_selection, now) light_wrangler = parms["light_wrangler"].Value[0] paramset = ParamSet() paramset.add(_to_light_scale(parms)) if light_wrangler == "HoudiniEnvLight": env_map = [] paramset.add(PBRTParam("rgb", "L", parms["light_color"].Value)) if light.evalString("env_map", now, env_map): paramset.add(PBRTParam("string", "mapname", env_map)) output_xform(light, now, no_motionblur=True) api.Scale(1, 1, -1) api.Rotate(90, 0, 0, 1) api.Rotate(90, 0, 1, 0) _light_api_wrapper("infinite", paramset, node) return elif light_wrangler != "HoudiniLight": api.Comment("This light type, %s, is unsupported" % light_wrangler) return # We are dealing with a standard HoudiniLight type. light_type = light.wrangleString(wrangler, "light_type", now, ["point"])[0] if light_type in ("sphere", "disk", "grid", "tube", "geo"): single_sided = light.wrangleInt(wrangler, "singlesided", now, [0])[0] visible = light.wrangleInt(wrangler, "light_contribprimary", now, [0])[0] size = light.wrangleFloat(wrangler, "areasize", now, [1, 1]) paramset.add(PBRTParam("rgb", "L", parms["light_color"].Value)) paramset.add(PBRTParam("bool", "twosided", [not single_sided])) # TODO, Possibly get the xform's scale and scale the geo, not the light. # (for example, further multiplying down the radius) xform = get_transform(light, now) xform_to_api_srt(xform, scale=False) _light_api_wrapper("diffuse", paramset, node) api.AttributeBegin() # PBRT only supports uniform scales for non-mesh area lights # this is in part due to explicit light's area scaling factor. if light_type in ("grid", "geo"): api.Scale(size[0], size[1], size[0]) # The visibility only applies to hits on the non-emissive side of the light. # the emissive side will still be rendered if not visible: api.Material("none") if light_type == "sphere": # We apply the scale to the radius instead of using a api.Scale api.Shape("sphere", [PBRTParam("float", "radius", 0.5 * size[0])]) elif light_type == "tube": api.Rotate(90, 0, 1, 0) api.Shape( "cylinder", [ PBRTParam("float", "radius", 0.075 * size[1]), PBRTParam("float", "zmin", -0.5 * size[0]), PBRTParam("float", "zmax", 0.5 * size[0]), ], ) elif light_type == "disk": # After pbrt-v3 commit #2f0852ce api.ReverseOrientation() is needed, # prior that it was a api.Scale(1,1,-1) # (see issue #183 in pbrt-v3) api.ReverseOrientation() api.Shape("disk", [PBRTParam("float", "radius", 0.5 * size[0])]) elif light_type == "grid": api.Shape( "trianglemesh", [ PBRTParam("integer", "indices", [0, 3, 1, 0, 2, 3]), PBRTParam( "point", "P", [-0.5, -0.5, 0, 0.5, -0.5, 0, -0.5, 0.5, 0, 0.5, 0.5, 0], ), ], ) elif light_type == "geo": areageo_parm = hou.node(light.getName()).parm("areageometry") if not areageo_parm: api.Comment('No "areageometry" parm on light') return area_geo_node = areageo_parm.evalAsNode() if not area_geo_node: api.Comment("Skipping, no geometry object specified") return obj = soho.getObject(area_geo_node.path()) api.Comment("Light geo from %s" % obj.getName()) # TODO: The area light scale ('areasize') happens *after* the wrangle_obj's # xform when 'intothisobject' is enabled. into_this_obj = light.wrangleInt(wrangler, "intothisobject", now, [0])[0] ignore_xform = not into_this_obj wrangle_obj(obj, None, now, ignore_xform=ignore_xform) api.AttributeEnd() return cone_enable = light.wrangleInt(wrangler, "coneenable", now, [0])[0] projmap = light.wrangleString(wrangler, "projmap", now, [""])[0] areamap = light.wrangleString(wrangler, "areamap", now, [""])[0] api_calls = [] api_calls.append(_apiclosure(output_xform, light, now, no_motionblur=True)) api_calls.append(_apiclosure(api.Scale, 1, 1, -1)) api_calls.append(_apiclosure(api.Scale, 1, -1, 1)) if light_type == "point": paramset.add(PBRTParam("rgb", "I", parms["light_color"].Value)) if areamap: light_name = "goniometric" paramset.add(PBRTParam("string", "mapname", [areamap])) api_calls = [] api_calls.append(_apiclosure(output_xform, light, now, no_motionblur=True)) api_calls.append(_apiclosure(api.Scale, 1, -1, 1)) api_calls.append(_apiclosure(api.Rotate, 90, 0, 1, 0)) elif not cone_enable: light_name = "point" else: conedelta = light.wrangleFloat(wrangler, "conedelta", now, [10])[0] coneangle = light.wrangleFloat(wrangler, "coneangle", now, [45])[0] if projmap: light_name = "projection" paramset.add(PBRTParam("float", "fov", [coneangle])) paramset.add(PBRTParam("string", "mapname", [projmap])) else: light_name = "spot" coneangle *= 0.5 coneangle += conedelta paramset.add(PBRTParam("float", "coneangle", [coneangle])) paramset.add(PBRTParam("float", "conedeltaangle", [conedelta])) elif light_type == "distant": light_name = light_type paramset.add(PBRTParam("rgb", "L", parms["light_color"].Value)) else: api.Comment("Light Type, %s, not supported" % light_type) return for api_call in api_calls: api_call() _light_api_wrapper(light_name, paramset, node) return
def wrangle_camera(obj, wrangler, now): node = wrangle_node_parm(obj, "camera_node", now) if node is not None: output_cam_xform(obj, node.directive_type, now) return node.type_and_paramset paramset = ParamSet() window = obj.getCameraScreenWindow(wrangler, now) parm_selection = { "projection": SohoPBRT("projection", "string", ["perspective"], False), "focal": SohoPBRT("focal", "float", [50], False), "focalunits": SohoPBRT("focalunits", "string", ["mm"], False), "aperture": SohoPBRT("aperture", "float", [41.4214], False), "orthowidth": SohoPBRT("orthowidth", "float", [2], False), "res": SohoPBRT("res", "integer", [1280, 720], False), "aspect": SohoPBRT("aspect", "float", [1], False), "fstop": SohoPBRT("fstop", "float", [5.6], False), "focaldistance": SohoPBRT("focus", "float", [5], False, key="focaldistance"), "pbrt_dof": SohoPBRT("pbrt_dof", "integer", [0], False), } parms = obj.evaluate(parm_selection, now) aspect = parms["aspect"].Value[0] aspectfix = aspect * float(parms["res"].Value[0]) / float(parms["res"].Value[1]) projection = parms["projection"].Value[0] if parms["pbrt_dof"].Value[0]: paramset.add(parms["focaldistance"].to_pbrt()) # to convert from f-stop to lens radius # FStop = FocalLength / (Radius * 2) # Radius = FocalLength/(FStop * 2) focal = parms["focal"].Value[0] fstop = parms["fstop"].Value[0] units = parms["focalunits"].Value[0] focal = soho.houdiniUnitLength(focal, units) lens_radius = focal / (fstop * 2.0) paramset.add(PBRTParam("float", "lensradius", lens_radius)) if projection == "perspective": projection_name = "perspective" focal = parms["focal"].Value[0] aperture = parms["aperture"].Value[0] fov = 2.0 * focal / aperture fov = 2.0 * math.degrees(math.atan2(1.0, fov)) paramset.add(PBRTParam("float", "fov", [fov])) screen = [ (window[0] - 0.5) * 2.0, (window[1] - 0.5) * 2.0, (window[2] - 0.5) * 2.0 / aspectfix, (window[3] - 0.5) * 2.0 / aspectfix, ] paramset.add(PBRTParam("float", "screenwindow", screen)) elif projection == "ortho": projection_name = "orthographic" width = parms["orthowidth"].Value[0] screen = [ (window[0] - 0.5) * width, (window[1] - 0.5) * width, (window[2] - 0.5) * width / aspectfix, (window[3] - 0.5) * width / aspectfix, ] paramset.add(PBRTParam("float", "screenwindow", screen)) elif projection == "sphere": projection_name = "environment" else: soho.error("Camera projection setting of %s not supported by PBRT" % projection) output_cam_xform(obj, projection_name, now) return (projection_name, paramset)
def wrangle_light(light, wrangler, now): # NOTE: Lights do not support motion blur so we disable it when # outputs the xforms node = wrangle_node_parm(light, "light_node", now) # We skip the light_color if its at default so we avoid setting rgb values # if at all possible, that way we get a constant spectrum instead parm_selection = { "light_wrangler": SohoPBRT("light_wrangler", "string", [""], False), "light_color": SohoPBRT("light_color", "float", [1, 1, 1], True), "light_intensity": SohoPBRT("light_intensity", "float", [1], False), "light_exposure": SohoPBRT("light_exposure", "float", [0], False), } parms = light.evaluate(parm_selection, now) light_wrangler = parms["light_wrangler"].Value[0] exterior = light.wrangleString(wrangler, "pbrt_exterior", now, [None])[0] exterior = wrangle_medium(exterior) if exterior: api.MediumInterface("", exterior) print() paramset = ParamSet() paramset.add(_to_light_scale(parms)) if light_wrangler == "HoudiniEnvLight": env_map = [] light.evalString("env_map", now, env_map) # evalString will return [""] if the parm exists yet at its default env_map = env_map[0] if env_map else "" if env_map: paramset.add(PBRTParam("string", "filename", env_map)) elif "light_color" in parms: paramset.add(PBRTParam("rgb", "L", parms["light_color"].Value)) portal = light.wrangleString(wrangler, "env_portal", now, [""])[0] portal_enabled = light.wrangleInt(wrangler, "env_portalenable", now, [0])[0] if portal_enabled and portal: portal_pts = _portal_helper(now, portal) if portal_pts is not None: # TODO pbrt-v4 we may need to invert the Houdini -> PBRT xform paramset.add(PBRTParam("point", "portal", portal_pts)) output_xform(light, now, no_motionblur=True) api.Scale(1, 1, -1) api.Rotate(90, 0, 0, 1) api.Rotate(90, 0, 1, 0) _light_api_wrapper("infinite", paramset, node) return elif light_wrangler != "HoudiniLight": api.Comment("This light type, %s, is unsupported" % light_wrangler) return # We are dealing with a standard HoudiniLight type. light_type = light.wrangleString(wrangler, "light_type", now, ["point"])[0] if light_type in ("sphere", "disk", "grid", "tube", "geo"): single_sided = light.wrangleInt(wrangler, "singlesided", now, [0])[0] reverse = light.wrangleInt(wrangler, "reverse", now, [0])[0] visible = light.wrangleInt(wrangler, "light_contribprimary", now, [0])[0] size = light.wrangleFloat(wrangler, "areasize", now, [1, 1]) paramset.add(PBRTParam("bool", "twosided", [not single_sided])) texmap = light.wrangleString(wrangler, "light_texture", now, [""])[0] if texmap: paramset.add(PBRTParam("string", "filename", texmap)) elif "light_color" in parms: paramset.add(PBRTParam("rgb", "L", parms["light_color"].Value)) # TODO, Possibly get the xform's scale and scale the geo, not the light. # (for example, further multiplying down the radius) xform = get_transform(light, now) xform_to_api_srt(xform, scale=False) _light_api_wrapper("diffuse", paramset, node) api.AttributeBegin() if single_sided and reverse: api.ReverseOrientation() shape_paramset = ParamSet() if not visible: shape_paramset.add(PBRTParam("float", "alpha", 0.0)) # PBRT only supports uniform scales for non-mesh area lights # this is in part due to explicit light's area scaling factor. if light_type in ("grid", "geo"): api.Scale(size[0], size[1], size[0]) if light_type == "sphere": # NOTE: # To match the UVs we need a api.Scale(1, 1, -1) # However doing this screws up the direction of emission. # When rendering as one sided, the emissive side will be the opposite # side from which is used to illuminate. Unfortunately an # api.ReverseOrientation() does not fix this. # We apply the scale to the radius instead of using a api.Scale shape_paramset.add(PBRTParam("float", "radius", 0.5 * size[0])) api.Shape("sphere", shape_paramset) elif light_type == "tube": api.Rotate(90, 0, 1, 0) api.Rotate(90, 0, 0, 1) # NOTE: # To match UVs we need a api.Scale(1, 1, -1) # see note above about spheres. shape_paramset.add(PBRTParam("float", "radius", 0.075 * size[1])) shape_paramset.add(PBRTParam("float", "zmin", -0.5 * size[0])) shape_paramset.add(PBRTParam("float", "zmax", 0.5 * size[0])) api.Shape("cylinder", shape_paramset) elif light_type == "disk": # NOTE this should match mantra now, unlike in pbrt-v3 api.Scale(-1, 1, -1) shape_paramset.add(PBRTParam("float", "radius", 0.5 * size[0])) api.Shape("disk", shape_paramset) elif light_type == "grid": api.ReverseOrientation() shape_paramset.add( PBRTParam( "point", "P", [-0.5, -0.5, 0, 0.5, -0.5, 0, -0.5, 0.5, 0, 0.5, 0.5, 0], ) ) api.Shape("bilinearmesh", shape_paramset) elif light_type == "geo": areageo_parm = hou.node(light.getName()).parm("areageometry") if not areageo_parm: api.Comment('No "areageometry" parm on light') return area_geo_node = areageo_parm.evalAsNode() if not area_geo_node: api.Comment("Skipping, no geometry object specified") return obj = soho.getObject(area_geo_node.path()) api.Comment("Light geo from %s" % obj.getName()) # TODO: The area light scale ('areasize') happens *after* the wrangle_obj's # xform when 'intothisobject' is enabled. # TODO: the Light visiblity paramset ("alpha") can't be easily passed # with this current interface. It can be worked aroudn by setting # the referenced object's "alpha" property into_this_obj = light.wrangleInt(wrangler, "intothisobject", now, [0])[0] ignore_xform = not into_this_obj wrangle_obj(obj, None, now, ignore_xform=ignore_xform) api.AttributeEnd() return cone_enable = light.wrangleInt(wrangler, "coneenable", now, [0])[0] projmap = light.wrangleString(wrangler, "projmap", now, [""])[0] areamap = light.wrangleString(wrangler, "areamap", now, [""])[0] api_calls = [] api_calls.append(_apiclosure(output_xform, light, now, no_motionblur=True)) api_calls.append(_apiclosure(api.Scale, 1, 1, -1)) api_calls.append(_apiclosure(api.Scale, 1, -1, 1)) if light_type == "point": if areamap: light_name = "goniometric" if "light_color" in parms: paramset.add(PBRTParam("rgb", "I", parms["light_color"].Value)) paramset.add(PBRTParam("string", "filename", [areamap])) api_calls = [] api_calls.append(_apiclosure(output_xform, light, now, no_motionblur=True)) api_calls.append(_apiclosure(api.Scale, 1, -1, 1)) api_calls.append(_apiclosure(api.Rotate, 90, 0, 1, 0)) elif not cone_enable: light_name = "point" if "light_color" in parms: paramset.add(PBRTParam("rgb", "I", parms["light_color"].Value)) elif projmap: light_name = "projection" coneangle = light.wrangleFloat(wrangler, "coneangle", now, [45])[0] paramset.add(PBRTParam("float", "fov", [coneangle])) paramset.add(PBRTParam("string", "filename", [projmap])) else: light_name = "spot" if "light_color" in parms: paramset.add(PBRTParam("rgb", "I", parms["light_color"].Value)) conedelta = light.wrangleFloat(wrangler, "conedelta", now, [10])[0] coneangle = light.wrangleFloat(wrangler, "coneangle", now, [45])[0] coneangle *= 0.5 coneangle += conedelta paramset.add(PBRTParam("float", "coneangle", [coneangle])) paramset.add(PBRTParam("float", "conedeltaangle", [conedelta])) elif light_type == "distant": light_name = light_type if "light_color" in parms: paramset.add(PBRTParam("rgb", "L", parms["light_color"].Value)) else: api.Comment("Light Type, %s, not supported" % light_type) return for api_call in api_calls: api_call() _light_api_wrapper(light_name, paramset, node) return
def wrangle_integrator(obj, wrangler, now): node = wrangle_node_parm(obj, "integrator_node", now) if node is not None: return node.type_and_paramset parm_selection = { "integrator": SohoPBRT("integrator", "string", ["path"], False), "maxdepth": SohoPBRT("maxdepth", "integer", [5], False), "rrthreshold": SohoPBRT("rrthreshold", "float", [1], True), "lightsamplestrategy": SohoPBRT( "lightsamplestrategy", "string", ["spatial"], True ), "visualizestrategies": SohoPBRT("visualizestrategies", "toggle", [False], True), "visualizeweights": SohoPBRT("visualizeweights", "toggle", [False], True), "iterations": SohoPBRT("iterations", "integer", [64], True), "photonsperiterations": SohoPBRT("photonsperiterations", "integer", [-1], True), "imagewritefrequency": SohoPBRT( "imagewritefrequency", "integer", [2.14748e09], True ), "radius": SohoPBRT("radius", "float", [1], True), "bootstrapsamples": SohoPBRT("bootstrapsamples", "integer", [100000], True), "chains": SohoPBRT("chains", "integer", [1000], True), "mutationsperpixel": SohoPBRT("mutataionsperpixel", "integer", [100], True), "largestepprobability": SohoPBRT("largestepprobability", "float", [0.3], True), "sigma": SohoPBRT("sigma", "float", [0.01], True), "strategy": SohoPBRT("strategy", "string", ["all"], True), "nsamples": SohoPBRT("nsamples", "integer", ["64"], True), "cossample": SohoPBRT("cossample", "toggle", [True], True), } integrator_parms = { "ao": ["nsamples", "cossample"], "path": ["maxdepth", "rrthreshold", "lightsamplestrategy"], "bdpt": [ "maxdepth", "rrthreshold", "lightsamplestrategy", "visualizestrategies", "visualizeweights", ], "mlt": [ "maxdepth", "bootstrapsamples", "chains", "mutationsperpixel", "largestepprobability", "sigma", ], "sppm": [ "maxdepth", "iterations", "photonsperiteration", "imagewritefrequency", "radius", ], "whitted": ["maxdepth"], "volpath": ["maxdepth", "rrthreshold", "lightsamplestrategy"], "directlighting": ["maxdepth", "strategy"], } parms = obj.evaluate(parm_selection, now) integrator_name = parms["integrator"].Value[0] paramset = ParamSet() for parm_name in integrator_parms[integrator_name]: if parm_name not in parms: continue paramset.add(parms[parm_name].to_pbrt()) return (integrator_name, paramset)
def wrangle_geo(obj, wrangler, now): parm_selection = { 'object:soppath': SohoPBRT('object:soppath', 'string', [''], skipdefault=False), 'ptinstance': SohoPBRT('ptinstance', 'integer', [0], skipdefault=False), # NOTE: In order for shop_materialpath to evaluate correctly when using (full) instancing # shop_materialpath needs to be a 'shaderhandle' and not a 'string' # NOTE: However this does not seem to apply to shop_materialpaths on the instance points # and has to be done manually 'shop_materialpath': SohoPBRT('shop_materialpath', 'shaderhandle', skipdefault=False), 'pbrt_rendersubd': SohoPBRT('pbrt_rendersubd', 'bool', [False], False), 'pbrt_subdlevels': SohoPBRT('pbrt_subdlevels', 'integer', [3], False, key='levels'), 'pbrt_computeN': SohoPBRT('pbrt_computeN', 'bool', [True], False), # The combination of None as a default as well as ignore defaults being False is # important. 'None' implying the parm is missing and not available, and '' meaning # a vacuum medium. # We can't ignore defaults since a default might be the only way to set a medium # back to a vacuum. 'pbrt_interior': SohoPBRT('pbrt_interior', 'string', [None], False), 'pbrt_exterior': SohoPBRT('pbrt_exterior', 'string', [None], False), 'pbrt_ignorevolumes': SohoPBRT('pbrt_ignorevolumes', 'bool', [False], True), 'pbrt_ignorematerials': SohoPBRT('pbrt_ignorematerials', 'bool', [False], True), 'pbrt_splitdepth': SohoPBRT('pbrt_splitdepth', 'integer', [3], True, key='splitdepth'), # We don't use the key=type since its a bit too generic of a name 'pbrt_curvetype': SohoPBRT('pbrt_curvetype', 'string', ['flat'], True), 'pbrt_include': SohoPBRT('pbrt_include', 'string', [''], False), 'pbrt_alpha_texture': SohoPBRT('pbrt_alpha_texture', 'string', [''], skipdefault=False, key='alpha'), 'pbrt_shadowalpha_texture': SohoPBRT('pbrt_shadowalpha_texture', 'string', [''], skipdefault=False, key='shadowalpha'), # TODO, Tesselation options? } properties = obj.evaluate(parm_selection, now) if 'shop_materialpath' not in properties: shop = '' else: shop = properties['shop_materialpath'].Value[0] # NOTE: Having to track down shop_materialpaths does not seem to be a requirement # with Mantra or RenderMan. Either its because I'm missing some logic/initialization # either in Soho or in the Shading HDAs. Or there is some hardcoding in the Houdini libs # that know how to translate shop_materialpath point aassignments to shaders directly # through a SohoParm. Until that is figured out, we'll have to do it manually. pt_shop_found = False if properties['ptinstance'].Value[0] == 1: pt_shop_found = Instancing.process_full_pt_instance_material(obj, now) # If we found a point shop, don't output the default one here. if shop in scene_state.shading_nodes and not pt_shop_found: api.NamedMaterial(shop) interior = None exterior = None if 'pbrt_interior' in properties: interior = properties['pbrt_interior'].Value[0] if 'pbrt_exterior' in properties: exterior = properties['pbrt_exterior'].Value[0] # We only output a MediumInterface if one or both of the parms exist if interior is not None or exterior is not None: interior = '' if interior is None else interior exterior = '' if exterior is None else exterior api.MediumInterface(interior, exterior) for prop in ('alpha', 'shadowalpha'): alpha_tex = properties[prop].Value[0] alpha_node = BaseNode.from_node(alpha_tex) if (alpha_node and alpha_node.directive == 'texture' and alpha_node.output_type == 'float'): if alpha_node.path not in scene_state.shading_nodes: wrangle_shading_network(alpha_node.path, saved_nodes=set()) else: # If the passed in alpha_texture wasn't valid, clear it so we don't add # it to the geometry if alpha_tex: api.Comment('%s is an invalid float texture' % alpha_tex) properties[prop].Value[0] = '' if properties['pbrt_include'].Value[0]: # If we have included a file, skip output any geo. api.Include(properties['pbrt_include'].Value[0]) return soppath = properties['object:soppath'].Value[0] if not soppath: api.Comment('Can not find soppath for object') return Geo.output_geo(soppath, now, properties) return