Various Python integration changes #77

Closed
Brecht Van Lommel wants to merge 6 commits from brecht:hydra-python-changes into hydra-render

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
4 changed files with 145 additions and 121 deletions
Showing only changes of commit 47dfb1827a - Show all commits

View File

@ -0,0 +1,54 @@
"""
Base class for integrating USD Hydra based renderers.
USD Hydra Based Renderer
++++++++++++++++++++++++
"""
import bpy
class CustomHydraRenderEngine(bpy.types.HydraRenderEngine):
# Identifier and name in the user interface.
bl_idname = "CUSTOM_HYDRA_RENDERER"
bl_label = "Custom Hydra Renderer"
# Name of the render plugin.
bl_delegate_id = "HdCustomRendererPlugin"
# Register path to plugin.
@classmethod
def register(cls):
super().register()
import pxr
pxr.Plug.Registry().RegisterPlugins(['/path/to/plugin'])
# Render settings that will be passed to the delegate.
def get_render_settings(self, engine_type):
return {
'myBoolean': True,
'myValue': 8,
}
# Settings used by the synchronization process.
def get_sync_settings(self, engine_type):
return {
'MaterialXFilenameKey': "MaterialXFilename",
}
# RenderEngine methods for update, render and draw are implemented in
# HydraRenderEngine. Optionally extra work can be done before or after
# by implementing the methods like this.
def update(self, data, depsgraph):
super().update(data, depsgraph)
# Do extra work here
# Registration
def register():
bpy.utils.register_class(CustomHydraRenderEngine)
def unregister():
bpy.utils.unregister_class(CustomHydraRenderEngine)
if __name__ == "__main__":
register()

View File

@ -1,126 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-or-later
"""
Implementation of class `HydraRenderEngine`.
Render Blender addon with Hydra render delegate should inherit `HydraRenderEngine`.
Example:
```
import bpy_hydra
class CustomHydraRenderEngine(HydraRenderEngine):
bl_idname = 'CustomHydraRenderEngine'
bl_label = "Hydra: Custom"
bl_info = "Hydra Custom render delegate"
delegate_id = 'HdCustomRendererPlugin'
@classmethod
def register(cls):
super().register()
import pxr
pxr.Plug.Registry().RegisterPlugins(["/path/to/plugin")])
def get_sync_settings(self, engine_type):
return {
'MaterialXFilenameKey': "MaterialXFilename",
}
def get_render_settings(self, engine_type):
return {
'enableTinyPrimCulling': True,
'maxLights': 8,
}
```
"""
__all__ = (
"HydraRenderEngine",
"export_mtlx",
)
import os
import platform
from pathlib import Path
import bpy
import _bpy_hydra
class HydraRenderEngine(bpy.types.RenderEngine):
""" Render addon with Hydra render delegate should inherit this class """
bl_use_shading_nodes_custom = False
delegate_id = ''
engine_ptr = None
def __del__(self):
if not self.engine_ptr:
return
_bpy_hydra.engine_free(self.engine_ptr)
def get_sync_settings(self, engine_type):
"""
Provide settings for Blender scene delegate. Available settings:
`MaterialXFilenameKey` - if provided then MaterialX file will be provided directly to render delegate
without converting to HdMaterialNetwork
"""
return {}
def get_render_settings(self, engine_type):
"""
Provide render settings for render delegate. List of settings should be available in render delegate
documentation or in `pxr.UsdImagingGL.Engine.GetRendererSettingsList()`
"""
return {}
# final render
def update(self, data, depsgraph):
"""This function is preferable to override in child classes instead of update()"""
engine_type = 'PREVIEW' if self.is_preview else 'FINAL'
self.engine_ptr = _bpy_hydra.engine_create(self.as_pointer(), engine_type, self.delegate_id)
if not self.engine_ptr:
return
for key, val in self.get_sync_settings(engine_type).items():
_bpy_hydra.engine_set_sync_setting(self.engine_ptr, key, val)
_bpy_hydra.engine_update(self.engine_ptr, depsgraph.as_pointer(), None)
def render(self, depsgraph):
if not self.engine_ptr:
return
for key, val in self.get_render_settings('PREVIEW' if self.is_preview else 'FINAL').items():
_bpy_hydra.engine_set_render_setting(self.engine_ptr, key, val)
_bpy_hydra.engine_render(self.engine_ptr, depsgraph.as_pointer())
# viewport render
def view_update(self, context, depsgraph):
if not self.engine_ptr:
self.engine_ptr = _bpy_hydra.engine_create(self.as_pointer(), 'VIEWPORT', self.delegate_id)
if not self.engine_ptr:
return
for key, val in self.get_sync_settings('VIEWPORT').items():
_bpy_hydra.engine_set_sync_setting(self.engine_ptr, key, val)
_bpy_hydra.engine_update(self.engine_ptr, depsgraph.as_pointer(), context.as_pointer())
for key, val in self.get_render_settings('VIEWPORT').items():
_bpy_hydra.engine_set_render_setting(self.engine_ptr, key, val)
def view_draw(self, context, depsgraph):
if not self.engine_ptr:
return
_bpy_hydra.engine_view_draw(self.engine_ptr, depsgraph.as_pointer(), context.as_pointer())
def export_mtlx(material):
""" Exports material to .mtlx file. It is called from Blender source code. """
try:

