Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds material baking option to Addon #87

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion mitsuba-blender/io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
importlib.reload(exporter)

import bpy
import time
from bpy.props import (
StringProperty,
BoolProperty,
IntProperty,
)
from bpy_extras.io_utils import (
ImportHelper,
Expand Down Expand Up @@ -104,13 +106,46 @@ class ExportMitsuba(bpy.types.Operator, ExportHelper):
default = True
)

bake_materials: BoolProperty(
name = "Bake Materials",
description = "Bakes Materials into textures. Takes longer to export scenes. Make sure GPU is enabled in settings",
default = False
)
bake_mat_ids: BoolProperty(
name = "Unique Material IDs",
description = """If 'Bake Materials' is active bakes Materials with unique IDs.
Each object will have a unique material in final XML and will have correct blender representation.
Otherwise some materials are reused and textures may be inaccurate""",
default = False
)

bake_again: BoolProperty(
name = "Bake textures again",
description = """If 'Bake Materials' is active, this will bake the already existing textures if enabled.
This option allows to incrementally bake scene materials.""",
default = True
)

bake_res_x: IntProperty(
name = "Bake Resolution X",
description = "Resultion size of X coordinate in pixels. If \"Bake Materials\" is enabled will bake with this resolution",
default = 1024
)

bake_res_y: IntProperty(
name = "Bake Resolution Y",
description = "Resultion size of Y coordinate in pixels. If \"Bake Materials\" is enabled will bake with this resolution",
default = 1024
)

def __init__(self):
self.reset()

def reset(self):
self.converter = exporter.SceneConverter()

def execute(self, context):
start = time.time()
# Conversion matrix to shift the "Up" Vector. This can be useful when exporting single objects to an existing mitsuba scene.
axis_mat = axis_conversion(
to_forward=self.axis_forward,
Expand All @@ -122,6 +157,12 @@ def execute(self, context):
self.converter.export_ctx.export_ids = self.export_ids

self.converter.use_selection = self.use_selection
# Bake material feature options
self.converter.export_ctx.bake_materials = self.bake_materials
self.converter.export_ctx.bake_res_x = self.bake_res_x
self.converter.export_ctx.bake_res_y = self.bake_res_y
self.converter.export_ctx.bake_mat_ids = self.bake_mat_ids
self.converter.export_ctx.bake_again = self.bake_again

# Set path to scene .xml file
self.converter.set_path(self.filepath, split_files=self.split_files)
Expand All @@ -143,7 +184,8 @@ def execute(self, context):

#reset the exporter
self.reset()

end = time.time()
self.converter.export_ctx.log(f"Export took {end-start}")
return {'FINISHED'}


Expand Down
4 changes: 2 additions & 2 deletions mitsuba-blender/io/exporter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def scene_to_dict(self, depsgraph, window_manager):
for object_instance in depsgraph.object_instances:
window_manager.progress_update(progress_counter)
progress_counter += 1

if self.use_selection:
#skip if it's not selected or if it's an instance and the parent object is not selected
if not object_instance.is_instance and not object_instance.object.original.select_get():
Expand All @@ -93,7 +93,7 @@ def scene_to_dict(self, depsgraph, window_manager):
and evaluated_obj.parent and evaluated_obj.parent.original.hide_render):
self.export_ctx.log("Object: {} is hidden for render. Ignoring it.".format(evaluated_obj.name), 'INFO')
continue#ignore it since we don't want it rendered (TODO: hide_viewport)
if object_type in {'MESH', 'FONT', 'SURFACE', 'META'}:
if object_type in {'MESH', 'FONT', 'SURFACE', 'META'} and evaluated_obj.name in bpy.context.view_layer.objects:
geometry.export_object(object_instance, self.export_ctx, evaluated_obj.name in particles)
elif object_type == 'CAMERA':
# When rendering inside blender, export only the active camera
Expand Down
12 changes: 12 additions & 0 deletions mitsuba-blender/io/exporter/export_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ def __init__(self):
self.counter = 0 # Counter to create unique IDs.
self.exported_mats = ExportedMaterialsCache()
self.export_ids = False # Export Object IDs in the XML file
self.bake_materials = False
self.bake_res_x = 1024
self.bake_res_y = 1024
self.bake_mat_ids = False
self.bake_again = True
self.exported_ids = set()
# All the args defined below are set in the Converter
self.directory = ''
Expand Down Expand Up @@ -159,6 +164,13 @@ def export_texture(self, image):
image.filepath_raw = old_filepath
return f"{self.subfolders['texture']}/{name}"

def blackbody(self, value):
param = {
"type" : "blackbody",
"temperature" : value
}
return param

def spectrum(self, value, mode='rgb'):
'''
Given a spectrum value, format it for the scene dict.
Expand Down
15 changes: 8 additions & 7 deletions mitsuba-blender/io/exporter/geometry.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import os
import bpy

from .materials import export_material
from .export_context import Files


def convert_mesh(export_ctx, b_mesh, matrix_world, name, mat_nr):
'''
This method creates a mitsuba mesh from a blender mesh and returns it.
Expand Down Expand Up @@ -104,10 +102,9 @@ def export_object(deg_instance, export_ctx, is_particle):
# Remove spurious characters such as slashes
name_clean = bpy.path.clean_name(b_object.name_full)
object_id = f"mesh-{name_clean}"

export_ctx.log(f"Exporting object {name_clean}")
is_instance_emitter = b_object.parent is not None and b_object.parent.is_instancer
is_instance = deg_instance.is_instance

# Only write to file objects that have never been exported before
if export_ctx.data_get(object_id) is None:
if b_object.type == 'MESH':
Expand All @@ -123,7 +120,6 @@ def export_object(deg_instance, export_ctx, is_particle):
else:
transform = b_object.matrix_world


if mat_count == 0: # No assigned material
converted_parts.append((
name_clean,
Expand Down Expand Up @@ -156,7 +152,7 @@ def export_object(deg_instance, export_ctx, is_particle):

if n_mat_refs == 0:
# Only export this material once
export_material(export_ctx, mat)
export_material(export_ctx, b_mesh.materials[mat_nr], b_object.name)

if b_object.type != 'MESH':
b_object.to_mesh_clear()
Expand Down Expand Up @@ -201,7 +197,12 @@ def export_object(deg_instance, export_ctx, is_particle):
export_ctx.data_add(default_bsdf)
params['bsdf'] = {'type':'ref', 'id':'default-bsdf'}
else:
mat_id = f"mat-{b_object.data.materials[mat_nr].name}"
# For each object to have a unique material to prevent inaccurate textures
# We must ID all the objects in a unique way.
if export_ctx.bake_materials and export_ctx.bake_mat_ids:
mat_id = f"{name_clean}-{b_object.data.materials[mat_nr].name}"
else:
mat_id = f"mat-{b_object.data.materials[mat_nr].name}"
if export_ctx.exported_mats.has_mat(mat_id): # Add one emitter *and* one bsdf
mixed_mat = export_ctx.exported_mats.mats[mat_id]
params['bsdf'] = {'type':'ref', 'id':mixed_mat['bsdf']}
Expand Down
Loading
Loading