feat: boost render speed
This commit is contained in:
Binary file not shown.
@@ -9,7 +9,8 @@ from uuid import uuid4
|
||||
|
||||
from ..nodes import custom_nodes
|
||||
from ..bioxel.layer import Layer
|
||||
from .utils import get_layer_prop_value, move_node_between_nodes
|
||||
from .utils import (get_layer_prop_value,
|
||||
move_node_between_nodes, add_direct_driver)
|
||||
|
||||
|
||||
def obj_to_layer(layer_obj: bpy.types.Object):
|
||||
@@ -135,9 +136,14 @@ def layer_to_obj(layer: Layer,
|
||||
cache_filepaths = [cache_filepath]
|
||||
|
||||
layer_data = bpy.data.volumes.new(layer_display_name)
|
||||
layer_data.render.space = 'WORLD'
|
||||
layer_data.render.step_size = container_obj.scale[0] * layer.bioxel_size[0]
|
||||
layer_data.sequence_mode = 'REPEAT'
|
||||
layer_data.filepath = str(cache_filepaths[0])
|
||||
|
||||
# add_direct_driver(layer_data, "render.step_size",
|
||||
# container_obj, "scale[0]")
|
||||
|
||||
if layer.frame_count > 1:
|
||||
layer_data.is_sequence = True
|
||||
layer_data.frame_duration = layer.frame_count
|
||||
@@ -145,7 +151,6 @@ def layer_to_obj(layer: Layer,
|
||||
layer_data.is_sequence = False
|
||||
|
||||
layer_obj = bpy.data.objects.new(layer_display_name, layer_data)
|
||||
|
||||
layer_obj['bioxel_layer'] = True
|
||||
|
||||
print(f"Creating Node for {layer.name}...")
|
||||
|
||||
@@ -94,3 +94,35 @@ def get_all_layer_objs():
|
||||
layer_objs.append(obj)
|
||||
|
||||
return layer_objs
|
||||
|
||||
def add_driver(target, target_prop, var_sources, expression):
|
||||
driver = target.driver_add(target_prop)
|
||||
is_vector = isinstance(driver, list)
|
||||
drivers = driver if is_vector else [driver]
|
||||
|
||||
for i, driver in enumerate(drivers):
|
||||
for j, var_source in enumerate(var_sources):
|
||||
|
||||
source = var_source['source']
|
||||
prop = var_source['prop']
|
||||
|
||||
var = driver.driver.variables.new()
|
||||
var.name = f"var{j}"
|
||||
|
||||
var.targets[0].id_type = source.id_type
|
||||
var.targets[0].id = source
|
||||
var.targets[0].data_path = f'["{prop}"][{i}]'\
|
||||
if is_vector else f'["{prop}"]'
|
||||
|
||||
driver.driver.expression = expression
|
||||
|
||||
|
||||
def add_direct_driver(target, target_prop, source, source_prop):
|
||||
drivers = [
|
||||
{
|
||||
"source": source,
|
||||
"prop": source_prop
|
||||
}
|
||||
]
|
||||
expression = "var0"
|
||||
add_driver(target, target_prop, drivers, expression)
|
||||
@@ -13,10 +13,10 @@ from .operators.layer import (FetchLayerMenu, FetchLayer,
|
||||
from .operators.container import (SaveAllLayerCaches, SaveContainer, LoadContainer,
|
||||
AddPieCutter, AddPlaneCutter,
|
||||
AddCylinderCutter, AddCubeCutter, AddSphereCutter,
|
||||
PickBboxWire, PickMesh, PickVolume)
|
||||
PickBboxWire, PickMesh, PickVolume, ScaleContainer)
|
||||
from .operators.io import (ImportAsLabel, ImportAsScalar, ImportAsColor)
|
||||
from .operators.misc import (CleanAllCaches,
|
||||
ReLinkNodes, RenderSettingPreset, SaveStagedData)
|
||||
ReLinkNodes, RenderSettingPreset, SaveStagedData, SliceViewer)
|
||||
|
||||
|
||||
class PickFromContainerMenu(bpy.types.Menu):
|
||||
@@ -156,19 +156,19 @@ class BioxelNodesNodeMenu(bpy.types.Menu):
|
||||
active_obj_name = ""
|
||||
|
||||
layout = self.layout
|
||||
|
||||
layout.separator()
|
||||
layout.menu(AddLayerMenu.bl_idname,
|
||||
icon=AddLayerMenu.bl_icon)
|
||||
|
||||
layout.operator(RemoveMissingLayers.bl_idname,
|
||||
icon=RemoveMissingLayers.bl_icon)
|
||||
|
||||
layout.separator()
|
||||
layout.operator(SaveContainer.bl_idname)
|
||||
layout.separator()
|
||||
layout.operator(ScaleContainer.bl_idname)
|
||||
layout.menu(AddCutterMenu.bl_idname)
|
||||
layout.menu(PickFromContainerMenu.bl_idname)
|
||||
layout.operator(SaveAllLayerCaches.bl_idname,
|
||||
icon=SaveAllLayerCaches.bl_icon)
|
||||
layout.operator(RemoveMissingLayers.bl_idname,
|
||||
icon=RemoveMissingLayers.bl_icon)
|
||||
|
||||
layout.separator()
|
||||
layout.menu(FetchLayerMenu.bl_idname)
|
||||
@@ -247,6 +247,8 @@ def NODE_PT(self, context):
|
||||
sidebar.menu(AddLayerMenu.bl_idname,
|
||||
icon=AddLayerMenu.bl_icon, text="")
|
||||
|
||||
sidebar.operator(SaveAllLayerCaches.bl_idname,
|
||||
icon=SaveAllLayerCaches.bl_icon, text="")
|
||||
sidebar.operator(RemoveMissingLayers.bl_idname,
|
||||
icon=RemoveMissingLayers.bl_icon, text="")
|
||||
|
||||
@@ -285,13 +287,21 @@ def NODE_PT(self, context):
|
||||
layout.separator()
|
||||
|
||||
|
||||
def VIEW3D_TOPBAR(self, context):
|
||||
layout = self.layout
|
||||
layout.operator(SliceViewer.bl_idname,
|
||||
icon=SliceViewer.bl_icon, text="")
|
||||
|
||||
|
||||
def add():
|
||||
bpy.types.VIEW3D_HT_header.append(VIEW3D_TOPBAR)
|
||||
bpy.types.NODE_PT_node_tree_properties.prepend(NODE_PT)
|
||||
bpy.types.TOPBAR_MT_editor_menus.append(TOPBAR)
|
||||
bpy.types.NODE_MT_editor_menus.append(NODE)
|
||||
|
||||
|
||||
def remove():
|
||||
bpy.types.VIEW3D_HT_header.remove(VIEW3D_TOPBAR)
|
||||
bpy.types.NODE_PT_node_tree_properties.remove(NODE_PT)
|
||||
bpy.types.TOPBAR_MT_editor_menus.remove(TOPBAR)
|
||||
bpy.types.NODE_MT_editor_menus.remove(NODE)
|
||||
|
||||
@@ -60,9 +60,9 @@ MENU_ITEMS = [
|
||||
'node_description': ''
|
||||
},
|
||||
{
|
||||
'label': 'Set Color by Layer',
|
||||
'label': 'Set Color by Color',
|
||||
'icon': 'IPO_QUINT',
|
||||
'node_type': 'BioxelNodes_SetColorByLayer',
|
||||
'node_type': 'BioxelNodes_SetColorByColor',
|
||||
'node_description': ''
|
||||
},
|
||||
{
|
||||
|
||||
@@ -6,7 +6,8 @@ from ..nodes import custom_nodes
|
||||
from ..customnodes.nodes import AddCustomNode
|
||||
from ..bioxel.io import load_container, save_container
|
||||
from ..bioxelutils.container import container_to_obj, obj_to_container
|
||||
from ..bioxelutils.utils import (get_container_layer_objs, get_container_obj, get_nodes_by_type,
|
||||
from ..bioxelutils.utils import (get_container_layer_objs, get_container_obj,
|
||||
get_layer_prop_value, get_nodes_by_type,
|
||||
move_node_between_nodes,
|
||||
move_node_to_node,
|
||||
get_all_layer_objs)
|
||||
@@ -66,7 +67,8 @@ class LoadContainer(bpy.types.Operator):
|
||||
select_object(container_obj)
|
||||
|
||||
if is_first_import:
|
||||
change_render_setting(context)
|
||||
bpy.ops.bioxelnodes.render_setting_preset('EXEC_DEFAULT',
|
||||
preset="preview_c")
|
||||
|
||||
self.report({"INFO"}, f"Successfully load {load_path}")
|
||||
return {'FINISHED'}
|
||||
@@ -158,14 +160,24 @@ class AddCutter():
|
||||
bpy.ops.mesh.primitive_ico_sphere_add(
|
||||
radius=1, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
|
||||
elif self.cutter_type == "pie":
|
||||
bpy.ops.mesh.primitive_plane_add(
|
||||
size=2, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
|
||||
pie = bpy.context.active_object
|
||||
pie.name = "Pie"
|
||||
orig_data = pie.data
|
||||
|
||||
# Create mesh
|
||||
pie_mesh = bpy.data.meshes.new('Pie')
|
||||
|
||||
# Create object
|
||||
pie = bpy.data.objects.new('Pie', pie_mesh)
|
||||
pie.data = pie_mesh
|
||||
bpy.data.meshes.remove(orig_data)
|
||||
|
||||
# # Create object
|
||||
# pie = bpy.data.objects.new('Pie', pie_mesh)
|
||||
|
||||
# # Link object to scene
|
||||
# bpy.context.scene.collection.objects.link(pie)
|
||||
|
||||
# Link object to scene
|
||||
bpy.context.scene.collection.objects.link(pie)
|
||||
# Get a BMesh representation
|
||||
bm = bmesh.new() # create an empty BMesh
|
||||
bm.from_mesh(pie_mesh) # fill it in from a Mesh
|
||||
@@ -189,7 +201,7 @@ class AddCutter():
|
||||
|
||||
# Finish up, write the bmesh back to the mesh
|
||||
bm.to_mesh(pie_mesh)
|
||||
bpy.context.view_layer.objects.active = pie
|
||||
# bpy.context.view_layer.objects.active = pie
|
||||
|
||||
cutter_obj = bpy.context.active_object
|
||||
cutter_obj.location = container_obj.location
|
||||
@@ -325,6 +337,46 @@ class AddPieCutter(bpy.types.Operator, AddCutter):
|
||||
cutter_type = "pie"
|
||||
|
||||
|
||||
class ScaleContainer(bpy.types.Operator):
|
||||
bl_idname = "bioxelnodes.scale_container"
|
||||
bl_label = "Scale Container"
|
||||
bl_description = "Scale Container."
|
||||
bl_icon = "FILE_TICK"
|
||||
|
||||
scene_scale: bpy.props.FloatProperty(name="Scene Scale",
|
||||
soft_min=0.0001, soft_max=10.0,
|
||||
min=1e-6, max=1e6,
|
||||
default=0.01) # type: ignore
|
||||
|
||||
def execute(self, context):
|
||||
container_obj = get_container_obj(context.object)
|
||||
|
||||
if container_obj is None:
|
||||
self.report({"WARNING"}, "Cannot find any bioxel container.")
|
||||
return {'FINISHED'}
|
||||
|
||||
container_obj.scale[0] = self.scene_scale
|
||||
container_obj.scale[1] = self.scene_scale
|
||||
container_obj.scale[2] = self.scene_scale
|
||||
|
||||
for layer_obj in get_container_layer_objs(container_obj):
|
||||
bioxel_size = get_layer_prop_value(layer_obj, "bioxel_size")
|
||||
layer_obj.data.render.step_size = self.scene_scale * bioxel_size
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
container_obj = get_container_obj(context.object)
|
||||
|
||||
if container_obj is None:
|
||||
return self.execute(context)
|
||||
else:
|
||||
self.scene_scale = container_obj.scale[0]
|
||||
context.window_manager.invoke_props_dialog(self,
|
||||
width=500)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
|
||||
class SaveAllLayerCaches(bpy.types.Operator):
|
||||
bl_idname = "bioxelnodes.save_all_layer_caches"
|
||||
bl_label = "Save All Layer Caches"
|
||||
|
||||
@@ -782,9 +782,8 @@ class ImportVolumetricDataDialog(bpy.types.Operator):
|
||||
# Change render setting for better result
|
||||
if is_first_import:
|
||||
bpy.ops.bioxelnodes.render_setting_preset('EXEC_DEFAULT',
|
||||
preset="slice_viewer")
|
||||
bpy.ops.bioxelnodes.render_setting_preset('EXEC_DEFAULT',
|
||||
preset="cycles_preview")
|
||||
preset="preview_c")
|
||||
# bpy.ops.bioxelnodes.slice_viewer('EXEC_DEFAULT')
|
||||
|
||||
self.report({"INFO"}, "Successfully Imported")
|
||||
return {'FINISHED'}
|
||||
|
||||
@@ -151,20 +151,19 @@ class RenderSettingPreset(bpy.types.Operator):
|
||||
bl_description = "Render Setting Preset"
|
||||
|
||||
PRESETS = {
|
||||
"slice_viewer": "Slice Viewer",
|
||||
"eevee_preview": "EEVEE Preview",
|
||||
"eevee_production": "EEVEE Production",
|
||||
"cycles_preview": "Cycles Preview",
|
||||
"cycles_production": "Cycles Production"
|
||||
"preview_e": "Preview (EEVEE)",
|
||||
"preview_c": "Preview (Cycles)",
|
||||
"production_e": "Production (EEVEE)",
|
||||
"production_c": "Production (Cycles)"
|
||||
}
|
||||
|
||||
preset: bpy.props.EnumProperty(name="Preset",
|
||||
default="eevee_preview",
|
||||
default="preview_c",
|
||||
items=[(k, v, "")
|
||||
for k, v in PRESETS.items()]) # type: ignore
|
||||
|
||||
def execute(self, context):
|
||||
if self.preset == "eevee_preview":
|
||||
if self.preset == "preview_e":
|
||||
bpy.context.scene.render.engine = 'BLENDER_EEVEE_NEXT'
|
||||
bpy.context.scene.eevee.use_taa_reprojection = False
|
||||
bpy.context.scene.eevee.taa_samples = 16
|
||||
@@ -174,7 +173,7 @@ class RenderSettingPreset(bpy.types.Operator):
|
||||
bpy.context.scene.eevee.volumetric_ray_depth = 16
|
||||
bpy.context.scene.eevee.use_volumetric_shadows = True
|
||||
|
||||
elif self.preset == "eevee_production":
|
||||
elif self.preset == "production_e":
|
||||
bpy.context.scene.render.engine = 'BLENDER_EEVEE_NEXT'
|
||||
bpy.context.scene.eevee.use_taa_reprojection = False
|
||||
bpy.context.scene.eevee.taa_samples = 16
|
||||
@@ -184,24 +183,31 @@ class RenderSettingPreset(bpy.types.Operator):
|
||||
bpy.context.scene.eevee.volumetric_ray_depth = 16
|
||||
bpy.context.scene.eevee.use_volumetric_shadows = True
|
||||
|
||||
elif self.preset == "cycles_preview":
|
||||
elif self.preset == "preview_c":
|
||||
bpy.context.scene.render.engine = 'CYCLES'
|
||||
bpy.context.scene.cycles.shading_system = True
|
||||
bpy.context.scene.cycles.volume_bounces = 12
|
||||
bpy.context.scene.cycles.transparent_max_bounces = 16
|
||||
bpy.context.scene.cycles.volume_preview_step_rate = 10
|
||||
bpy.context.scene.cycles.volume_step_rate = 10
|
||||
bpy.context.scene.cycles.volume_preview_step_rate = 1
|
||||
bpy.context.scene.cycles.volume_step_rate = 1
|
||||
|
||||
elif self.preset == "cycles_production":
|
||||
elif self.preset == "production_c":
|
||||
bpy.context.scene.render.engine = 'CYCLES'
|
||||
bpy.context.scene.cycles.shading_system = True
|
||||
bpy.context.scene.cycles.volume_bounces = 16
|
||||
bpy.context.scene.cycles.transparent_max_bounces = 32
|
||||
bpy.context.scene.cycles.volume_preview_step_rate = 1
|
||||
bpy.context.scene.cycles.volume_step_rate = 1
|
||||
bpy.context.scene.cycles.volume_preview_step_rate = 0.1
|
||||
bpy.context.scene.cycles.volume_step_rate = 0.1
|
||||
|
||||
elif self.preset == "slice_viewer":
|
||||
# bpy.context.scene.render.engine = 'BLENDER_EEVEE_NEXT'
|
||||
return {'FINISHED'}
|
||||
|
||||
class SliceViewer(bpy.types.Operator):
|
||||
bl_idname = "bioxelnodes.slice_viewer"
|
||||
bl_label = "Slice Viewer"
|
||||
bl_description = "Slice Viewer"
|
||||
bl_icon = "FILE_VOLUME"
|
||||
|
||||
def execute(self, context):
|
||||
bpy.context.scene.eevee.use_taa_reprojection = False
|
||||
bpy.context.scene.eevee.taa_samples = 4
|
||||
bpy.context.scene.eevee.volumetric_tile_size = '2'
|
||||
@@ -210,4 +216,13 @@ class RenderSettingPreset(bpy.types.Operator):
|
||||
bpy.context.scene.eevee.volumetric_ray_depth = 1
|
||||
bpy.context.scene.eevee.use_volumetric_shadows = False
|
||||
|
||||
for area in bpy.context.screen.areas:
|
||||
if area.type == 'VIEW_3D':
|
||||
area.spaces[0].shading.type = 'MATERIAL'
|
||||
area.spaces[0].shading.studio_light = 'studio.exr'
|
||||
area.spaces[0].shading.studiolight_intensity = 2.5
|
||||
area.spaces[0].shading.use_scene_lights = False
|
||||
area.spaces[0].shading.use_scene_world = False
|
||||
|
||||
|
||||
return {'FINISHED'}
|
||||
Reference in New Issue
Block a user