View File

@ -935,10 +935,6 @@ class PropertyGroup(StructRNA, metaclass=RNAMetaPropGroup):
__slots__ = ()
class RenderEngine(StructRNA, metaclass=RNAMeta):
__slots__ = ()
class KeyingSetInfo(StructRNA, metaclass=RNAMeta):
__slots__ = ()
@ -1249,3 +1245,85 @@ class GeometryNode(NodeInternal):
@classmethod
def poll(cls, ntree):
return ntree.bl_idname == 'GeometryNodeTree'
class RenderEngine(StructRNA, metaclass=RNAMeta):
__slots__ = ()
class HydraRenderEngine(RenderEngine):
__slots__ = ()
bl_use_shading_nodes_custom = False
bl_delegate_id = 'HdStormRendererPlugin'
def __init__(self):
self.engine_ptr = None
def __del__(self):
if hasattr(self, 'engine_ptr'):
if self.engine_ptr:
import _bpy_hydra
_bpy_hydra.engine_free(self.engine_ptr)
def get_sync_settings(self, engine_type: str):
"""
Provide settings for Blender scene export. Available settings:
`MaterialXFilenameKey` - if provided then MaterialX file will be provided directly to render delegate
without converting to HdMaterialNetwork
"""
return {}
def get_render_settings(self, engine_type: str):
"""
Provide render settings for `HdRenderDelegate`.
"""
return {}
# Final render.
def update(self, data, depsgraph):
import _bpy_hydra
engine_type = 'PREVIEW' if self.is_preview else 'FINAL'
if not self.engine_ptr:
self.engine_ptr = _bpy_hydra.engine_create(self.as_pointer(), engine_type, self.bl_delegate_id)
if not self.engine_ptr:
return
for key, val in self.get_sync_settings(engine_type).items():
_bpy_hydra.engine_set_sync_setting(self.engine_ptr, key, val)
_bpy_hydra.engine_update(self.engine_ptr, depsgraph.as_pointer(), 0)
for key, val in self.get_render_settings('PREVIEW' if self.is_preview else 'FINAL').items():
_bpy_hydra.engine_set_render_setting(self.engine_ptr, key, val)
def render(self, depsgraph):
if not self.engine_ptr:
return
import _bpy_hydra
_bpy_hydra.engine_render(self.engine_ptr, depsgraph.as_pointer())
# Viewport render.
def view_update(self, context, depsgraph):
import _bpy_hydra
if not self.engine_ptr:
self.engine_ptr = _bpy_hydra.engine_create(self.as_pointer(), 'VIEWPORT', self.bl_delegate_id)
if not self.engine_ptr:
return
for key, val in self.get_sync_settings('VIEWPORT').items():
_bpy_hydra.engine_set_sync_setting(self.engine_ptr, key, val)
_bpy_hydra.engine_update(self.engine_ptr, depsgraph.as_pointer(), context.as_pointer())
for key, val in self.get_render_settings('VIEWPORT').items():
_bpy_hydra.engine_set_render_setting(self.engine_ptr, key, val)
def view_draw(self, context, depsgraph):
if not self.engine_ptr:
return
import _bpy_hydra
_bpy_hydra.engine_view_draw(self.engine_ptr, depsgraph.as_pointer(), context.as_pointer())

View File

@ -1007,6 +1007,14 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_define_verify_sdna(1);
}
static void rna_def_hydra_render_engine(BlenderRNA *brna)
{
/* This is implemented in Python. */
StructRNA *srna = RNA_def_struct(brna, "HydraRenderEngine", "RenderEngine");
RNA_def_struct_sdna(srna, "RenderEngine");
RNA_def_struct_ui_text(srna, "Hydra Render Engine", "Base class from USD Hydra based renderers");
}
static void rna_def_render_result(BlenderRNA *brna)
{
StructRNA *srna;
@ -1235,6 +1243,7 @@ static void rna_def_render_pass(BlenderRNA *brna)
void RNA_def_render(BlenderRNA *brna)
{
rna_def_render_engine(brna);
rna_def_hydra_render_engine(brna);
rna_def_render_result(brna);
rna_def_render_view(brna);
rna_def_render_layer(brna);