io_scene_3ds: Update for Principled BSDF specularity #104917
35
hydra_storm/__init__.py
Normal file
35
hydra_storm/__init__.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
# Copyright 2011-2022 Blender Foundation
|
||||||
|
|
||||||
|
# <pep8 compliant>
|
||||||
|
|
||||||
|
|
||||||
|
bl_info = {
|
||||||
|
"name": "Hydra Storm render engine",
|
||||||
|
"author": "AMD",
|
||||||
|
"version": (1, 0, 0),
|
||||||
|
"blender": (4, 0, 0),
|
||||||
|
"description": "USD's high performance rasterizing renderer",
|
||||||
|
"tracker_url": "",
|
||||||
|
"doc_url": "",
|
||||||
|
"community": "",
|
||||||
|
"downloads": "",
|
||||||
|
"main_web": "",
|
||||||
|
"support": 'OFFICIAL',
|
||||||
|
"category": "Render"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
from . import engine, properties, ui
|
||||||
|
|
||||||
|
|
||||||
|
def register():
|
||||||
|
engine.register()
|
||||||
|
properties.register()
|
||||||
|
ui.register()
|
||||||
|
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
ui.unregister()
|
||||||
|
properties.unregister()
|
||||||
|
engine.unregister()
|
44
hydra_storm/engine.py
Normal file
44
hydra_storm/engine.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
# Copyright 2011-2022 Blender Foundation
|
||||||
|
|
||||||
|
# <pep8 compliant>
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
class StormHydraRenderEngine(bpy.types.HydraRenderEngine):
|
||||||
|
bl_idname = 'HYDRA_STORM'
|
||||||
|
bl_label = "Hydra Storm"
|
||||||
|
bl_info = "USD's high performance rasterizing renderer"
|
||||||
|
|
||||||
|
bl_use_preview = True
|
||||||
|
bl_use_gpu_context = True
|
||||||
|
|
||||||
|
bl_delegate_id = 'HdStormRendererPlugin'
|
||||||
|
|
||||||
|
def get_render_settings(self, engine_type):
|
||||||
|
settings = bpy.context.scene.hydra_storm.viewport if engine_type == 'VIEWPORT' else \
|
||||||
|
bpy.context.scene.hydra_storm.final
|
||||||
|
result = {
|
||||||
|
'enableTinyPrimCulling': settings.enable_tiny_prim_culling,
|
||||||
|
'volumeRaymarchingStepSize': settings.volume_raymarching_step_size,
|
||||||
|
'volumeRaymarchingStepSizeLighting': settings.volume_raymarching_step_size_lighting,
|
||||||
|
'volumeMaxTextureMemoryPerField': settings.volume_max_texture_memory_per_field,
|
||||||
|
'maxLights': settings.max_lights,
|
||||||
|
}
|
||||||
|
|
||||||
|
if engine_type != 'VIEWPORT':
|
||||||
|
result |= {
|
||||||
|
'aovToken:Combined': "color",
|
||||||
|
'aovToken:Depth': "depth",
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def update_render_passes(self, scene, render_layer):
|
||||||
|
if render_layer.use_pass_z:
|
||||||
|
self.register_pass(scene, render_layer, 'Depth', 1, 'Z', 'VALUE')
|
||||||
|
|
||||||
|
|
||||||
|
register, unregister = bpy.utils.register_classes_factory((
|
||||||
|
StormHydraRenderEngine,
|
||||||
|
))
|
63
hydra_storm/properties.py
Normal file
63
hydra_storm/properties.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
# Copyright 2011-2022 Blender Foundation
|
||||||
|
|
||||||
|
# <pep8 compliant>
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
|
||||||
|
class Properties(bpy.types.PropertyGroup):
|
||||||
|
type = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def register(cls):
|
||||||
|
cls.type.hydra_storm = bpy.props.PointerProperty(
|
||||||
|
name="Hydra Storm",
|
||||||
|
description="Hydra Storm properties",
|
||||||
|
type=cls,
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def unregister(cls):
|
||||||
|
del cls.type.hydra_storm
|
||||||
|
|
||||||
|
|
||||||
|
class RenderProperties(bpy.types.PropertyGroup):
|
||||||
|
enable_tiny_prim_culling: bpy.props.BoolProperty(
|
||||||
|
name="Tiny Prim Culling",
|
||||||
|
description="Enable Tiny Prim Culling",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
volume_raymarching_step_size: bpy.props.FloatProperty(
|
||||||
|
name="Volume Raymarching Step Size",
|
||||||
|
description="Step size when raymarching volume",
|
||||||
|
default=1.0,
|
||||||
|
)
|
||||||
|
volume_raymarching_step_size_lighting: bpy.props.FloatProperty(
|
||||||
|
name="Volume Raymarching Step Size Lighting",
|
||||||
|
description="Step size when raymarching volume for lighting computation",
|
||||||
|
default=10.0,
|
||||||
|
)
|
||||||
|
volume_max_texture_memory_per_field: bpy.props.FloatProperty(
|
||||||
|
name="Max Texture Memory Per Field",
|
||||||
|
description="Maximum memory for a volume field texture in Mb (unless overridden by field prim)",
|
||||||
|
default=128.0,
|
||||||
|
)
|
||||||
|
max_lights: bpy.props.IntProperty(
|
||||||
|
name="Max Lights",
|
||||||
|
description="Limit maximum number of lights",
|
||||||
|
default=16, min=0, max=16,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SceneProperties(Properties):
|
||||||
|
type = bpy.types.Scene
|
||||||
|
|
||||||
|
final: bpy.props.PointerProperty(type=RenderProperties)
|
||||||
|
viewport: bpy.props.PointerProperty(type=RenderProperties)
|
||||||
|
|
||||||
|
|
||||||
|
register, unregister = bpy.utils.register_classes_factory((
|
||||||
|
RenderProperties,
|
||||||
|
SceneProperties,
|
||||||
|
))
|
243
hydra_storm/ui.py
Normal file
243
hydra_storm/ui.py
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
# Copyright 2011-2022 Blender Foundation
|
||||||
|
|
||||||
|
# <pep8 compliant>
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
from .engine import StormHydraRenderEngine
|
||||||
|
|
||||||
|
|
||||||
|
class Panel(bpy.types.Panel):
|
||||||
|
bl_space_type = 'PROPERTIES'
|
||||||
|
bl_region_type = 'WINDOW'
|
||||||
|
bl_context = 'render'
|
||||||
|
COMPAT_ENGINES = {StormHydraRenderEngine.bl_idname}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return context.engine in cls.COMPAT_ENGINES
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Final render settings
|
||||||
|
#
|
||||||
|
class STORM_HYDRA_RENDER_PT_final(Panel):
|
||||||
|
"""Final render delegate and settings"""
|
||||||
|
bl_idname = 'STORM_HYDRA_RENDER_PT_final'
|
||||||
|
bl_label = "Final Render Settings"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.use_property_split = True
|
||||||
|
layout.use_property_decorate = False
|
||||||
|
|
||||||
|
settings = context.scene.hydra_storm.final
|
||||||
|
layout.prop(settings, 'enable_tiny_prim_culling')
|
||||||
|
layout.prop(settings, 'max_lights')
|
||||||
|
|
||||||
|
|
||||||
|
class STORM_HYDRA_RENDER_PT_volume_final(bpy.types.Panel):
|
||||||
|
bl_parent_id = STORM_HYDRA_RENDER_PT_final.bl_idname
|
||||||
|
bl_label = "Volume Raymarching"
|
||||||
|
bl_space_type = 'PROPERTIES'
|
||||||
|
bl_region_type = 'WINDOW'
|
||||||
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.use_property_split = True
|
||||||
|
layout.use_property_decorate = False
|
||||||
|
|
||||||
|
settings = context.scene.hydra_storm.final
|
||||||
|
|
||||||
|
col = layout.column(align=True)
|
||||||
|
col.prop(settings, "volume_raymarching_step_size", text="Step Size")
|
||||||
|
col.prop(settings, "volume_raymarching_step_size_lighting", text="Step Size Lightning")
|
||||||
|
col.prop(settings, "volume_max_texture_memory_per_field")
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Viewport render settings
|
||||||
|
#
|
||||||
|
class STORM_HYDRA_RENDER_PT_viewport(Panel):
|
||||||
|
"""Viewport render delegate and settings"""
|
||||||
|
bl_idname = 'STORM_HYDRA_RENDER_PT_viewport'
|
||||||
|
bl_label = "Viewport Render Settings"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.use_property_split = True
|
||||||
|
layout.use_property_decorate = False
|
||||||
|
|
||||||
|
settings = context.scene.hydra_storm.viewport
|
||||||
|
layout.prop(settings, 'enable_tiny_prim_culling')
|
||||||
|
layout.prop(settings, 'max_lights')
|
||||||
|
|
||||||
|
|
||||||
|
class STORM_HYDRA_RENDER_PT_volume_viewport(bpy.types.Panel):
|
||||||
|
bl_parent_id = STORM_HYDRA_RENDER_PT_viewport.bl_idname
|
||||||
|
bl_label = "Volume Raymarching"
|
||||||
|
bl_space_type = 'PROPERTIES'
|
||||||
|
bl_region_type = 'WINDOW'
|
||||||
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.use_property_split = True
|
||||||
|
layout.use_property_decorate = False
|
||||||
|
|
||||||
|
settings = context.scene.hydra_storm.viewport
|
||||||
|
|
||||||
|
col = layout.column(align=True)
|
||||||
|
col.prop(settings, "volume_raymarching_step_size", text="Step Size")
|
||||||
|
col.prop(settings, "volume_raymarching_step_size_lighting", text="Step Size Lightning")
|
||||||
|
col.prop(settings, "volume_max_texture_memory_per_field")
|
||||||
|
|
||||||
|
|
||||||
|
class STORM_HYDRA_LIGHT_PT_light(Panel):
|
||||||
|
"""Physical light sources"""
|
||||||
|
bl_label = "Light"
|
||||||
|
bl_context = 'data'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return super().poll(context) and context.light
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
|
||||||
|
light = context.light
|
||||||
|
|
||||||
|
layout.prop(light, "type", expand=True)
|
||||||
|
|
||||||
|
layout.use_property_split = True
|
||||||
|
layout.use_property_decorate = False
|
||||||
|
|
||||||
|
main_col = layout.column()
|
||||||
|
|
||||||
|
main_col.prop(light, "color")
|
||||||
|
main_col.prop(light, "energy")
|
||||||
|
main_col.separator()
|
||||||
|
|
||||||
|
if light.type == 'POINT':
|
||||||
|
row = main_col.row(align=True)
|
||||||
|
row.prop(light, "shadow_soft_size", text="Radius")
|
||||||
|
|
||||||
|
elif light.type == 'SPOT':
|
||||||
|
col = main_col.column(align=True)
|
||||||
|
col.prop(light, 'spot_size', slider=True)
|
||||||
|
col.prop(light, 'spot_blend', slider=True)
|
||||||
|
|
||||||
|
main_col.prop(light, 'show_cone')
|
||||||
|
|
||||||
|
elif light.type == 'SUN':
|
||||||
|
main_col.prop(light, "angle")
|
||||||
|
|
||||||
|
elif light.type == 'AREA':
|
||||||
|
main_col.prop(light, "shape", text="Shape")
|
||||||
|
sub = main_col.column(align=True)
|
||||||
|
|
||||||
|
if light.shape in {'SQUARE', 'DISK'}:
|
||||||
|
sub.prop(light, "size")
|
||||||
|
elif light.shape in {'RECTANGLE', 'ELLIPSE'}:
|
||||||
|
sub.prop(light, "size", text="Size X")
|
||||||
|
sub.prop(light, "size_y", text="Y")
|
||||||
|
|
||||||
|
else:
|
||||||
|
main_col.prop(light, 'size')
|
||||||
|
|
||||||
|
|
||||||
|
class STORM_HYDRA_RENDER_PT_film(Panel):
|
||||||
|
bl_label = "Film"
|
||||||
|
bl_space_type = 'PROPERTIES'
|
||||||
|
bl_region_type = 'WINDOW'
|
||||||
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.use_property_split = True
|
||||||
|
layout.use_property_decorate = False
|
||||||
|
|
||||||
|
layout.prop(context.scene.render, "film_transparent", text="Transparent Background")
|
||||||
|
|
||||||
|
|
||||||
|
class STORM_HYDRA_RENDER_PT_passes(Panel):
|
||||||
|
bl_label = "Passes"
|
||||||
|
bl_context = "view_layer"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class STORM_HYDRA_RENDER_PT_passes_data(Panel):
|
||||||
|
bl_label = "Data"
|
||||||
|
bl_context = "view_layer"
|
||||||
|
bl_parent_id = "STORM_HYDRA_RENDER_PT_passes"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.use_property_split = True
|
||||||
|
layout.use_property_decorate = False
|
||||||
|
|
||||||
|
view_layer = context.view_layer
|
||||||
|
|
||||||
|
col = layout.column(heading="Include", align=True)
|
||||||
|
col.prop(view_layer, "use_pass_z")
|
||||||
|
|
||||||
|
|
||||||
|
register_classes, unregister_classes = bpy.utils.register_classes_factory((
|
||||||
|
STORM_HYDRA_RENDER_PT_final,
|
||||||
|
STORM_HYDRA_RENDER_PT_volume_final,
|
||||||
|
STORM_HYDRA_RENDER_PT_viewport,
|
||||||
|
STORM_HYDRA_RENDER_PT_volume_viewport,
|
||||||
|
STORM_HYDRA_RENDER_PT_film,
|
||||||
|
STORM_HYDRA_LIGHT_PT_light,
|
||||||
|
STORM_HYDRA_RENDER_PT_passes,
|
||||||
|
STORM_HYDRA_RENDER_PT_passes_data,
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
def get_panels():
|
||||||
|
# Follow the Cycles model of excluding panels we don't want.
|
||||||
|
exclude_panels = {
|
||||||
|
'RENDER_PT_stamp',
|
||||||
|
'DATA_PT_light',
|
||||||
|
'DATA_PT_spot',
|
||||||
|
'NODE_DATA_PT_light',
|
||||||
|
'DATA_PT_falloff_curve',
|
||||||
|
'RENDER_PT_post_processing',
|
||||||
|
'RENDER_PT_simplify',
|
||||||
|
'SCENE_PT_audio',
|
||||||
|
'RENDER_PT_freestyle'
|
||||||
|
}
|
||||||
|
include_eevee_panels = {
|
||||||
|
'MATERIAL_PT_preview',
|
||||||
|
'EEVEE_MATERIAL_PT_context_material',
|
||||||
|
'EEVEE_MATERIAL_PT_surface',
|
||||||
|
'EEVEE_MATERIAL_PT_volume',
|
||||||
|
'EEVEE_MATERIAL_PT_settings',
|
||||||
|
'EEVEE_WORLD_PT_surface',
|
||||||
|
}
|
||||||
|
|
||||||
|
for panel_cls in bpy.types.Panel.__subclasses__():
|
||||||
|
if hasattr(panel_cls, 'COMPAT_ENGINES') and (
|
||||||
|
('BLENDER_RENDER' in panel_cls.COMPAT_ENGINES and panel_cls.__name__ not in exclude_panels) or
|
||||||
|
('BLENDER_EEVEE' in panel_cls.COMPAT_ENGINES and panel_cls.__name__ in include_eevee_panels)
|
||||||
|
):
|
||||||
|
yield panel_cls
|
||||||
|
|
||||||
|
|
||||||
|
def register():
|
||||||
|
register_classes()
|
||||||
|
|
||||||
|
for panel_cls in get_panels():
|
||||||
|
panel_cls.COMPAT_ENGINES.add(StormHydraRenderEngine.bl_idname)
|
||||||
|
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
unregister_classes()
|
||||||
|
|
||||||
|
for panel_cls in get_panels():
|
||||||
|
if StormHydraRenderEngine.bl_idname in panel_cls.COMPAT_ENGINES:
|
||||||
|
panel_cls.COMPAT_ENGINES.remove(StormHydraRenderEngine.bl_idname)
|
@ -12,6 +12,7 @@ from bpy.types import (
|
|||||||
Context,
|
Context,
|
||||||
Menu,
|
Menu,
|
||||||
Panel,
|
Panel,
|
||||||
|
UILayout,
|
||||||
UIList,
|
UIList,
|
||||||
WindowManager,
|
WindowManager,
|
||||||
WorkSpace,
|
WorkSpace,
|
||||||
@ -29,12 +30,54 @@ class PoseLibraryPanel:
|
|||||||
return cls.pose_library_panel_poll(context)
|
return cls.pose_library_panel_poll(context)
|
||||||
|
|
||||||
|
|
||||||
|
class VIEW3D_AST_pose_library(bpy.types.AssetShelf):
|
||||||
|
bl_space_type = "VIEW_3D"
|
||||||
|
# We have own keymap items to add custom drag behavior (pose blending), disable the default
|
||||||
|
# asset dragging.
|
||||||
|
bl_options = {'NO_ASSET_DRAG'}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context: Context) -> bool:
|
||||||
|
return PoseLibraryPanel.poll(context)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def asset_poll(cls, asset: AssetHandle) -> bool:
|
||||||
|
return asset.file_data.id_type == 'ACTION'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def draw_context_menu(cls, _context: Context, _asset: AssetHandle, layout: UILayout):
|
||||||
|
# Make sure these operator properties match those used in `VIEW3D_PT_pose_library`.
|
||||||
|
layout.operator("poselib.apply_pose_asset", text="Apply Pose").flipped = False
|
||||||
|
layout.operator("poselib.apply_pose_asset", text="Apply Pose Flipped").flipped = True
|
||||||
|
|
||||||
|
with operator_context(layout, 'INVOKE_DEFAULT'):
|
||||||
|
layout.operator("poselib.blend_pose_asset", text="Blend Pose")
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
props = layout.operator("poselib.pose_asset_select_bones", text="Select Pose Bones")
|
||||||
|
props.select = True
|
||||||
|
props = layout.operator("poselib.pose_asset_select_bones", text="Deselect Pose Bones")
|
||||||
|
props.select = False
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
layout.operator("asset.open_containing_blend_file")
|
||||||
|
|
||||||
|
|
||||||
class VIEW3D_PT_pose_library(PoseLibraryPanel, Panel):
|
class VIEW3D_PT_pose_library(PoseLibraryPanel, Panel):
|
||||||
bl_space_type = "VIEW_3D"
|
bl_space_type = "VIEW_3D"
|
||||||
bl_region_type = "UI"
|
bl_region_type = "UI"
|
||||||
bl_category = "Animation"
|
bl_category = "Animation"
|
||||||
bl_label = "Pose Library"
|
bl_label = "Pose Library"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context: Context) -> bool:
|
||||||
|
prefs = context.preferences
|
||||||
|
# Use Asset Shelf as UI instead of the old asset-view template in the sidebar.
|
||||||
|
if prefs.experimental.use_asset_shelf:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return PoseLibraryPanel.poll(context)
|
||||||
|
|
||||||
def draw(self, context: Context) -> None:
|
def draw(self, context: Context) -> None:
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
@ -194,6 +237,7 @@ classes = (
|
|||||||
DOPESHEET_PT_asset_panel,
|
DOPESHEET_PT_asset_panel,
|
||||||
VIEW3D_PT_pose_library,
|
VIEW3D_PT_pose_library,
|
||||||
ASSETBROWSER_MT_asset,
|
ASSETBROWSER_MT_asset,
|
||||||
|
VIEW3D_AST_pose_library,
|
||||||
)
|
)
|
||||||
|
|
||||||
_register, _unregister = bpy.utils.register_classes_factory(classes)
|
_register, _unregister = bpy.utils.register_classes_factory(classes)
|
||||||
|
@ -21,6 +21,15 @@ def register() -> None:
|
|||||||
kmi = km.keymap_items.new("poselib.apply_pose_asset", "LEFTMOUSE", "DOUBLE_CLICK")
|
kmi = km.keymap_items.new("poselib.apply_pose_asset", "LEFTMOUSE", "DOUBLE_CLICK")
|
||||||
addon_keymaps.append((km, kmi))
|
addon_keymaps.append((km, kmi))
|
||||||
|
|
||||||
|
# Asset Shelf
|
||||||
|
km = wm.keyconfigs.addon.keymaps.new(name="Asset Shelf")
|
||||||
|
# Click to apply pose.
|
||||||
|
kmi = km.keymap_items.new("poselib.apply_pose_asset", "LEFTMOUSE", "CLICK")
|
||||||
|
addon_keymaps.append((km, kmi))
|
||||||
|
# Drag to blend pose.
|
||||||
|
kmi = km.keymap_items.new("poselib.blend_pose_asset", "LEFTMOUSE", "CLICK_DRAG")
|
||||||
|
addon_keymaps.append((km, kmi))
|
||||||
|
|
||||||
|
|
||||||
def unregister() -> None:
|
def unregister() -> None:
|
||||||
# Clear shortcuts from the keymap.
|
# Clear shortcuts from the keymap.
|
||||||
|
Loading…
Reference in New Issue
Block a user