Source code for blenderproc.python.lighting.SuncgLighting

"""This module provides functions to add light to the SUNCG scenes."""

from typing import Tuple, List, Dict

from blenderproc.python.utility.Utility import Utility
from blenderproc.python.types.MeshObjectUtility import MeshObject, get_all_mesh_objects
from blenderproc.python.types.MaterialUtility import Material


[docs] def light_suncg_scene(lightbulb_emission_strength: float = 15, lampshade_emission_strength: float = 7, ceiling_emission_strength: float = 1.5): """ Makes the lamps, windows and ceilings object emit light. :param lightbulb_emission_strength: The emission strength that should be used for light bulbs. Default: 15 :param lampshade_emission_strength: The emission strength that should be used for lamp shades. Default: 7 :param ceiling_emission_strength: The emission strength that should be used for the ceiling. Default: 1.5 """ # Read in the materials for lights and windows lights, windows = Utility.read_suncg_lights_windows_materials() collection_of_mats: Dict[str, Dict[str, Material]] = {"lamp": {}, "window": {}, "ceiling": {}} # Make some objects emit lights for obj in get_all_mesh_objects(): if obj.has_cp("modelId"): obj_id = obj.get_cp("modelId") # In the case of the lamp if obj_id in lights: _SuncgLighting.make_lamp_emissive(obj, lights[obj_id], collection_of_mats, lightbulb_emission_strength, lampshade_emission_strength) # Make the windows emit light if obj_id in windows: _SuncgLighting.make_window_emissive(obj, collection_of_mats) # Also make ceilings slightly emit light if obj.get_name().startswith("Ceiling#"): _SuncgLighting.make_ceiling_emissive(obj, collection_of_mats, ceiling_emission_strength)
[docs] class _SuncgLighting: """ Adds light properties to the SUNCG scenes. """
[docs] @staticmethod def make_lamp_emissive(obj: MeshObject, light: Tuple[List[str], List[str]], collection_of_mats: Dict[str, Dict[str, Material]], lightbulb_emission_strength: float = 15, lampshade_emission_strength: float = 7): """ Adds an emission shader to the object materials which are specified in the light dictionary :param obj: The blender object. :param light: A tuple of two lists. The first list specifies all materials which should act as a lightbulb, the second one lists all materials corresponding to lampshades. :param collection_of_mats: A dictionary that contains materials for lamps, windows and ceilings. :param lightbulb_emission_strength: The emission strength that should be used for light bulbs. Default: 15 :param lampshade_emission_strength: The emission strength that should be used for lamp shades. Default: 7 """ for i, m in enumerate(obj.get_materials()): if m is None: continue mat_name = m.get_name() if "." in mat_name: mat_name = mat_name[:mat_name.find(".")] if mat_name in light[0] or mat_name in light[1]: old_mat_name = m.get_name() if old_mat_name in collection_of_mats["lamp"]: # this material was used as a ceiling before use that one obj.set_material(i, collection_of_mats["lamp"][old_mat_name]) continue # copy the material if more than one users is using it if m.get_users() > 1: m = m.duplicate() obj.set_material(i, m) # rename the material m.set_name(m.get_name() + "_emission") emission = m.get_nodes_with_type("Emission") if not emission: if mat_name in light[0]: # If the material corresponds to light bulb emission_strength = lightbulb_emission_strength else: # If the material corresponds to a lampshade emission_strength = lampshade_emission_strength m.make_emissive(emission_strength, emission_color=m.blender_obj.diffuse_color) collection_of_mats["lamp"][old_mat_name] = m
[docs] @staticmethod def make_window_emissive(obj: MeshObject, collection_of_mats: Dict[str, Dict[str, Material]]): """ Makes the given window object emissive. For each material with alpha < 1. Uses a light path node to make it emit light, but at the same time look like a principle material. Otherwise windows would be completely white. :param obj: A window object. :param collection_of_mats: A dictionary that contains materials for lamps, windows and ceilings. """ for i, m in enumerate(obj.get_materials()): if m is None: continue # All parameters imported from the .mtl file are stored inside the principled bsdf node principled_node = m.get_the_one_node_with_type("BsdfPrincipled") alpha = principled_node.inputs['Alpha'].default_value if alpha < 1: mat_name = m.get_name() if mat_name in collection_of_mats["window"]: # this material was used as a ceiling before use that one obj.set_material(i, collection_of_mats["window"][mat_name]) continue # copy the material if more than one user is using it if m.get_users() > 1: m = m.duplicate() obj.set_material(i, m) # rename the material m.set_name(m.get_name() + "_emission") if not m.get_nodes_with_type('Emission'): transparent_node = m.new_node('ShaderNodeBsdfDiffuse') transparent_node.inputs['Color'].default_value[:3] = (0.285, 0.5, 0.48) m.make_emissive(emission_strength=10, emission_color=[1, 1, 1, 1], non_emissive_color_socket=transparent_node.outputs['BSDF']) collection_of_mats["window"][mat_name] = m
[docs] @staticmethod def make_ceiling_emissive(obj: MeshObject, collection_of_mats: Dict[str, Dict[str, Material]], ceiling_emission_strength: float = 1.5): """ Makes the given ceiling object emissive, s.t. there is always a little bit ambient light. :param obj: The ceiling object. :param collection_of_mats: A dictionary that contains materials for lamps, windows and ceilings. :param ceiling_emission_strength: The emission strength that should be used for the ceiling. Default: 1.5 """ for i, material in enumerate(obj.get_materials()): if material is None: continue mat_name = material.get_name() if mat_name in collection_of_mats["ceiling"]: # this material was used as a ceiling before use that one obj.set_material(i, collection_of_mats["ceiling"][mat_name]) continue # copy the material if more than one user is using it if material.get_users() > 1: material = material.duplicate() obj.set_material(i, material) # rename the material material.set_name(material.get_name() + "_emission") if not material.get_nodes_with_type("Emission") and material.get_nodes_with_type("BsdfPrincipled"): material.make_emissive(emission_strength=ceiling_emission_strength, emission_color=[1, 1, 1, 1]) collection_of_mats["ceiling"][mat_name] = material