Render: support USD Hydra render delegates

Hydra is a rendering architecture part of USD, designed to abstract the
host application from the renderer. A renderer implementing a Hydra
render delegate can run in any host application supporting Hydra, which
now includes Blender.

For external renderers this means less code to be written, and improved
performance due to a using a C++ API instead of a Python API.

Add-ons need to subclass bpy.types.HydraRenderEngine. See the example in
the Python API docs for details.

An add-on for Hydra Storm will be included as well. This is USD's
rasterizing renderer, used in other applications like usdview. For users
it can provide a preview of USD file export, and for developers it
serves a reference.

There are still limitations and missing features, especially around
materials. The remaining to do items are tracked in #110765.

This feature was contributed by AMD.

Ref #110765

Co-authored-by: Georgiy Markelov <georgiy.m.markelov@gmail.com>
Co-authored-by: Vasyl-Pidhirskyi <vpidhirskyi@gmail.com>
Co-authored-by: Brian Savery <brian.savery@gmail.com>
Co-authored-by: Brecht Van Lommel <brecht@blender.org>

Pull Request: https://projects.blender.org/blender/blender/pulls/104712
This commit is contained in:
Bogdan Nagirniak
2023-08-04 15:10:48 +02:00
committed by Brecht Van Lommel
parent 61f407d427
commit 04bb5f9995
54 changed files with 5144 additions and 55 deletions

View File

@@ -938,10 +938,6 @@ class PropertyGroup(StructRNA, metaclass=RNAMetaPropGroup):
__slots__ = ()
class RenderEngine(StructRNA, metaclass=RNAMeta):
__slots__ = ()
class KeyingSetInfo(StructRNA, metaclass=RNAMeta):
__slots__ = ()
@@ -1256,3 +1252,71 @@ 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_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, engine_type, self.bl_delegate_id)
if not self.engine_ptr:
return
_bpy_hydra.engine_update(self.engine_ptr, depsgraph, None)
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)
# Viewport render.
def view_update(self, context, depsgraph):
import _bpy_hydra
if not self.engine_ptr:
self.engine_ptr = _bpy_hydra.engine_create(self, 'VIEWPORT', self.bl_delegate_id)
if not self.engine_ptr:
return
_bpy_hydra.engine_update(self.engine_ptr, depsgraph, context)
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, context)