class_docstr: An implementation of a rendering backend in Blender/Cycles.
class_docstr_tok: ["An","implementation","of","a","rendering","backend","in","Blender\/Cycles","."]
code: def _add_asset(self, obj: core.FlatMaterial):
      # --- Create node-based material
      mat = bpy.data.materials.new("Holdout")
      mat.use_nodes = True
      tree = mat.node_tree
      tree.nodes.remove(
          tree.nodes["Principled BSDF"]
      )  # remove the default shader
  
      output_node = tree.nodes["Material Output"]
  
      # This material is constructed from three different shaders:
      #  1. if holdout=False then emission_node is responsible for giving the object a uniform color
      #  2. if holdout=True, then the holdout_node is responsible for making the object transparent
      #  3. if indirect_visibility=False then transparent_node makes the node invisible for indirect
      #     effects such as shadows or reflections
  
      light_path_node = tree.nodes.new(type="ShaderNodeLightPath")
      holdout_node = tree.nodes.new(type="ShaderNodeHoldout")
      transparent_node = tree.nodes.new(
          type="ShaderNodeBsdfTransparent"
      )
      holdout_mix_node = tree.nodes.new(type="ShaderNodeMixShader")
      indirect_mix_node = tree.nodes.new(type="ShaderNodeMixShader")
      overall_mix_node = tree.nodes.new(type="ShaderNodeMixShader")
  
      emission_node = tree.nodes.new(type="ShaderNodeEmission")
  
      tree.links.new(
          transparent_node.outputs["BSDF"], indirect_mix_node.inputs[1]
      )
      tree.links.new(
          emission_node.outputs["Emission"], indirect_mix_node.inputs[2]
      )
      tree.links.new(
          emission_node.outputs["Emission"], holdout_mix_node.inputs[1]
      )
      tree.links.new(
          holdout_node.outputs["Holdout"], holdout_mix_node.inputs[2]
      )
      tree.links.new(
          light_path_node.outputs["Is Camera Ray"],
          overall_mix_node.inputs["Fac"],
      )
      tree.links.new(
          indirect_mix_node.outputs["Shader"],
          overall_mix_node.inputs[1],
      )
      tree.links.new(
          holdout_mix_node.outputs["Shader"], overall_mix_node.inputs[2]
      )
      tree.links.new(
          overall_mix_node.outputs["Shader"],
          output_node.inputs["Surface"],
      )
  
      obj.observe(
          AttributeSetter(
              emission_node.inputs["Color"], "default_value"
          ),
          "color",
      )
      obj.observe(
          KeyframeSetter(
              emission_node.inputs["Color"], "default_value"
          ),
          "color",
          type="keyframe",
      )
      obj.observe(
          AttributeSetter(
              holdout_mix_node.inputs["Fac"], "default_value"
          ),
          "holdout",
      )
      obj.observe(
          KeyframeSetter(
              holdout_mix_node.inputs["Fac"], "default_value"
          ),
          "holdout",
          type="keyframe",
      )
      obj.observe(
          AttributeSetter(
              indirect_mix_node.inputs["Fac"], "default_value"
          ),
          "indirect_visibility",
      )
      obj.observe(
          KeyframeSetter(
              indirect_mix_node.inputs["Fac"], "default_value"
          ),
          "indirect_visibility",
          type="keyframe",
      )
      return mat
  
imports: import collections
  import io
  import logging
  import os
  import sys
  from contextlib import redirect_stdout
  from typing import Any, Dict, Optional, Sequence, Union
  import tempfile
  from kubric.safeimport.bpy import bpy
  import numpy
  import tensorflow
  from singledispatchmethod import singledispatchmethod
  import kubric
  from kubric import core
  from kubric.core.assets import UndefinedAsset
  from kubric.redirect_io import RedirectStream
  from kubric.renderer import blender_utils
  from kubric import file_io
  from kubric.file_io import PathLike
label_desc: Use image node_id 33 for calling the Blender obj's underlying member method code with example usage: obj._add_asset(obj) and returns: mat