Page MenuHome
Paste P1622

(WIP) Disney PBR Extension (Principled) in Obj Export
ActivePublic

Authored by Alex Strand (astrand130) on Fri, Sep 4, 11:03 PM.
for mtl_mat_name, mat in mtl_dict_values:
# Get the Blender data for the material and the image.
# Having an image named None will make a bug, dont do it :)
fw('\nnewmtl %s\n' % mtl_mat_name) # Define a new material: matname_imgname
mat_wrap = node_shader_utils.PrincipledBSDFWrapper(mat) if mat else None
if mat_wrap: # PrincipledBSDF Material
use_mirror = mat_wrap.metallic != 0.0
use_alpha = mat_wrap.alpha != 1.0
use_transmission = mat_wrap.transmission != 0.0
use_transparency = use_alpha or use_transmission
use_subsurface = mat_wrap.subsurface != 0.0
# Base Color/Diffuse
tex_wrap = getattr(mat_wrap, "subsurface_color_texture", None) if use_subsurface else getattr(mat_wrap, "base_color_texture", None)
if tex_wrap is None or tex_wrap.image is None: # Solid base color
# when using subsurface the color is a subsurface color / base color lerp
base_color_final = Vector.lerp(Vector(mat_wrap.base_color[:3]), Vector(mat_wrap.subsurface_color[:3]), mat_wrap.subsurface)
fw('Kd %.6f %.6f %.6f\n' % tuple(base_color_final))
else: # Textured base color (treat as multiplier)
fw('Kd %.6f %.6f %.6f\n', (1.0, 1.0, 1.0))
# Specular F0
fw('Ks %.6f %.6f %.6f\n' % (mat_wrap.specular, mat_wrap.specular, mat_wrap.specular))
# Emission
# Not in original MTL standard but seems pretty common, see T45766.
tex_wrap = getattr(mat_wrap, "emission_color_texture", None)
if tex_wrap is None or tex_wrap.image is None: # Solid color emission
# Get final emission color multiplied by strength
emit_strength = mat_wrap.emission_strength
emit_final = mat_wrap.emission_color
emit_final.r *= emit_strength
emit_final.g *= emit_strength
emit_final.b *= emit_strength
fw('Ke %.6f %.6f %.6f\n' % tuple(emit_final))
else: # Textured emission (treat as multiplier)
fw('Ke %.6f %.6f %.6f\n' % (emit_strength, emit_strength, emit_strength))
# Transparency/Transmission/Subsurface
if use_alpha: # Using Alpha
fw('d %.6f\n' % mat_wrap.alpha) # Alpha (obj uses 'd' for dissolve)
elif use_transmission: # Using Transmission
fw('Tr %.6f\n' % mat_wrap.transmission) # Transmission (Inverse Opacity)
fw('Ni %.6f\n' % mat_wrap.ior) # Refraction index
fw('Tf %.6f %.6f %.6f\n' % (1.0, 1.0, 1.0)) # todo: Transmittance (is volume absorption)
elif use_subsurface: # Using Subsurface
# Multiply emission radius by strength for closer to expected result
sss_strength = mat_wrap.subsurface
sss_final = mat_wrap.subsurface_radius
sss_final.r *= sss_strength
sss_final.g *= sss_strength
sss_final.b *= sss_strength
fw('Tf %.6f %.6f %.6f\n' % tuple(sss_final)) # Transmittance (is subsurface radius)
# Disney PBR
# See http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr for Disney PBR extension as supported by modern importers such as tiny_obj...
fw('Pr %.6f\n' % mat_wrap.roughness) # Roughness extension
fw('Pm %.6f\n' % mat_wrap.metallic) # Metallic extension
fw('Ps %.6f\n' % mat_wrap.sheen) # Sheen extension
fw('Pc %.6f\n' % mat_wrap.clearcoat) # Clearcoat extension
fw('Pcr %.6f\n' % mat_wrap.clearcoat_roughness) # Clearcoat roughness extension
fw('aniso %.6f\n' % mat_wrap.anisotropic) # Anisotropic extension
fw('anisor %.6f\n' % mat_wrap.anisotropic_rotation) # Anisotropic rotation extension
# Illumination Model (legacy)
# Note that mapping is rather fuzzy sometimes, trying to do our best here.
# See http://en.wikipedia.org/wiki/Wavefront_.obj_file for whole list of values...
if mat_wrap.specular == 0:
fw('illum 1\n') # no specular.
elif use_mirror:
if use_transparency:
fw('illum 6\n') # Reflection, Transparency, Ray trace
else:
fw('illum 3\n') # Reflection and Ray trace
elif use_transparency:
fw('illum 9\n') # 'Glass' transparency and no Ray trace reflection... fuzzy matching, but...
else:
fw('illum 2\n') # Light normally
# Ambient (legacy)
if use_mirror:
fw('Ka %.6f %.6f %.6f\n' % (mat_wrap.metallic, mat_wrap.metallic, mat_wrap.metallic))
else:
fw('Ka %.6f %.6f %.6f\n' % (1.0, 1.0, 1.0))
# Specular Exponent (legacy)
# (Empirical conversion)
# (from 1.0 - 0.0 Principled BSDF range to 0.0 - 900.0 OBJ specular exponent range)...
spec_exponent = (1.0 - mat_wrap.roughness) * 30
spec_exponent *= spec_exponent
fw('Ns %.6f\n' % spec_exponent)
#Image Textures
image_map = {
"map_Kd": "base_color_texture", # Base color map
"map_Ka": None, # Ambient (legacy)
"map_Ks": "specular_texture", # Specular map
"map_Ns": None, # todo: Specular exponent map (gloss/inverse roughness) (legacy)
"map_d": "alpha_texture", # Opacity map (alpha)
"map_Tr": "transmission_texture", # Inverse opacity (transmission)
"map_Pr": "roughness_texture", # Roughness map extension
"map_Pm": "metallic_texture", # Metallic map extension
"map_Ps": "sheen_texture", # Sheen map extension
"map_Bump": None, # todo: Bump map (defined as a greyscale image, not normal)
"norm": "normalmap_texture", # Normal map extension
"disp": None, # todo: Displacement map
"refl": None, # Environment map (legacy)
"map_Ke": "emission_color_texture", # Emission map
}
for key, mat_wrap_key in sorted(image_map.items()):
if mat_wrap_key is None:
continue
tex_wrap = getattr(mat_wrap, mat_wrap_key, None)
if tex_wrap is None:
continue
image = tex_wrap.image
if image is None:
continue
filepath = io_utils.path_reference(image.filepath, source_dir, dest_dir,
path_mode, "", copy_set, image.library)
options = []
if key == "norm":
options.append('-bm %.6f' % mat_wrap.normalmap_strength)
if tex_wrap.translation != Vector((0.0, 0.0, 0.0)):
options.append('-o %.6f %.6f %.6f' % tex_wrap.translation[:])
if tex_wrap.scale != Vector((1.0, 1.0, 1.0)):
options.append('-s %.6f %.6f %.6f' % tex_wrap.scale[:])
if options:
fw('%s %s %s\n' % (key, " ".join(options), repr(filepath)[1:-1]))
else:
fw('%s %s\n' % (key, repr(filepath)[1:-1]))
else: # Fallback Material
fw('Kd 0.8 0.8 0.8\n') # Color
fw('Ks 0.5 0.5 0.5\n') # Specular F0
fw('Pr 0.4\n') # Roughness
fw('Pm 0.0\n') # Metal
fw('illum 2\n') # Illumination Model: Lit (legacy)
fw('Ka 0.0 0.0 0.0\n') # Ambient (legacy)
fw('Ns 225\n') # Specular Exponent (legacy)

Event Timeline

Alex Strand (astrand130) updated the paste's language from autodetect to python.Fri, Sep 4, 11:07 PM
Alex Strand (astrand130) changed the title of this paste from Disney PBR Extension (Principled) in Obj Export to (WIP) Disney PBR Extension (Principled) in Obj Export.Fri, Sep 4, 11:51 PM