Support more AOVs #78

Merged
Bogdan Nagirniak merged 11 commits from DagerD/blender:BLEN-462_3 into hydra-render 2023-07-29 14:45:16 +02:00
56 changed files with 1297 additions and 1243 deletions
Showing only changes of commit 07f6cf428d - 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,155 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-or-later # 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()
bpy_hydra.register_plugins(["/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,
'aov:Depth': "depth",
}
def update_render_passes(self, scene, render_layer):
if render_layer.use_pass_z:
self.register_pass(scene, render_layer, 'Depth', 1, 'Z', 'VALUE')
```
"""
__all__ = ( __all__ = (
"HydraRenderEngine",
"export_mtlx", "export_mtlx",
"register_plugins",
) )
import os
import platform
from pathlib import Path
import bpy
import _bpy_hydra
from _bpy_hydra import register_plugins
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)
@classmethod
def register(cls):
root_folder = "blender.shared" if platform.system() == 'Windows' else "lib"
os.environ['PXR_MTLX_STDLIB_SEARCH_PATHS'] = os.pathsep.join([
str(Path(bpy.app.binary_path).parent / f"{root_folder}/materialx/libraries"),
os.environ.get('PXR_MTLX_STDLIB_SEARCH_PATHS', "")])
@classmethod
def unregister(cls):
pass
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, 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_sync(self.engine_ptr, depsgraph.as_pointer(), bpy.context.as_pointer())
def update(self, data, depsgraph):
# If bl_use_gpu_context is true, this function is ignored and render() is used
if not self.bl_use_gpu_context:
self._update(depsgraph)
def render(self, depsgraph):
if self.bl_use_gpu_context:
self._update(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_sync(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 update_render_passes(self, scene, render_layer):
""" Register supported AOVs for render. Must be overridden in child classes. """
pass
def export_mtlx(material): def export_mtlx(material):
""" Exports material to .mtlx file. It is called from Blender source code. """ """ Exports material to .mtlx file. It is called from Blender source code. """
try: try:

View File

@ -935,10 +935,6 @@ class PropertyGroup(StructRNA, metaclass=RNAMetaPropGroup):
__slots__ = () __slots__ = ()
class RenderEngine(StructRNA, metaclass=RNAMeta):
__slots__ = ()
class KeyingSetInfo(StructRNA, metaclass=RNAMeta): class KeyingSetInfo(StructRNA, metaclass=RNAMeta):
__slots__ = () __slots__ = ()
@ -1249,3 +1245,86 @@ class GeometryNode(NodeInternal):
@classmethod @classmethod
def poll(cls, ntree): def poll(cls, ntree):
return ntree.bl_idname == 'GeometryNodeTree' 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
import bpy
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
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, bpy.context)
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)
# 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
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, 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, depsgraph, context)

View File

@ -38,7 +38,11 @@ materialx_libs_dir = os.path.abspath(os.path.join(shared_lib_dir, "materialx", "
materialx_libs_env = os.getenv("MATERIALX_SEARCH_PATH") materialx_libs_env = os.getenv("MATERIALX_SEARCH_PATH")
if materialx_libs_env is None: if materialx_libs_env is None:
os.environ["MATERIALX_SEARCH_PATH"] = materialx_libs_dir os.environ["MATERIALX_SEARCH_PATH"] = materialx_libs_dir
elif sys.platform == "win32":
os.environ["MATERIALX_SEARCH_PATH"] = materialx_libs_dir + ";" + materialx_libs_env
else: else:
os.environ["MATERIALX_SEARCH_PATH"] = materialx_libs_dir + ":" + materialx_libs_env os.environ["MATERIALX_SEARCH_PATH"] = materialx_libs_env + os.pathsep + materialx_libs_dir
materialx_libs_env = os.getenv("PXR_MTLX_STDLIB_SEARCH_PATHS")
if materialx_libs_env is None:
os.environ["PXR_MTLX_STDLIB_SEARCH_PATHS"] = materialx_libs_dir
else:
os.environ["PXR_MTLX_STDLIB_SEARCH_PATHS"] = materialx_libs_env + os.pathsep + materialx_libs_dir

View File

@ -14,6 +14,17 @@ if(WIN32)
endif() endif()
add_definitions(-DBOOST_ALL_NO_LIB) add_definitions(-DBOOST_ALL_NO_LIB)
# Precompiled Linux libs are made with GCC, and USD uses some extensions
# which lead to an incompatible ABI for Clang. Using those extensions with
# Clang as well works around the issue.
if(UNIX AND NOT APPLE)
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
if(EXISTS ${LIBDIR})
add_definitions(-DARCH_HAS_GNU_STL_EXTENSIONS)
endif()
endif()
endif()
# USD headers use deprecated TBB headers, silence warning. # USD headers use deprecated TBB headers, silence warning.
add_definitions(-DTBB_SUPPRESS_DEPRECATED_MESSAGES=1) add_definitions(-DTBB_SUPPRESS_DEPRECATED_MESSAGES=1)
@ -53,8 +64,13 @@ set(INC
../../editors/include ../../editors/include
../../imbuf ../../imbuf
../../makesrna ../../makesrna
../../nodes
../../python/intern
../../windowmanager ../../windowmanager
../../../../intern/utfconv ../../../../intern/utfconv
../../../../intern/clog
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
set(INC_SYS set(INC_SYS
@ -124,6 +140,41 @@ set(SRC
intern/usd_reader_xform.h intern/usd_reader_xform.h
) )
if(WITH_HYDRA)
list(APPEND SRC
hydra/camera.cc
hydra/curves.cc
hydra/hydra_scene_delegate.cc
hydra/id.cc
hydra/image.cc
hydra/instancer.cc
hydra/light.cc
hydra/material.cc
hydra/mesh.cc
hydra/object.cc
hydra/usd_scene_delegate.cc
hydra/volume.cc
hydra/volume_modifier.cc
hydra/world.cc
hydra/camera.h
hydra/curves.h
hydra/hydra_scene_delegate.h
hydra/id.h
hydra/image.h
hydra/instancer.h
hydra/light.h
hydra/material.h
hydra/mesh.h
hydra/object.h
hydra/settings.h
hydra/usd_scene_delegate.h
hydra/volume.h
hydra/volume_modifier.h
hydra/world.h
)
endif()
set(LIB set(LIB
PRIVATE bf::blenkernel PRIVATE bf::blenkernel
PRIVATE bf::blenlib PRIVATE bf::blenlib
@ -151,8 +202,16 @@ if(WITH_OPENVDB)
) )
endif() endif()
if(WITH_MATERIALX)
add_definitions(-DWITH_MATERIALX)
list(APPEND LIB MaterialXCore)
endif()
blender_add_lib(bf_usd "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") blender_add_lib(bf_usd "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# RNA_prototypes.h
add_dependencies(bf_usd bf_rna)
if(COMMAND target_precompile_headers) if(COMMAND target_precompile_headers)
target_precompile_headers(bf_usd PRIVATE intern/usd_precomp.h) target_precompile_headers(bf_usd PRIVATE intern/usd_precomp.h)
endif() endif()

View File

@ -1,24 +1,23 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
* Copyright 2011-2022 Blender Foundation */ * SPDX-License-Identifier: GPL-2.0-or-later */
#include "camera.h"
#include "DNA_camera_types.h" #include "DNA_camera_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h" #include "DNA_screen_types.h"
#include "DNA_view3d_types.h" #include "DNA_view3d_types.h"
#include "camera.h" #include "hydra/object.h"
#include "scene_delegate/object.h"
namespace blender::render::hydra { namespace blender::io::hydra {
CameraData::CameraData(bContext *context) CameraData::CameraData(View3D *v3d, ARegion *region)
{ {
View3D *view3d = CTX_wm_view3d(context); RegionView3D *region_data = (RegionView3D *)region->regiondata;
RegionView3D *region_data = (RegionView3D *)CTX_wm_region_data(context);
ARegion *region = CTX_wm_region(context);
/* This constant was found experimentally, didn't find such option in /* TODO: refactor use BKE_camera_params API. */
* context.view3d or context.region_data. */ float VIEWPORT_SENSOR_SIZE = DEFAULT_SENSOR_WIDTH * 2.0f;
float VIEWPORT_SENSOR_SIZE = 72.0;
pxr::GfVec2i res(region->winx, region->winy); pxr::GfVec2i res(region->winx, region->winy);
float ratio = (float)res[0] / res[1]; float ratio = (float)res[0] / res[1];
@ -27,9 +26,9 @@ CameraData::CameraData(bContext *context)
switch (region_data->persp) { switch (region_data->persp) {
case RV3D_PERSP: { case RV3D_PERSP: {
mode_ = CAM_PERSP; mode_ = CAM_PERSP;
clip_range_ = pxr::GfRange1f(view3d->clip_start, view3d->clip_end); clip_range_ = pxr::GfRange1f(v3d->clip_start, v3d->clip_end);
lens_shift_ = pxr::GfVec2f(0.0, 0.0); lens_shift_ = pxr::GfVec2f(0.0, 0.0);
focal_length_ = view3d->lens; focal_length_ = v3d->lens;
if (ratio > 1.0) { if (ratio > 1.0) {
sensor_size_ = pxr::GfVec2f(VIEWPORT_SENSOR_SIZE, VIEWPORT_SENSOR_SIZE / ratio); sensor_size_ = pxr::GfVec2f(VIEWPORT_SENSOR_SIZE, VIEWPORT_SENSOR_SIZE / ratio);
@ -44,8 +43,8 @@ CameraData::CameraData(bContext *context)
mode_ = CAM_ORTHO; mode_ = CAM_ORTHO;
lens_shift_ = pxr::GfVec2f(0.0f, 0.0f); lens_shift_ = pxr::GfVec2f(0.0f, 0.0f);
float o_size = region_data->dist * VIEWPORT_SENSOR_SIZE / view3d->lens; float o_size = region_data->dist * VIEWPORT_SENSOR_SIZE / v3d->lens;
float o_depth = view3d->clip_end; float o_depth = v3d->clip_end;
clip_range_ = pxr::GfRange1f(-o_depth * 0.5, o_depth * 0.5); clip_range_ = pxr::GfRange1f(-o_depth * 0.5, o_depth * 0.5);
@ -60,7 +59,7 @@ CameraData::CameraData(bContext *context)
case RV3D_CAMOB: { case RV3D_CAMOB: {
pxr::GfMatrix4d mat = transform_; pxr::GfMatrix4d mat = transform_;
*this = CameraData(view3d->camera, res, pxr::GfVec4f(0, 0, 1, 1)); *this = CameraData(v3d->camera, res, pxr::GfVec4f(0, 0, 1, 1));
transform_ = mat; transform_ = mat;
/* This formula was taken from previous plugin with corresponded comment. /* This formula was taken from previous plugin with corresponded comment.
@ -141,7 +140,7 @@ CameraData::CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile)
lens_shift_[1] / t_size[1] + (t_pos[1] + t_size[1] * 0.5 - 0.5) / t_size[1]); lens_shift_[1] / t_size[1] + (t_pos[1] + t_size[1] * 0.5 - 0.5) / t_size[1]);
switch (camera->type) { switch (camera->type) {
case CAM_PERSP: case CAM_PERSP: {
focal_length_ = camera->lens; focal_length_ = camera->lens;
switch (camera->sensor_fit) { switch (camera->sensor_fit) {
@ -165,8 +164,9 @@ CameraData::CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile)
} }
sensor_size_ = pxr::GfVec2f(sensor_size_[0] * t_size[0], sensor_size_[1] * t_size[1]); sensor_size_ = pxr::GfVec2f(sensor_size_[0] * t_size[0], sensor_size_[1] * t_size[1]);
break; break;
}
case CAM_ORTHO: case CAM_ORTHO: {
focal_length_ = 0.0f; focal_length_ = 0.0f;
switch (camera->sensor_fit) { switch (camera->sensor_fit) {
case CAMERA_SENSOR_FIT_VERT: case CAMERA_SENSOR_FIT_VERT:
@ -189,8 +189,9 @@ CameraData::CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile)
} }
ortho_size_ = pxr::GfVec2f(ortho_size_[0] * t_size[0], ortho_size_[1] * t_size[1]); ortho_size_ = pxr::GfVec2f(ortho_size_[0] * t_size[0], ortho_size_[1] * t_size[1]);
break; break;
}
case CAM_PANO: case CAM_PANO: {
/* TODO: Recheck parameters for PANO camera */ /* TODO: Recheck parameters for PANO camera */
focal_length_ = camera->lens; focal_length_ = camera->lens;
@ -214,10 +215,14 @@ CameraData::CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile)
break; break;
} }
sensor_size_ = pxr::GfVec2f(sensor_size_[0] * t_size[0], sensor_size_[1] * t_size[1]); sensor_size_ = pxr::GfVec2f(sensor_size_[0] * t_size[0], sensor_size_[1] * t_size[1]);
break;
}
default: default: {
focal_length_ = camera->lens; focal_length_ = camera->lens;
sensor_size_ = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y); sensor_size_ = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y);
break;
}
} }
} }
@ -275,4 +280,4 @@ pxr::GfCamera CameraData::gf_camera(pxr::GfVec4f tile)
return gf_camera; return gf_camera;
} }
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,27 +1,20 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
#include <map> #include <tuple>
#include <pxr/base/gf/camera.h> #include <pxr/base/gf/camera.h>
#include <pxr/base/gf/vec2f.h> #include <pxr/base/gf/vec2f.h>
#include "BKE_context.h" struct ARegion;
struct Object;
struct View3D;
#include "DNA_object_types.h" namespace blender::io::hydra {
namespace blender::render::hydra {
class CameraData { class CameraData {
public:
CameraData(bContext *context);
CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile);
pxr::GfCamera gf_camera();
pxr::GfCamera gf_camera(pxr::GfVec4f tile);
private: private:
int mode_; int mode_;
pxr::GfRange1f clip_range_; pxr::GfRange1f clip_range_;
@ -31,6 +24,13 @@ class CameraData {
pxr::GfVec2f lens_shift_; pxr::GfVec2f lens_shift_;
pxr::GfVec2f ortho_size_; pxr::GfVec2f ortho_size_;
std::tuple<float, float, int> dof_data_; std::tuple<float, float, int> dof_data_;
public:
CameraData(View3D *v3d, ARegion *region);
CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile);
pxr::GfCamera gf_camera();
pxr::GfCamera gf_camera(pxr::GfVec4f tile);
}; };
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,5 +1,7 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "curves.h"
#include <pxr/base/gf/vec2f.h> #include <pxr/base/gf/vec2f.h>
#include <pxr/imaging/hd/tokens.h> #include <pxr/imaging/hd/tokens.h>
@ -7,11 +9,11 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "blender_scene_delegate.h" #include "hydra_scene_delegate.h"
namespace blender::render::hydra { namespace blender::io::hydra {
CurvesData::CurvesData(BlenderSceneDelegate *scene_delegate, CurvesData::CurvesData(HydraSceneDelegate *scene_delegate,
Object *object, Object *object,
pxr::SdfPath const &prim_id) pxr::SdfPath const &prim_id)
: ObjectData(scene_delegate, object, prim_id) : ObjectData(scene_delegate, object, prim_id)
@ -178,4 +180,4 @@ void CurvesData::write_uv_maps(Curves *curves)
} }
} }
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,23 +1,33 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
#include <pxr/base/vt/array.h> #include <pxr/base/vt/array.h>
#include <pxr/imaging/hd/sceneDelegate.h> #include <pxr/imaging/hd/sceneDelegate.h>
#include "BKE_duplilist.h"
#include "DNA_curves_types.h" #include "DNA_curves_types.h"
#include "BLI_set.hh" #include "BLI_set.hh"
#include "BKE_duplilist.h"
#include "material.h" #include "material.h"
#include "object.h" #include "object.h"
namespace blender::render::hydra { namespace blender::io::hydra {
class CurvesData : public ObjectData { class CurvesData : public ObjectData {
private:
pxr::VtIntArray curve_vertex_counts_;
pxr::VtVec3fArray vertices_;
pxr::VtVec2fArray uvs_;
pxr::VtFloatArray widths_;
MaterialData *mat_data_ = nullptr;
public: public:
CurvesData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id); CurvesData(HydraSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id);
void init() override; void init() override;
void insert() override; void insert() override;
@ -37,13 +47,6 @@ class CurvesData : public ObjectData {
private: private:
void write_curves(Curves *curves); void write_curves(Curves *curves);
void write_uv_maps(Curves *curves); void write_uv_maps(Curves *curves);
pxr::VtIntArray curve_vertex_counts_;
pxr::VtVec3fArray vertices_;
pxr::VtVec2fArray uvs_;
pxr::VtFloatArray widths_;
MaterialData *mat_data_ = nullptr;
}; };
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,19 +1,21 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "hydra_scene_delegate.h"
#include <bitset> #include <bitset>
#include "BLI_set.hh"
#include "DEG_depsgraph_query.h"
#include "DNA_scene_types.h" #include "DNA_scene_types.h"
#include "blender_scene_delegate.h" #include "BLI_set.hh"
namespace blender::render::hydra { #include "DEG_depsgraph_query.h"
namespace blender::io::hydra {
CLG_LOGREF_DECLARE_GLOBAL(LOG_RENDER_HYDRA_SCENE, "render.hydra.scene"); CLG_LOGREF_DECLARE_GLOBAL(LOG_RENDER_HYDRA_SCENE, "render.hydra.scene");
bool BlenderSceneDelegate::ShadingSettings::operator==(const ShadingSettings &other) bool HydraSceneDelegate::ShadingSettings::operator==(const ShadingSettings &other)
{ {
bool ret = use_scene_lights == other.use_scene_lights && bool ret = use_scene_lights == other.use_scene_lights &&
use_scene_world == other.use_scene_world; use_scene_world == other.use_scene_world;
@ -26,34 +28,34 @@ bool BlenderSceneDelegate::ShadingSettings::operator==(const ShadingSettings &ot
return ret; return ret;
} }
BlenderSceneDelegate::BlenderSceneDelegate(pxr::HdRenderIndex *parent_index, HydraSceneDelegate::HydraSceneDelegate(pxr::HdRenderIndex *parent_index,
pxr::SdfPath const &delegate_id, pxr::SdfPath const &delegate_id,
const SceneDelegateSettings &settings) const HydraDelegateSettings &settings)
: HdSceneDelegate(parent_index, delegate_id), settings(settings) : HdSceneDelegate(parent_index, delegate_id), settings(settings)
{ {
instancer_data_ = std::make_unique<InstancerData>(this, instancer_prim_id()); instancer_data_ = std::make_unique<InstancerData>(this, instancer_prim_id());
} }
pxr::HdMeshTopology BlenderSceneDelegate::GetMeshTopology(pxr::SdfPath const &id) pxr::HdMeshTopology HydraSceneDelegate::GetMeshTopology(pxr::SdfPath const &id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText());
MeshData *m_data = mesh_data(id); MeshData *m_data = mesh_data(id);
return m_data->mesh_topology(id); return m_data->topology(id);
} }
pxr::HdBasisCurvesTopology BlenderSceneDelegate::GetBasisCurvesTopology(pxr::SdfPath const &id) pxr::HdBasisCurvesTopology HydraSceneDelegate::GetBasisCurvesTopology(pxr::SdfPath const &id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText());
CurvesData *c_data = curves_data(id); CurvesData *c_data = curves_data(id);
return c_data->topology(); return c_data->topology();
}; };
pxr::GfMatrix4d BlenderSceneDelegate::GetTransform(pxr::SdfPath const &id) pxr::GfMatrix4d HydraSceneDelegate::GetTransform(pxr::SdfPath const &id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText());
InstancerData *i_data = instancer_data(id, true); InstancerData *i_data = instancer_data(id, true);
if (i_data) { if (i_data) {
return i_data->get_transform(id); return i_data->transform(id);
} }
ObjectData *obj_data = object_data(id); ObjectData *obj_data = object_data(id);
if (obj_data) { if (obj_data) {
@ -65,7 +67,7 @@ pxr::GfMatrix4d BlenderSceneDelegate::GetTransform(pxr::SdfPath const &id)
return pxr::GfMatrix4d(); return pxr::GfMatrix4d();
} }
pxr::VtValue BlenderSceneDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key) pxr::VtValue HydraSceneDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s, %s", id.GetText(), key.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s, %s", id.GetText(), key.GetText());
ObjectData *obj_data = object_data(id); ObjectData *obj_data = object_data(id);
@ -83,8 +85,8 @@ pxr::VtValue BlenderSceneDelegate::Get(pxr::SdfPath const &id, pxr::TfToken cons
return pxr::VtValue(); return pxr::VtValue();
} }
pxr::VtValue BlenderSceneDelegate::GetLightParamValue(pxr::SdfPath const &id, pxr::VtValue HydraSceneDelegate::GetLightParamValue(pxr::SdfPath const &id,
pxr::TfToken const &key) pxr::TfToken const &key)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s, %s", id.GetText(), key.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s, %s", id.GetText(), key.GetText());
LightData *l_data = light_data(id); LightData *l_data = light_data(id);
@ -94,7 +96,7 @@ pxr::VtValue BlenderSceneDelegate::GetLightParamValue(pxr::SdfPath const &id,
return pxr::VtValue(); return pxr::VtValue();
} }
pxr::HdPrimvarDescriptorVector BlenderSceneDelegate::GetPrimvarDescriptors( pxr::HdPrimvarDescriptorVector HydraSceneDelegate::GetPrimvarDescriptors(
pxr::SdfPath const &id, pxr::HdInterpolation interpolation) pxr::SdfPath const &id, pxr::HdInterpolation interpolation)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s, %d", id.GetText(), interpolation); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s, %d", id.GetText(), interpolation);
@ -113,7 +115,7 @@ pxr::HdPrimvarDescriptorVector BlenderSceneDelegate::GetPrimvarDescriptors(
return pxr::HdPrimvarDescriptorVector(); return pxr::HdPrimvarDescriptorVector();
} }
pxr::SdfPath BlenderSceneDelegate::GetMaterialId(pxr::SdfPath const &rprim_id) pxr::SdfPath HydraSceneDelegate::GetMaterialId(pxr::SdfPath const &rprim_id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", rprim_id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", rprim_id.GetText());
ObjectData *obj_data = object_data(rprim_id); ObjectData *obj_data = object_data(rprim_id);
@ -123,7 +125,7 @@ pxr::SdfPath BlenderSceneDelegate::GetMaterialId(pxr::SdfPath const &rprim_id)
return pxr::SdfPath(); return pxr::SdfPath();
} }
pxr::VtValue BlenderSceneDelegate::GetMaterialResource(pxr::SdfPath const &id) pxr::VtValue HydraSceneDelegate::GetMaterialResource(pxr::SdfPath const &id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText());
MaterialData *mat_data = material_data(id); MaterialData *mat_data = material_data(id);
@ -133,7 +135,7 @@ pxr::VtValue BlenderSceneDelegate::GetMaterialResource(pxr::SdfPath const &id)
return pxr::VtValue(); return pxr::VtValue();
} }
bool BlenderSceneDelegate::GetVisible(pxr::SdfPath const &id) bool HydraSceneDelegate::GetVisible(pxr::SdfPath const &id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText());
if (id == world_prim_id()) { if (id == world_prim_id()) {
@ -146,51 +148,51 @@ bool BlenderSceneDelegate::GetVisible(pxr::SdfPath const &id)
return object_data(id)->visible; return object_data(id)->visible;
} }
bool BlenderSceneDelegate::GetDoubleSided(pxr::SdfPath const &id) bool HydraSceneDelegate::GetDoubleSided(pxr::SdfPath const &id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText());
return mesh_data(id)->double_sided(id); return mesh_data(id)->double_sided(id);
} }
pxr::HdCullStyle BlenderSceneDelegate::GetCullStyle(pxr::SdfPath const &id) pxr::HdCullStyle HydraSceneDelegate::GetCullStyle(pxr::SdfPath const &id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText());
return mesh_data(id)->cull_style(id); return mesh_data(id)->cull_style(id);
} }
pxr::SdfPath BlenderSceneDelegate::GetInstancerId(pxr::SdfPath const &prim_id) pxr::SdfPath HydraSceneDelegate::GetInstancerId(pxr::SdfPath const &prim_id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", prim_id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", prim_id.GetText());
InstancerData *i_data = instancer_data(prim_id, true); InstancerData *i_data = instancer_data(prim_id, true);
if (i_data) { if (i_data && mesh_data(prim_id)) {
return i_data->prim_id; return i_data->prim_id;
} }
return pxr::SdfPath(); return pxr::SdfPath();
} }
pxr::SdfPathVector BlenderSceneDelegate::GetInstancerPrototypes(pxr::SdfPath const &instancer_id) pxr::SdfPathVector HydraSceneDelegate::GetInstancerPrototypes(pxr::SdfPath const &instancer_id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", instancer_id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", instancer_id.GetText());
InstancerData *i_data = instancer_data(instancer_id); InstancerData *i_data = instancer_data(instancer_id);
return i_data->prototypes(); return i_data->prototypes();
} }
pxr::VtIntArray BlenderSceneDelegate::GetInstanceIndices(pxr::SdfPath const &instancer_id, pxr::VtIntArray HydraSceneDelegate::GetInstanceIndices(pxr::SdfPath const &instancer_id,
pxr::SdfPath const &prototype_id) pxr::SdfPath const &prototype_id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s, %s", instancer_id.GetText(), prototype_id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s, %s", instancer_id.GetText(), prototype_id.GetText());
InstancerData *i_data = instancer_data(instancer_id); InstancerData *i_data = instancer_data(instancer_id);
return i_data->indices(prototype_id); return i_data->indices(prototype_id);
} }
pxr::GfMatrix4d BlenderSceneDelegate::GetInstancerTransform(pxr::SdfPath const &instancer_id) pxr::GfMatrix4d HydraSceneDelegate::GetInstancerTransform(pxr::SdfPath const &instancer_id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", instancer_id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", instancer_id.GetText());
InstancerData *i_data = instancer_data(instancer_id); InstancerData *i_data = instancer_data(instancer_id);
return i_data->get_transform(instancer_id); return i_data->transform(instancer_id);
} }
pxr::HdVolumeFieldDescriptorVector BlenderSceneDelegate::GetVolumeFieldDescriptors( pxr::HdVolumeFieldDescriptorVector HydraSceneDelegate::GetVolumeFieldDescriptors(
pxr::SdfPath const &volume_id) pxr::SdfPath const &volume_id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", volume_id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", volume_id.GetText());
@ -198,14 +200,14 @@ pxr::HdVolumeFieldDescriptorVector BlenderSceneDelegate::GetVolumeFieldDescripto
return v_data->field_descriptors(); return v_data->field_descriptors();
} }
void BlenderSceneDelegate::populate(Depsgraph *deps, bContext *cont) void HydraSceneDelegate::populate(Depsgraph *deps, View3D *v3d)
{ {
bool is_populated = depsgraph != nullptr; bool is_populated = depsgraph != nullptr;
depsgraph = deps; depsgraph = deps;
context = cont; bmain = DEG_get_bmain(deps);
scene = DEG_get_input_scene(depsgraph); scene = DEG_get_input_scene(depsgraph);
view3d = CTX_wm_view3d(context); view3d = v3d;
if (is_populated) { if (is_populated) {
check_updates(); check_updates();
@ -218,7 +220,7 @@ void BlenderSceneDelegate::populate(Depsgraph *deps, bContext *cont)
} }
} }
void BlenderSceneDelegate::clear() void HydraSceneDelegate::clear()
{ {
for (auto &obj_data : objects_.values()) { for (auto &obj_data : objects_.values()) {
obj_data->remove(); obj_data->remove();
@ -231,12 +233,12 @@ void BlenderSceneDelegate::clear()
materials_.clear(); materials_.clear();
depsgraph = nullptr; depsgraph = nullptr;
context = nullptr; bmain = nullptr;
scene = nullptr; scene = nullptr;
view3d = nullptr; view3d = nullptr;
} }
pxr::SdfPath BlenderSceneDelegate::prim_id(ID *id, const char *prefix) const pxr::SdfPath HydraSceneDelegate::prim_id(ID *id, const char *prefix) const
{ {
/* Making id of object in form like <prefix>_<pointer in 16 hex digits format> */ /* Making id of object in form like <prefix>_<pointer in 16 hex digits format> */
char name[32]; char name[32];
@ -244,27 +246,27 @@ pxr::SdfPath BlenderSceneDelegate::prim_id(ID *id, const char *prefix) const
return GetDelegateID().AppendElementString(name); return GetDelegateID().AppendElementString(name);
} }
pxr::SdfPath BlenderSceneDelegate::object_prim_id(Object *object) const pxr::SdfPath HydraSceneDelegate::object_prim_id(Object *object) const
{ {
return prim_id((ID *)object, "O"); return prim_id((ID *)object, "O");
} }
pxr::SdfPath BlenderSceneDelegate::material_prim_id(Material *mat) const pxr::SdfPath HydraSceneDelegate::material_prim_id(Material *mat) const
{ {
return prim_id((ID *)mat, "M"); return prim_id((ID *)mat, "M");
} }
pxr::SdfPath BlenderSceneDelegate::instancer_prim_id() const pxr::SdfPath HydraSceneDelegate::instancer_prim_id() const
{ {
return GetDelegateID().AppendElementString("Instancer"); return GetDelegateID().AppendElementString("Instancer");
} }
pxr::SdfPath BlenderSceneDelegate::world_prim_id() const pxr::SdfPath HydraSceneDelegate::world_prim_id() const
{ {
return GetDelegateID().AppendElementString("World"); return GetDelegateID().AppendElementString("World");
} }
ObjectData *BlenderSceneDelegate::object_data(pxr::SdfPath const &id) const ObjectData *HydraSceneDelegate::object_data(pxr::SdfPath const &id) const
{ {
if (id == world_prim_id()) { if (id == world_prim_id()) {
return world_data_.get(); return world_data_.get();
@ -285,27 +287,27 @@ ObjectData *BlenderSceneDelegate::object_data(pxr::SdfPath const &id) const
return nullptr; return nullptr;
} }
MeshData *BlenderSceneDelegate::mesh_data(pxr::SdfPath const &id) const MeshData *HydraSceneDelegate::mesh_data(pxr::SdfPath const &id) const
{ {
return dynamic_cast<MeshData *>(object_data(id)); return dynamic_cast<MeshData *>(object_data(id));
} }
CurvesData *BlenderSceneDelegate::curves_data(pxr::SdfPath const &id) const CurvesData *HydraSceneDelegate::curves_data(pxr::SdfPath const &id) const
{ {
return dynamic_cast<CurvesData *>(object_data(id)); return dynamic_cast<CurvesData *>(object_data(id));
} }
VolumeData *BlenderSceneDelegate::volume_data(pxr::SdfPath const &id) const VolumeData *HydraSceneDelegate::volume_data(pxr::SdfPath const &id) const
{ {
return dynamic_cast<VolumeData *>(object_data(id)); return dynamic_cast<VolumeData *>(object_data(id));
} }
LightData *BlenderSceneDelegate::light_data(pxr::SdfPath const &id) const LightData *HydraSceneDelegate::light_data(pxr::SdfPath const &id) const
{ {
return dynamic_cast<LightData *>(object_data(id)); return dynamic_cast<LightData *>(object_data(id));
} }
MaterialData *BlenderSceneDelegate::material_data(pxr::SdfPath const &id) const MaterialData *HydraSceneDelegate::material_data(pxr::SdfPath const &id) const
{ {
auto mat_data = materials_.lookup_ptr(id); auto mat_data = materials_.lookup_ptr(id);
if (!mat_data) { if (!mat_data) {
@ -314,7 +316,7 @@ MaterialData *BlenderSceneDelegate::material_data(pxr::SdfPath const &id) const
return mat_data->get(); return mat_data->get();
} }
InstancerData *BlenderSceneDelegate::instancer_data(pxr::SdfPath const &id, bool child_id) const InstancerData *HydraSceneDelegate::instancer_data(pxr::SdfPath const &id, bool child_id) const
{ {
pxr::SdfPath p_id; pxr::SdfPath p_id;
if (child_id) { if (child_id) {
@ -338,7 +340,7 @@ InstancerData *BlenderSceneDelegate::instancer_data(pxr::SdfPath const &id, bool
return nullptr; return nullptr;
} }
void BlenderSceneDelegate::update_world() void HydraSceneDelegate::update_world()
{ {
if (!world_data_) { if (!world_data_) {
if (!shading_settings.use_scene_world || (shading_settings.use_scene_world && scene->world)) { if (!shading_settings.use_scene_world || (shading_settings.use_scene_world && scene->world)) {
@ -358,7 +360,7 @@ void BlenderSceneDelegate::update_world()
} }
} }
void BlenderSceneDelegate::check_updates() void HydraSceneDelegate::check_updates()
{ {
bool do_update_collection = false; bool do_update_collection = false;
bool do_update_world = false; bool do_update_world = false;
@ -427,7 +429,7 @@ void BlenderSceneDelegate::check_updates()
} }
} }
void BlenderSceneDelegate::update_collection() void HydraSceneDelegate::update_collection()
{ {
Set<std::string> available_objects; Set<std::string> available_objects;
@ -449,17 +451,21 @@ void BlenderSceneDelegate::update_collection()
object) object)
{ {
if (data.dupli_object_current) { if (data.dupli_object_current) {
instancer_data_->update_instance(data.dupli_parent, data.dupli_object_current); DupliObject *dupli = data.dupli_object_current;
if (!ObjectData::is_supported(dupli->ob) ||
!ObjectData::is_visible(this, data.dupli_parent, OB_VISIBLE_INSTANCES) ||
(!shading_settings.use_scene_lights && object->type == OB_LAMP))
{
continue;
}
instancer_data_->update_instance(data.dupli_parent, dupli);
continue; continue;
} }
if (!ObjectData::is_supported(object)) { if (!ObjectData::is_supported(object) || !ObjectData::is_visible(this, object) ||
continue; (!shading_settings.use_scene_lights && object->type == OB_LAMP))
} {
if (!ObjectData::is_visible(this, object)) {
continue;
}
if (!shading_settings.use_scene_lights && object->type == OB_LAMP) {
continue; continue;
} }
@ -515,7 +521,7 @@ void BlenderSceneDelegate::update_collection()
}); });
} }
bool BlenderSceneDelegate::set_light_shading_settings() bool HydraSceneDelegate::set_light_shading_settings()
{ {
if (!view3d) { if (!view3d) {
return false; return false;
@ -525,7 +531,7 @@ bool BlenderSceneDelegate::set_light_shading_settings()
return !(shading_settings == prev_settings); return !(shading_settings == prev_settings);
} }
bool BlenderSceneDelegate::set_world_shading_settings() bool HydraSceneDelegate::set_world_shading_settings()
{ {
if (!view3d) { if (!view3d) {
return false; return false;
@ -538,4 +544,4 @@ bool BlenderSceneDelegate::set_world_shading_settings()
return !(shading_settings == prev_settings); return !(shading_settings == prev_settings);
} }
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,13 +1,13 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
#include <pxr/base/gf/vec2f.h> #include <pxr/base/gf/vec2f.h>
#include <pxr/imaging/hd/sceneDelegate.h> #include <pxr/imaging/hd/sceneDelegate.h>
#include "BKE_context.h"
#include "BLI_map.hh" #include "BLI_map.hh"
#include "DEG_depsgraph.h" #include "DEG_depsgraph.h"
#include "CLG_log.h" #include "CLG_log.h"
@ -22,13 +22,18 @@
#include "volume_modifier.h" #include "volume_modifier.h"
#include "world.h" #include "world.h"
namespace blender::render::hydra { struct Depsgraph;
struct Main;
struct Scene;
struct View3D;
namespace blender::io::hydra {
extern struct CLG_LogRef *LOG_RENDER_HYDRA_SCENE; extern struct CLG_LogRef *LOG_RENDER_HYDRA_SCENE;
class Engine; class Engine;
class BlenderSceneDelegate : public pxr::HdSceneDelegate { class HydraSceneDelegate : public pxr::HdSceneDelegate {
friend ObjectData; /* has access to materials */ friend ObjectData; /* has access to materials */
friend MaterialData; /* has access to objects and instancers */ friend MaterialData; /* has access to objects and instancers */
@ -43,10 +48,24 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
bool operator==(const ShadingSettings &other); bool operator==(const ShadingSettings &other);
}; };
BlenderSceneDelegate(pxr::HdRenderIndex *parent_index, Depsgraph *depsgraph = nullptr;
pxr::SdfPath const &delegate_id, View3D *view3d = nullptr;
const SceneDelegateSettings &settings); Main *bmain = nullptr;
~BlenderSceneDelegate() override = default; Scene *scene = nullptr;
const HydraDelegateSettings &settings;
ShadingSettings shading_settings;
private:
ObjectDataMap objects_;
MaterialDataMap materials_;
std::unique_ptr<InstancerData> instancer_data_;
std::unique_ptr<WorldData> world_data_;
public:
HydraSceneDelegate(pxr::HdRenderIndex *parent_index,
pxr::SdfPath const &delegate_id,
const HydraDelegateSettings &settings);
~HydraSceneDelegate() override = default;
/* Delegate methods */ /* Delegate methods */
pxr::HdMeshTopology GetMeshTopology(pxr::SdfPath const &id) override; pxr::HdMeshTopology GetMeshTopology(pxr::SdfPath const &id) override;
@ -69,16 +88,9 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
pxr::HdVolumeFieldDescriptorVector GetVolumeFieldDescriptors( pxr::HdVolumeFieldDescriptorVector GetVolumeFieldDescriptors(
pxr::SdfPath const &volume_id) override; pxr::SdfPath const &volume_id) override;
void populate(Depsgraph *depsgraph, bContext *context); void populate(Depsgraph *depsgraph, View3D *v3d);
void clear(); void clear();
Depsgraph *depsgraph = nullptr;
bContext *context = nullptr;
View3D *view3d = nullptr;
Scene *scene = nullptr;
const SceneDelegateSettings &settings;
ShadingSettings shading_settings;
private: private:
pxr::SdfPath prim_id(ID *id, const char *prefix) const; pxr::SdfPath prim_id(ID *id, const char *prefix) const;
pxr::SdfPath object_prim_id(Object *object) const; pxr::SdfPath object_prim_id(Object *object) const;
@ -99,11 +111,6 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
void update_collection(); void update_collection();
bool set_light_shading_settings(); bool set_light_shading_settings();
bool set_world_shading_settings(); bool set_world_shading_settings();
ObjectDataMap objects_;
MaterialDataMap materials_;
std::unique_ptr<InstancerData> instancer_data_;
std::unique_ptr<WorldData> world_data_;
}; };
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "id.h"
#include "BKE_lib_id.h"
namespace blender::io::hydra {
IdData::IdData(HydraSceneDelegate *scene_delegate, ID *id, pxr::SdfPath const &prim_id)
: id(id), prim_id(prim_id), scene_delegate_(scene_delegate)
{
}
} // namespace blender::io::hydra

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
@ -7,9 +7,10 @@
#include <pxr/base/vt/value.h> #include <pxr/base/vt/value.h>
#include <pxr/usd/sdf/path.h> #include <pxr/usd/sdf/path.h>
#include "BLI_hash.hh"
#include "DNA_ID.h" #include "DNA_ID.h"
#include "BLI_hash.hh"
template<> struct blender::DefaultHash<pxr::SdfPath> { template<> struct blender::DefaultHash<pxr::SdfPath> {
uint64_t operator()(const pxr::SdfPath &value) const uint64_t operator()(const pxr::SdfPath &value) const
{ {
@ -24,13 +25,20 @@ template<> struct blender::DefaultHash<pxr::TfToken> {
} }
}; };
namespace blender::render::hydra { namespace blender::io::hydra {
class BlenderSceneDelegate; class HydraSceneDelegate;
class IdData { class IdData {
public: public:
IdData(BlenderSceneDelegate *scene_delegate, ID *id, pxr::SdfPath const &prim_id); ID *id;
pxr::SdfPath prim_id;
protected:
HydraSceneDelegate *scene_delegate_;
public:
IdData(HydraSceneDelegate *scene_delegate, ID *id, pxr::SdfPath const &prim_id);
virtual ~IdData() = default; virtual ~IdData() = default;
virtual void init() = 0; virtual void init() = 0;
@ -39,12 +47,6 @@ class IdData {
virtual void update() = 0; virtual void update() = 0;
virtual pxr::VtValue get_data(pxr::TfToken const &key) const = 0; virtual pxr::VtValue get_data(pxr::TfToken const &key) const = 0;
ID *id;
pxr::SdfPath prim_id;
protected:
BlenderSceneDelegate *scene_delegate_;
}; };
#define ID_LOG(level, msg, ...) \ #define ID_LOG(level, msg, ...) \
@ -58,4 +60,4 @@ class IdData {
id ? id->name : "", \ id ? id->name : "", \
##__VA_ARGS__); ##__VA_ARGS__);
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,20 +1,24 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "image.h"
#include <pxr/imaging/hio/imageRegistry.h> #include <pxr/imaging/hio/imageRegistry.h>
#include "BKE_appdir.h"
#include "BKE_image_format.h"
#include "BKE_image_save.h"
#include "BLI_fileops.h" #include "BLI_fileops.h"
#include "BLI_path_util.h" #include "BLI_path_util.h"
#include "BKE_appdir.h"
#include "BKE_image.h"
#include "BKE_image_format.h"
#include "BKE_image_save.h"
#include "IMB_imbuf.h" #include "IMB_imbuf.h"
#include "IMB_imbuf_types.h" #include "IMB_imbuf_types.h"
#include "blender_scene_delegate.h" #include "hydra_scene_delegate.h"
#include "image.h"
namespace blender::render::hydra { namespace blender::io::hydra {
static std::string get_cache_file(const std::string &file_name, bool mkdir = true) static std::string get_cache_file(const std::string &file_name, bool mkdir = true)
{ {
@ -29,16 +33,12 @@ static std::string get_cache_file(const std::string &file_name, bool mkdir = tru
return file_path; return file_path;
} }
static std::string cache_image_file(Image *image, static std::string cache_image_file(
bContext *context, Main *bmain, Scene *scene, Image *image, ImageUser *iuser, bool check_exist)
ImageUser *iuser,
bool check_exist)
{ {
std::string file_path; std::string file_path;
Main *main = CTX_data_main(context);
Scene *scene = CTX_data_scene(context);
ImageSaveOptions opts; ImageSaveOptions opts;
if (BKE_image_save_options_init(&opts, main, scene, image, iuser, false, false)) { if (BKE_image_save_options_init(&opts, bmain, scene, image, iuser, false, false)) {
char file_name[32]; char file_name[32];
const char *r_ext = BLI_path_extension_or_end(image->id.name); const char *r_ext = BLI_path_extension_or_end(image->id.name);
if (!pxr::HioImageRegistry::GetInstance().IsSupportedImageFile(image->id.name)) { if (!pxr::HioImageRegistry::GetInstance().IsSupportedImageFile(image->id.name)) {
@ -55,7 +55,7 @@ static std::string cache_image_file(Image *image,
opts.save_copy = true; opts.save_copy = true;
STRNCPY(opts.filepath, file_path.c_str()); STRNCPY(opts.filepath, file_path.c_str());
if (BKE_image_save(nullptr, main, image, iuser, &opts)) { if (BKE_image_save(nullptr, bmain, image, iuser, &opts)) {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 1, "%s -> %s", image->id.name, file_path.c_str()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 1, "%s -> %s", image->id.name, file_path.c_str());
} }
else { else {
@ -67,23 +67,22 @@ static std::string cache_image_file(Image *image,
return file_path; return file_path;
} }
std::string cache_or_get_image_file(Image *image, bContext *context, ImageUser *iuser) std::string cache_or_get_image_file(Main *bmain, Scene *scene, Image *image, ImageUser *iuser)
{ {
std::string file_path; std::string file_path;
if (image->source == IMA_SRC_GENERATED) { if (image->source == IMA_SRC_GENERATED) {
file_path = cache_image_file(image, context, iuser, false); file_path = cache_image_file(bmain, scene, image, iuser, false);
} }
else if (BKE_image_has_packedfile(image)) { else if (BKE_image_has_packedfile(image)) {
file_path = cache_image_file(image, context, iuser, true); file_path = cache_image_file(bmain, scene, image, iuser, true);
} }
else { else {
Main *main = CTX_data_main(context);
char str[FILE_MAX]; char str[FILE_MAX];
BKE_image_user_file_path_ex(main, iuser, image, str, false, true); BKE_image_user_file_path_ex(bmain, iuser, image, str, false, true);
file_path = str; file_path = str;
if (!pxr::HioImageRegistry::GetInstance().IsSupportedImageFile(file_path)) { if (!pxr::HioImageRegistry::GetInstance().IsSupportedImageFile(file_path)) {
file_path = cache_image_file(image, context, iuser, true); file_path = cache_image_file(bmain, scene, image, iuser, true);
} }
} }
@ -96,7 +95,7 @@ std::string cache_image_color(float color[4])
char name[128]; char name[128];
snprintf(name, snprintf(name,
sizeof(name), sizeof(name),
"color_%02x%02x%02x.hdr", "color_%02d%02d%02d.hdr",
int(color[0] * 255), int(color[0] * 255),
int(color[1] * 255), int(color[1] * 255),
int(color[2] * 255)); int(color[2] * 255));
@ -121,4 +120,4 @@ std::string cache_image_color(float color[4])
return file_path; return file_path;
} }
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once
#include <string>
struct Main;
struct Scene;
struct Image;
struct ImageUser;
namespace blender::io::hydra {
std::string cache_or_get_image_file(Main *bmain, Scene *Scene, Image *image, ImageUser *iuser);
std::string cache_image_color(float color[4]);
} // namespace blender::io::hydra

View File

@ -0,0 +1,286 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "instancer.h"
#include <pxr/base/gf/vec2f.h>
#include <pxr/imaging/hd/light.h>
#include "DEG_depsgraph_query.h"
#include "hydra_scene_delegate.h"
namespace blender::io::hydra {
InstancerData::InstancerData(HydraSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id)
: IdData(scene_delegate, nullptr, prim_id)
{
}
void InstancerData::init() {}
void InstancerData::insert() {}
void InstancerData::remove()
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 1, "%s", prim_id.GetText());
for (auto &m_inst : mesh_instances_.values()) {
m_inst.data->remove();
}
if (!mesh_instances_.is_empty()) {
scene_delegate_->GetRenderIndex().RemoveInstancer(prim_id);
}
mesh_instances_.clear();
for (auto &l_inst : nonmesh_instances_.values()) {
l_inst.transforms.clear();
update_nonmesh_instance(l_inst);
}
nonmesh_instances_.clear();
}
void InstancerData::update() {}
pxr::VtValue InstancerData::get_data(pxr::TfToken const &key) const
{
ID_LOG(3, "%s", key.GetText());
if (key == pxr::HdInstancerTokens->instanceTransform) {
return pxr::VtValue(mesh_transforms_);
}
return pxr::VtValue();
}
pxr::GfMatrix4d InstancerData::transform(pxr::SdfPath const &id) const
{
NonmeshInstance *nm_inst = nonmesh_instance(id);
if (nm_inst) {
return nm_inst->transforms[nonmesh_prim_id_index(id)];
}
/* Mesh instance transform must be identity */
return pxr::GfMatrix4d(1.0);
}
pxr::HdPrimvarDescriptorVector InstancerData::primvar_descriptors(
pxr::HdInterpolation interpolation) const
{
pxr::HdPrimvarDescriptorVector primvars;
if (interpolation == pxr::HdInterpolationInstance) {
primvars.emplace_back(
pxr::HdInstancerTokens->instanceTransform, interpolation, pxr::HdPrimvarRoleTokens->none);
}
return primvars;
}
pxr::VtIntArray InstancerData::indices(pxr::SdfPath const &id) const
{
return mesh_instance(id)->indices;
}
ObjectData *InstancerData::object_data(pxr::SdfPath const &id) const
{
MeshInstance *m_inst = mesh_instance(id);
if (m_inst) {
return m_inst->data.get();
}
NonmeshInstance *nm_inst = nonmesh_instance(id);
if (nm_inst) {
return nm_inst->data.get();
}
return nullptr;
}
pxr::SdfPathVector InstancerData::prototypes() const
{
pxr::SdfPathVector paths;
for (auto &m_inst : mesh_instances_.values()) {
for (auto &p : m_inst.data->submesh_paths()) {
paths.push_back(p);
}
}
return paths;
}
void InstancerData::available_materials(Set<pxr::SdfPath> &paths) const
{
for (auto &m_inst : mesh_instances_.values()) {
m_inst.data->available_materials(paths);
}
for (auto &l_inst : nonmesh_instances_.values()) {
l_inst.data->available_materials(paths);
}
}
void InstancerData::update_double_sided(MaterialData *mat_data)
{
for (auto &m_inst : mesh_instances_.values()) {
m_inst.data->update_double_sided(mat_data);
}
}
void InstancerData::pre_update()
{
mesh_transforms_.clear();
for (auto &m_inst : mesh_instances_.values()) {
m_inst.indices.clear();
}
for (auto &l_inst : nonmesh_instances_.values()) {
l_inst.transforms.clear();
}
}
void InstancerData::update_instance(Object * /* parent_ob */, DupliObject *dupli)
{
Object *object = dupli->ob;
pxr::SdfPath p_id = object_prim_id(object);
if (ObjectData::is_mesh(object)) {
MeshInstance *m_inst = mesh_instance(p_id);
if (!m_inst) {
m_inst = &mesh_instances_.lookup_or_add_default(p_id);
m_inst->data = std::make_unique<MeshData>(scene_delegate_, object, p_id);
m_inst->data->init();
m_inst->data->insert();
}
else {
m_inst->data->update();
}
ID_LOG(2, "Mesh %s %d", m_inst->data->id->name, (int)mesh_transforms_.size());
m_inst->indices.push_back(mesh_transforms_.size());
mesh_transforms_.push_back(gf_matrix_from_transform(dupli->mat));
}
else {
NonmeshInstance *nm_inst = nonmesh_instance(p_id);
if (!nm_inst) {
nm_inst = &nonmesh_instances_.lookup_or_add_default(p_id);
nm_inst->data = ObjectData::create(scene_delegate_, object, p_id);
}
ID_LOG(2, "Light %s %d", nm_inst->data->id->name, (int)nm_inst->transforms.size());
nm_inst->transforms.push_back(gf_matrix_from_transform(dupli->mat));
}
}
void InstancerData::post_update()
{
/* Remove mesh intances without indices */
mesh_instances_.remove_if([&](auto item) {
bool res = item.value.indices.empty();
if (res) {
item.value.data->remove();
}
return res;
});
/* Update light intances and remove instances without transforms */
for (auto &l_inst : nonmesh_instances_.values()) {
update_nonmesh_instance(l_inst);
}
nonmesh_instances_.remove_if([&](auto item) { return item.value.transforms.empty(); });
/* Insert/remove/update instancer in RenderIndex */
pxr::HdRenderIndex &index = scene_delegate_->GetRenderIndex();
if (mesh_instances_.is_empty()) {
/* Important: removing instancer when nonmesh_instances_ are empty too */
if (index.HasInstancer(prim_id) && nonmesh_instances_.is_empty()) {
index.RemoveInstancer(prim_id);
ID_LOG(1, "Remove instancer");
}
}
else {
if (index.HasInstancer(prim_id)) {
index.GetChangeTracker().MarkInstancerDirty(prim_id, pxr::HdChangeTracker::AllDirty);
ID_LOG(1, "Update instancer");
}
else {
index.InsertInstancer(scene_delegate_, prim_id);
ID_LOG(1, "Insert instancer");
}
}
}
pxr::SdfPath InstancerData::object_prim_id(Object *object) const
{
/* Making id of object in form like <prefix>_<pointer in 16 hex digits format> */
char name[32];
snprintf(name, sizeof(name), "O_%p", object);
return prim_id.AppendElementString(name);
}
pxr::SdfPath InstancerData::nonmesh_prim_id(pxr::SdfPath const &prim_id, int index) const
{
char name[16];
snprintf(name, sizeof(name), "NM_%08d", index);
return prim_id.AppendElementString(name);
}
int InstancerData::nonmesh_prim_id_index(pxr::SdfPath const &id) const
{
int index;
sscanf(id.GetName().c_str(), "NM_%d", &index);
return index;
}
void InstancerData::update_nonmesh_instance(NonmeshInstance &nm_inst)
{
ObjectData *obj_data = nm_inst.data.get();
pxr::SdfPath prev_id = nm_inst.data->prim_id;
int i;
/* Remove old light instances */
while (nm_inst.count > nm_inst.transforms.size()) {
--nm_inst.count;
obj_data->prim_id = nonmesh_prim_id(prev_id, nm_inst.count);
obj_data->remove();
}
/* Update current light instances */
LightData *l_data = dynamic_cast<LightData *>(obj_data);
if (l_data && l_data->prim_type((Light *)((Object *)l_data->id)->data) != l_data->prim_type_) {
/* Special case: recreate instances when prim_type was changed */
for (i = 0; i < nm_inst.count; ++i) {
obj_data->prim_id = nonmesh_prim_id(prev_id, i);
obj_data->remove();
}
l_data->init();
for (i = 0; i < nm_inst.count; ++i) {
obj_data->prim_id = nonmesh_prim_id(prev_id, i);
obj_data->insert();
}
}
else {
for (i = 0; i < nm_inst.count; ++i) {
obj_data->prim_id = nonmesh_prim_id(prev_id, i);
obj_data->update();
}
}
/* Add new light instances */
while (nm_inst.count < nm_inst.transforms.size()) {
obj_data->prim_id = nonmesh_prim_id(prev_id, nm_inst.count);
obj_data->insert();
++nm_inst.count;
}
obj_data->prim_id = prev_id;
}
InstancerData::MeshInstance *InstancerData::mesh_instance(pxr::SdfPath const &id) const
{
auto m_inst = mesh_instances_.lookup_ptr(id.GetPathElementCount() == 4 ? id.GetParentPath() :
id);
if (!m_inst) {
return nullptr;
}
return const_cast<MeshInstance *>(m_inst);
}
InstancerData::NonmeshInstance *InstancerData::nonmesh_instance(pxr::SdfPath const &id) const
{
auto nm_inst = nonmesh_instances_.lookup_ptr(id.GetPathElementCount() == 4 ? id.GetParentPath() :
id);
if (!nm_inst) {
return nullptr;
}
return const_cast<NonmeshInstance *>(nm_inst);
}
} // namespace blender::io::hydra

View File

@ -1,16 +1,14 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
#include "BKE_duplilist.h"
#include "BLI_map.hh" #include "BLI_map.hh"
#include "BLI_set.hh" #include "BLI_set.hh"
#include "light.h"
#include "mesh.h" #include "mesh.h"
namespace blender::render::hydra { namespace blender::io::hydra {
class InstancerData : public IdData { class InstancerData : public IdData {
struct MeshInstance { struct MeshInstance {
@ -18,15 +16,19 @@ class InstancerData : public IdData {
pxr::VtIntArray indices; pxr::VtIntArray indices;
}; };
struct LightInstance { struct NonmeshInstance {
std::unique_ptr<LightData> data; std::unique_ptr<ObjectData> data;
pxr::VtMatrix4dArray transforms; pxr::VtMatrix4dArray transforms;
int count = 0; int count = 0;
}; };
private:
Map<pxr::SdfPath, MeshInstance> mesh_instances_;
Map<pxr::SdfPath, NonmeshInstance> nonmesh_instances_;
pxr::VtMatrix4dArray mesh_transforms_;
public: public:
InstancerData(BlenderSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id); InstancerData(HydraSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id);
static bool is_instance_supported(Object *object);
void init() override; void init() override;
void insert() override; void insert() override;
@ -34,7 +36,7 @@ class InstancerData : public IdData {
void update() override; void update() override;
pxr::VtValue get_data(pxr::TfToken const &key) const override; pxr::VtValue get_data(pxr::TfToken const &key) const override;
pxr::GfMatrix4d get_transform(pxr::SdfPath const &id) const; pxr::GfMatrix4d transform(pxr::SdfPath const &id) const;
pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation) const; pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation) const;
pxr::VtIntArray indices(pxr::SdfPath const &id) const; pxr::VtIntArray indices(pxr::SdfPath const &id) const;
ObjectData *object_data(pxr::SdfPath const &id) const; ObjectData *object_data(pxr::SdfPath const &id) const;
@ -54,15 +56,11 @@ class InstancerData : public IdData {
private: private:
pxr::SdfPath object_prim_id(Object *object) const; pxr::SdfPath object_prim_id(Object *object) const;
pxr::SdfPath light_prim_id(LightInstance const &inst, int index) const; pxr::SdfPath nonmesh_prim_id(pxr::SdfPath const &prim_id, int index) const;
int light_prim_id_index(pxr::SdfPath const &id) const; int nonmesh_prim_id_index(pxr::SdfPath const &id) const;
void update_light_instance(LightInstance &inst); void update_nonmesh_instance(NonmeshInstance &inst);
MeshInstance *mesh_instance(pxr::SdfPath const &id) const; MeshInstance *mesh_instance(pxr::SdfPath const &id) const;
LightInstance *light_instance(pxr::SdfPath const &id) const; NonmeshInstance *nonmesh_instance(pxr::SdfPath const &id) const;
Map<pxr::SdfPath, MeshInstance> mesh_instances_;
Map<pxr::SdfPath, LightInstance> light_instances_;
pxr::VtMatrix4dArray mesh_transforms_;
}; };
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,21 +1,21 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include <boost/algorithm/string/predicate.hpp> #include "light.h"
#include <pxr/imaging/hd/light.h> #include <pxr/imaging/hd/light.h>
#include <pxr/imaging/hd/tokens.h> #include <pxr/imaging/hd/tokens.h>
#include <pxr/usd/usdLux/tokens.h> #include <pxr/usd/usdLux/tokens.h>
#include "BLI_math_rotation.h"
#include "DNA_light_types.h" #include "DNA_light_types.h"
#include "blender_scene_delegate.h" #include "BLI_math_rotation.h"
#include "light.h"
namespace blender::render::hydra { #include "hydra_scene_delegate.h"
LightData::LightData(BlenderSceneDelegate *scene_delegate, namespace blender::io::hydra {
LightData::LightData(HydraSceneDelegate *scene_delegate,
Object *object, Object *object,
pxr::SdfPath const &prim_id) pxr::SdfPath const &prim_id)
: ObjectData(scene_delegate, object, prim_id) : ObjectData(scene_delegate, object, prim_id)
@ -179,4 +179,4 @@ pxr::TfToken LightData::prim_type(Light *light)
} }
} }
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,9 +1,9 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
#include "pxr/base/tf/hashmap.h" #include <pxr/base/tf/hashmap.h>
#include <pxr/usd/sdf/assetPath.h> #include <pxr/usd/sdf/assetPath.h>
#include <pxr/usd/sdf/path.h> #include <pxr/usd/sdf/path.h>
@ -11,15 +11,19 @@
#include "object.h" #include "object.h"
namespace blender::render::hydra { namespace blender::io::hydra {
class InstancerData; class InstancerData;
class LightData : public ObjectData { class LightData : public ObjectData {
friend InstancerData; friend InstancerData;
protected:
std::map<pxr::TfToken, pxr::VtValue> data_;
pxr::TfToken prim_type_;
public: public:
LightData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id); LightData(HydraSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id);
void init() override; void init() override;
void insert() override; void insert() override;
@ -30,9 +34,6 @@ class LightData : public ObjectData {
protected: protected:
pxr::TfToken prim_type(Light *light); pxr::TfToken prim_type(Light *light);
std::map<pxr::TfToken, pxr::VtValue> data_;
pxr::TfToken prim_type_;
}; };
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,5 +1,7 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "material.h"
#include <Python.h> #include <Python.h>
#include <unicodeobject.h> #include <unicodeobject.h>
@ -8,21 +10,38 @@
#include <pxr/imaging/hd/renderDelegate.h> #include <pxr/imaging/hd/renderDelegate.h>
#include <pxr/imaging/hd/tokens.h> #include <pxr/imaging/hd/tokens.h>
#ifdef WITH_MATERIALX
# include <pxr/base/arch/fileSystem.h>
# include <pxr/usd/ar/resolver.h>
# include <pxr/usd/ar/resolverContextBinder.h>
# include <pxr/usd/ar/resolverScopedCache.h>
# include <pxr/usd/usdMtlx/reader.h>
# include <pxr/usd/usdMtlx/utils.h>
# include <pxr/usd/usdShade/material.h>
# include <pxr/usd/usdShade/shader.h>
# include <pxr/usdImaging/usdImaging/materialParamUtils.h>
#endif
#include "MEM_guardedalloc.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "MEM_guardedalloc.h" #include "RNA_access.h"
#include "RNA_blender_cpp.h" #include "RNA_prototypes.h"
#include "RNA_types.h"
#include "bpy_rna.h" #include "bpy_rna.h"
#include "../engine.h" #include "hydra_scene_delegate.h"
#include "blender_scene_delegate.h"
#include "material.h"
#include "mtlx_hydra_adapter.h"
namespace blender::render::hydra { namespace blender::io::hydra {
MaterialData::MaterialData(BlenderSceneDelegate *scene_delegate, MaterialData::MaterialData(HydraSceneDelegate *scene_delegate,
Material *material, Material *material,
pxr::SdfPath const &prim_id) pxr::SdfPath const &prim_id)
: IdData(scene_delegate, (ID *)material, prim_id) : IdData(scene_delegate, (ID *)material, prim_id)
@ -152,6 +171,64 @@ void MaterialData::export_mtlx()
ID_LOGN(1, "mtlx=%s", mtlx_path_.GetResolvedPath().c_str()); ID_LOGN(1, "mtlx=%s", mtlx_path_.GetResolvedPath().c_str());
} }
#ifdef WITH_MATERIALX
static void hdmtlx_convert_to_materialnetworkmap(std::string const &mtlx_path,
pxr::TfTokenVector const &shader_source_types,
pxr::TfTokenVector const &render_contexts,
pxr::HdMaterialNetworkMap *out)
{
if (mtlx_path.empty()) {
return;
}
std::string basePath = pxr::TfGetPathName(mtlx_path);
pxr::ArResolver &resolver = pxr::ArGetResolver();
const pxr::ArResolverContext context = resolver.CreateDefaultContextForAsset(mtlx_path);
pxr::ArResolverContextBinder binder(context);
pxr::ArResolverScopedCache resolver_cache;
std::string mtlxName = pxr::TfGetBaseName(mtlx_path);
std::string stage_id = pxr::TfStringPrintf(
"%s%s%s.usda", basePath.c_str(), ARCH_PATH_SEP, mtlxName.c_str());
pxr::UsdStageRefPtr stage = pxr::UsdStage::CreateInMemory(stage_id, context);
try {
MaterialX::DocumentPtr doc = pxr::UsdMtlxReadDocument(mtlx_path);
pxr::UsdMtlxRead(doc, stage);
}
catch (MaterialX::ExceptionFoundCycle &x) {
Tf_PostErrorHelper(pxr::TF_CALL_CONTEXT,
pxr::TF_DIAGNOSTIC_RUNTIME_ERROR_TYPE,
"MaterialX cycle found: %s\n",
x.what());
return;
}
catch (MaterialX::Exception &x) {
Tf_PostErrorHelper(pxr::TF_CALL_CONTEXT,
pxr::TF_DIAGNOSTIC_RUNTIME_ERROR_TYPE,
"MaterialX error: %s\n",
x.what());
return;
}
if (pxr::UsdPrim materials = stage->GetPrimAtPath(pxr::SdfPath("/MaterialX/Materials"))) {
if (pxr::UsdPrimSiblingRange children = materials.GetChildren()) {
if (auto material = pxr::UsdShadeMaterial(*children.begin())) {
if (pxr::UsdShadeShader mtlx_surface = material.ComputeSurfaceSource(render_contexts)) {
UsdImagingBuildHdMaterialNetworkFromTerminal(mtlx_surface.GetPrim(),
pxr::HdMaterialTerminalTokens->surface,
shader_source_types,
render_contexts,
out,
pxr::UsdTimeCode::Default());
}
}
}
}
}
#endif
void MaterialData::write_material_network_map() void MaterialData::write_material_network_map()
{ {
ID_LOGN(1, ""); ID_LOGN(1, "");
@ -165,10 +242,12 @@ void MaterialData::write_material_network_map()
pxr::TfTokenVector render_contexts = render_delegate->GetMaterialRenderContexts(); pxr::TfTokenVector render_contexts = render_delegate->GetMaterialRenderContexts();
pxr::HdMaterialNetworkMap network_map; pxr::HdMaterialNetworkMap network_map;
#ifdef WITH_MATERIALX
hdmtlx_convert_to_materialnetworkmap( hdmtlx_convert_to_materialnetworkmap(
mtlx_path_.GetResolvedPath(), shader_source_types, render_contexts, &network_map); mtlx_path_.GetResolvedPath(), shader_source_types, render_contexts, &network_map);
#endif
material_network_map_ = network_map; material_network_map_ = network_map;
} }
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
@ -7,16 +7,21 @@
#include <pxr/usd/sdf/assetPath.h> #include <pxr/usd/sdf/assetPath.h>
#include <pxr/usd/sdf/path.h> #include <pxr/usd/sdf/path.h>
#include "BLI_map.hh"
#include "DNA_material_types.h" #include "DNA_material_types.h"
#include "BLI_map.hh"
#include "id.h" #include "id.h"
namespace blender::render::hydra { namespace blender::io::hydra {
class MaterialData : public IdData { class MaterialData : public IdData {
private:
pxr::SdfAssetPath mtlx_path_;
pxr::VtValue material_network_map_;
public: public:
MaterialData(BlenderSceneDelegate *scene_delegate, MaterialData(HydraSceneDelegate *scene_delegate,
Material *material, Material *material,
pxr::SdfPath const &prim_id); pxr::SdfPath const &prim_id);
@ -34,11 +39,8 @@ class MaterialData : public IdData {
private: private:
void export_mtlx(); void export_mtlx();
void write_material_network_map(); void write_material_network_map();
pxr::SdfAssetPath mtlx_path_;
pxr::VtValue material_network_map_;
}; };
using MaterialDataMap = Map<pxr::SdfPath, std::unique_ptr<MaterialData>>; using MaterialDataMap = Map<pxr::SdfPath, std::unique_ptr<MaterialData>>;
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include <pxr/base/gf/vec2f.h> #include <pxr/base/gf/vec2f.h>
#include <pxr/base/tf/staticTokens.h> #include <pxr/base/tf/staticTokens.h>
@ -9,18 +9,16 @@
#include "BKE_mesh.hh" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "blender_scene_delegate.h" #include "hydra_scene_delegate.h"
#include "mesh.h" #include "mesh.h"
PXR_NAMESPACE_OPEN_SCOPE PXR_NAMESPACE_OPEN_SCOPE
TF_DEFINE_PRIVATE_TOKENS(tokens_, (st)); TF_DEFINE_PRIVATE_TOKENS(tokens_, (st));
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_CLOSE_SCOPE
namespace blender::render::hydra { namespace blender::io::hydra {
MeshData::MeshData(BlenderSceneDelegate *scene_delegate, MeshData::MeshData(HydraSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id)
Object *object,
pxr::SdfPath const &prim_id)
: ObjectData(scene_delegate, object, prim_id) : ObjectData(scene_delegate, object, prim_id)
{ {
} }
@ -119,7 +117,7 @@ void MeshData::available_materials(Set<pxr::SdfPath> &paths) const
} }
} }
pxr::HdMeshTopology MeshData::mesh_topology(pxr::SdfPath const &id) const pxr::HdMeshTopology MeshData::topology(pxr::SdfPath const &id) const
{ {
const SubMesh &sm = submesh(id); const SubMesh &sm = submesh(id);
return pxr::HdMeshTopology(pxr::PxOsdOpenSubdivTokens->none, return pxr::HdMeshTopology(pxr::PxOsdOpenSubdivTokens->none,
@ -202,14 +200,14 @@ void MeshData::write_materials()
pxr::SdfPath MeshData::submesh_prim_id(int index) const pxr::SdfPath MeshData::submesh_prim_id(int index) const
{ {
char name[16]; char name[16];
snprintf(name, sizeof(name), "SM_%04x", index); snprintf(name, sizeof(name), "SM_%04d", index);
return prim_id.AppendElementString(name); return prim_id.AppendElementString(name);
} }
const MeshData::SubMesh &MeshData::submesh(pxr::SdfPath const &id) const const MeshData::SubMesh &MeshData::submesh(pxr::SdfPath const &id) const
{ {
int index; int index;
sscanf(id.GetName().c_str(), "SM_%x", &index); sscanf(id.GetName().c_str(), "SM_%d", &index);
return submeshes_[index]; return submeshes_[index];
} }
@ -301,4 +299,4 @@ void MeshData::update_prims()
submeshes_count_ = submeshes_.size(); submeshes_count_ = submeshes_.size();
} }
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,18 +1,19 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
#include <pxr/base/vt/array.h> #include <pxr/base/vt/array.h>
#include <pxr/imaging/hd/sceneDelegate.h> #include <pxr/imaging/hd/sceneDelegate.h>
#include "BKE_duplilist.h"
#include "BLI_set.hh" #include "BLI_set.hh"
#include "BKE_duplilist.h"
#include "material.h" #include "material.h"
#include "object.h" #include "object.h"
namespace blender::render::hydra { namespace blender::io::hydra {
class MeshData : public ObjectData { class MeshData : public ObjectData {
struct SubMesh { struct SubMesh {
@ -24,8 +25,13 @@ class MeshData : public ObjectData {
MaterialData *mat_data = nullptr; MaterialData *mat_data = nullptr;
}; };
private:
pxr::VtVec3fArray vertices_;
std::vector<SubMesh> submeshes_;
int submeshes_count_ = 0;
public: public:
MeshData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id); MeshData(HydraSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id);
void init() override; void init() override;
void insert() override; void insert() override;
@ -37,7 +43,7 @@ class MeshData : public ObjectData {
pxr::SdfPath material_id(pxr::SdfPath const &id) const override; pxr::SdfPath material_id(pxr::SdfPath const &id) const override;
void available_materials(Set<pxr::SdfPath> &paths) const override; void available_materials(Set<pxr::SdfPath> &paths) const override;
pxr::HdMeshTopology mesh_topology(pxr::SdfPath const &id) const; pxr::HdMeshTopology topology(pxr::SdfPath const &id) const;
pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation) const; pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation) const;
pxr::HdCullStyle cull_style(pxr::SdfPath const &id) const; pxr::HdCullStyle cull_style(pxr::SdfPath const &id) const;
bool double_sided(pxr::SdfPath const &id) const; bool double_sided(pxr::SdfPath const &id) const;
@ -52,10 +58,6 @@ class MeshData : public ObjectData {
const SubMesh &submesh(pxr::SdfPath const &id) const; const SubMesh &submesh(pxr::SdfPath const &id) const;
void write_submeshes(Mesh *mesh); void write_submeshes(Mesh *mesh);
void update_prims(); void update_prims();
pxr::VtVec3fArray vertices_;
std::vector<SubMesh> submeshes_;
int submeshes_count_ = 0;
}; };
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,30 +1,29 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "DEG_depsgraph_query.h" #include "DEG_depsgraph_query.h"
#include "blender_scene_delegate.h"
#include "curves.h" #include "curves.h"
#include "hydra_scene_delegate.h"
#include "light.h" #include "light.h"
#include "mesh.h" #include "mesh.h"
#include "object.h" #include "object.h"
#include "volume.h" #include "volume.h"
namespace blender::render::hydra { namespace blender::io::hydra {
ObjectData::ObjectData(BlenderSceneDelegate *scene_delegate, ObjectData::ObjectData(HydraSceneDelegate *scene_delegate,
Object *object, Object *object,
pxr::SdfPath const &prim_id) pxr::SdfPath const &prim_id)
: IdData(scene_delegate, (ID *)object, prim_id), transform(pxr::GfMatrix4d(1.0)) : IdData(scene_delegate, (ID *)object, prim_id), transform(pxr::GfMatrix4d(1.0))
{ {
} }
std::unique_ptr<ObjectData> ObjectData::create(BlenderSceneDelegate *scene_delegate, std::unique_ptr<ObjectData> ObjectData::create(HydraSceneDelegate *scene_delegate,
Object *object, Object *object,
pxr::SdfPath const &prim_id) pxr::SdfPath const &prim_id)
{ {
std::unique_ptr<ObjectData> obj_data; std::unique_ptr<ObjectData> obj_data;
switch (object->type) { switch (object->type) {
case OB_MESH: case OB_MESH:
case OB_SURF: case OB_SURF:
@ -73,7 +72,25 @@ bool ObjectData::is_supported(Object *object)
return false; return false;
} }
bool ObjectData::is_visible(BlenderSceneDelegate *scene_delegate, Object *object, int mode) bool ObjectData::is_mesh(Object *object)
{
switch (object->type) {
case OB_MESH:
case OB_SURF:
case OB_FONT:
case OB_CURVES_LEGACY:
case OB_MBALL:
if (VolumeModifierData::is_volume_modifier(object)) {
return false;
}
return true;
default:
break;
}
return false;
}
bool ObjectData::is_visible(HydraSceneDelegate *scene_delegate, Object *object, int mode)
{ {
eEvaluationMode deg_mode = DEG_get_mode(scene_delegate->depsgraph); eEvaluationMode deg_mode = DEG_get_mode(scene_delegate->depsgraph);
bool ret = BKE_object_visibility(object, deg_mode) & mode; bool ret = BKE_object_visibility(object, deg_mode) & mode;
@ -84,7 +101,7 @@ bool ObjectData::is_visible(BlenderSceneDelegate *scene_delegate, Object *object
return ret; return ret;
} }
pxr::VtValue ObjectData::get_data(pxr::SdfPath const &id, pxr::TfToken const &key) const pxr::VtValue ObjectData::get_data(pxr::SdfPath const & /* id */, pxr::TfToken const &key) const
{ {
return get_data(key); return get_data(key);
} }
@ -94,12 +111,12 @@ pxr::SdfPath ObjectData::material_id() const
return pxr::SdfPath(); return pxr::SdfPath();
} }
pxr::SdfPath ObjectData::material_id(pxr::SdfPath const &id) const pxr::SdfPath ObjectData::material_id(pxr::SdfPath const & /* id */) const
{ {
return material_id(); return material_id();
} }
void ObjectData::available_materials(Set<pxr::SdfPath> &paths) const {} void ObjectData::available_materials(Set<pxr::SdfPath> & /* paths */) const {}
void ObjectData::write_transform() void ObjectData::write_transform()
{ {
@ -137,4 +154,4 @@ pxr::GfMatrix4d gf_matrix_from_transform(float m[4][4])
return ret; return ret;
} }
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,31 +1,34 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
#include "pxr/base/tf/hashmap.h"
#include <pxr/base/gf/matrix4d.h> #include <pxr/base/gf/matrix4d.h>
#include <pxr/base/tf/hashmap.h>
#include "DNA_object_types.h"
#include "BLI_map.hh"
#include "BLI_set.hh"
#include "BKE_layer.h" #include "BKE_layer.h"
#include "BKE_object.h" #include "BKE_object.h"
#include "BLI_map.hh"
#include "BLI_set.hh"
#include "DNA_object_types.h"
#include "id.h" #include "id.h"
#include "material.h" #include "material.h"
namespace blender::render::hydra { namespace blender::io::hydra {
class ObjectData : public IdData { class ObjectData : public IdData {
public: public:
ObjectData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id); ObjectData(HydraSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id);
static std::unique_ptr<ObjectData> create(BlenderSceneDelegate *scene_delegate, static std::unique_ptr<ObjectData> create(HydraSceneDelegate *scene_delegate,
Object *object, Object *object,
pxr::SdfPath const &prim_id); pxr::SdfPath const &prim_id);
static bool is_supported(Object *object); static bool is_supported(Object *object);
static bool is_visible(BlenderSceneDelegate *scene_delegate, static bool is_mesh(Object *object);
static bool is_visible(HydraSceneDelegate *scene_delegate,
Object *object, Object *object,
int mode = OB_VISIBLE_SELF); int mode = OB_VISIBLE_SELF);
@ -48,4 +51,4 @@ using ObjectDataMap = Map<pxr::SdfPath, std::unique_ptr<ObjectData>>;
pxr::GfMatrix4d gf_matrix_from_transform(float m[4][4]); pxr::GfMatrix4d gf_matrix_from_transform(float m[4][4]);
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* SPDX-FileCopyrightText: 2011-2023 Blender Foundation */
#pragma once
#include <pxr/base/tf/token.h>
#include "BLI_map.hh"
namespace blender::io::hydra {
struct HydraDelegateSettings {
pxr::TfToken mx_filename_key;
Map<pxr::TfToken, pxr::VtValue> render_tokens;
};
}; // namespace blender::io::hydra

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "usd_scene_delegate.hh" #include "usd_scene_delegate.h"
#include "BLI_fileops.h" #include "BLI_fileops.h"
#include "BLI_path_util.h" #include "BLI_path_util.h"
@ -14,11 +14,11 @@
#include "usd.h" #include "usd.h"
#include "usd.hh" #include "usd.hh"
namespace blender::render::hydra { namespace blender::io::hydra {
USDSceneDelegate::USDSceneDelegate(pxr::HdRenderIndex *render_index, USDSceneDelegate::USDSceneDelegate(pxr::HdRenderIndex *render_index,
pxr::SdfPath const &delegate_id, pxr::SdfPath const &delegate_id,
const SceneDelegateSettings &settings) const HydraDelegateSettings &settings)
: render_index_(render_index), delegate_id_(delegate_id), settings_(settings) : render_index_(render_index), delegate_id_(delegate_id), settings_(settings)
{ {
/* Temporary directory to write any additional files to, like image or VDB files. */ /* Temporary directory to write any additional files to, like image or VDB files. */
@ -42,7 +42,7 @@ USDSceneDelegate::~USDSceneDelegate()
BLI_delete(temp_dir_.c_str(), true, true); BLI_delete(temp_dir_.c_str(), true, true);
} }
void USDSceneDelegate::populate(Depsgraph *depsgraph, bContext * /*context*/) void USDSceneDelegate::populate(Depsgraph *depsgraph)
{ {
/* TODO: implement MaterialX support in USD exporter. */ /* TODO: implement MaterialX support in USD exporter. */
const bool use_materialx = !settings_.mx_filename_key.IsEmpty(); const bool use_materialx = !settings_.mx_filename_key.IsEmpty();
@ -76,4 +76,4 @@ void USDSceneDelegate::populate(Depsgraph *depsgraph, bContext * /*context*/)
delegate_->Populate(stage_->GetPseudoRoot()); delegate_->Populate(stage_->GetPseudoRoot());
} }
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,27 +1,27 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation */ * SPDX-FileCopyrightText: 2023 Blender Foundation */
#pragma once #pragma once
#include <string>
#include <pxr/imaging/hd/renderIndex.h> #include <pxr/imaging/hd/renderIndex.h>
#include <pxr/usdImaging/usdImaging/delegate.h> #include <pxr/usdImaging/usdImaging/delegate.h>
#include <string>
#include "settings.h" #include "settings.h"
struct Depsgraph; struct Depsgraph;
struct bContext;
namespace blender::render::hydra { namespace blender::io::hydra {
/* Populate Hydra render index using USD file export, for testing. */ /* Populate Hydra render index using USD file export, for testing. */
class USDSceneDelegate { class USDSceneDelegate {
private:
pxr::HdRenderIndex *render_index_; pxr::HdRenderIndex *render_index_;
pxr::SdfPath const delegate_id_; pxr::SdfPath const delegate_id_;
pxr::UsdStageRefPtr stage_; pxr::UsdStageRefPtr stage_;
std::unique_ptr<pxr::UsdImagingDelegate> delegate_; std::unique_ptr<pxr::UsdImagingDelegate> delegate_;
const SceneDelegateSettings &settings_; const HydraDelegateSettings &settings_;
std::string temp_dir_; std::string temp_dir_;
std::string temp_file_; std::string temp_file_;
@ -29,10 +29,10 @@ class USDSceneDelegate {
public: public:
USDSceneDelegate(pxr::HdRenderIndex *render_index, USDSceneDelegate(pxr::HdRenderIndex *render_index,
pxr::SdfPath const &delegate_id, pxr::SdfPath const &delegate_id,
const SceneDelegateSettings &settings_); const HydraDelegateSettings &settings_);
~USDSceneDelegate(); ~USDSceneDelegate();
void populate(Depsgraph *depsgraph, bContext *context); void populate(Depsgraph *depsgraph);
}; };
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include <pxr/imaging/hd/bprim.h> #include <pxr/imaging/hd/bprim.h>
#include <pxr/imaging/hd/tokens.h> #include <pxr/imaging/hd/tokens.h>
@ -13,12 +13,12 @@
#include "BLI_index_range.hh" #include "BLI_index_range.hh"
#include "DNA_volume_types.h" #include "DNA_volume_types.h"
#include "blender_scene_delegate.h" #include "hydra_scene_delegate.h"
#include "volume.h" #include "volume.h"
namespace blender::render::hydra { namespace blender::io::hydra {
VolumeData::VolumeData(BlenderSceneDelegate *scene_delegate, VolumeData::VolumeData(HydraSceneDelegate *scene_delegate,
Object *object, Object *object,
pxr::SdfPath const &prim_id) pxr::SdfPath const &prim_id)
: ObjectData(scene_delegate, object, prim_id) : ObjectData(scene_delegate, object, prim_id)
@ -30,8 +30,7 @@ void VolumeData::init()
field_descriptors_.clear(); field_descriptors_.clear();
Volume *volume = (Volume *)((Object *)this->id)->data; Volume *volume = (Volume *)((Object *)this->id)->data;
Main *main = CTX_data_main(scene_delegate_->context); if (!BKE_volume_load(volume, scene_delegate_->bmain)) {
if (!BKE_volume_load(volume, main)) {
return; return;
} }
filepath_ = BKE_volume_grids_frame_filepath(volume); filepath_ = BKE_volume_grids_frame_filepath(volume);
@ -160,4 +159,4 @@ void VolumeData::write_materials()
mat_data_ = get_or_create_material(mat); mat_data_ = get_or_create_material(mat);
} }
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
@ -7,12 +7,16 @@
#include "object.h" #include "object.h"
namespace blender::render::hydra { namespace blender::io::hydra {
class VolumeData : public ObjectData { class VolumeData : public ObjectData {
protected:
std::string filepath_;
pxr::HdVolumeFieldDescriptorVector field_descriptors_;
MaterialData *mat_data_ = nullptr;
public: public:
VolumeData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id); VolumeData(HydraSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id);
void init() override; void init() override;
void insert() override; void insert() override;
@ -28,10 +32,6 @@ class VolumeData : public ObjectData {
protected: protected:
void write_materials() override; void write_materials() override;
std::string filepath_;
pxr::HdVolumeFieldDescriptorVector field_descriptors_;
MaterialData *mat_data_ = nullptr;
}; };
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,24 +1,27 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "volume_modifier.h"
#include <pxr/usdImaging/usdVolImaging/tokens.h> #include <pxr/usdImaging/usdVolImaging/tokens.h>
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BLI_path_util.h"
#include "DNA_scene_types.h" #include "DNA_scene_types.h"
#include "DNA_volume_types.h" #include "DNA_volume_types.h"
#include "blender_scene_delegate.h" #include "BLI_path_util.h"
#include "volume_modifier.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "hydra_scene_delegate.h"
PXR_NAMESPACE_OPEN_SCOPE PXR_NAMESPACE_OPEN_SCOPE
TF_DEFINE_PRIVATE_TOKENS(grid_tokens_, (density)(flame)(shadow)(temperature)(velocity)); TF_DEFINE_PRIVATE_TOKENS(grid_tokens_, (density)(flame)(shadow)(temperature)(velocity));
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_CLOSE_SCOPE
namespace blender::render::hydra { namespace blender::io::hydra {
VolumeModifierData::VolumeModifierData(BlenderSceneDelegate *scene_delegate, VolumeModifierData::VolumeModifierData(HydraSceneDelegate *scene_delegate,
Object *object, Object *object,
pxr::SdfPath const &prim_id) pxr::SdfPath const &prim_id)
: VolumeData(scene_delegate, object, prim_id) : VolumeData(scene_delegate, object, prim_id)
@ -128,4 +131,4 @@ std::string VolumeModifierData::get_cached_file_path(std::string directory, int
return file_path; return file_path;
} }
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
@ -7,12 +7,12 @@
#include "volume.h" #include "volume.h"
namespace blender::render::hydra { namespace blender::io::hydra {
class VolumeModifierData : public VolumeData { class VolumeModifierData : public VolumeData {
public: public:
VolumeModifierData(BlenderSceneDelegate *scene_delegate, VolumeModifierData(HydraSceneDelegate *scene_delegate,
Object *object, Object *object,
pxr::SdfPath const &prim_id); pxr::SdfPath const &prim_id);
static bool is_volume_modifier(Object *object); static bool is_volume_modifier(Object *object);
@ -29,4 +29,4 @@ class VolumeModifierData : public VolumeData {
FluidModifierData *modifier_; FluidModifierData *modifier_;
}; };
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include <filesystem> #include "world.h"
#include <pxr/base/gf/rotation.h> #include <pxr/base/gf/rotation.h>
#include <pxr/base/gf/vec2f.h> #include <pxr/base/gf/vec2f.h>
@ -11,28 +11,28 @@
#include <pxr/imaging/hd/tokens.h> #include <pxr/imaging/hd/tokens.h>
#include <pxr/usd/usdLux/tokens.h> #include <pxr/usd/usdLux/tokens.h>
#include "BKE_context.h"
#include "DNA_node_types.h" #include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "BLI_math_rotation.h"
#include "BLI_path_util.h"
#include "BKE_node.h" #include "BKE_node.h"
#include "BKE_node_runtime.hh" #include "BKE_node_runtime.hh"
#include "BKE_studiolight.h" #include "BKE_studiolight.h"
#include "BLI_math_rotation.h"
#include "BLI_path_util.h"
#include "NOD_shader.h" #include "NOD_shader.h"
#include "../engine.h" #include "hydra_scene_delegate.h"
#include "blender_scene_delegate.h"
#include "image.h" #include "image.h"
#include "world.h"
/* TODO : add custom tftoken "transparency"? */ /* TODO : add custom tftoken "transparency"? */
/* NOTE: opacity and blur aren't supported by USD */ /* NOTE: opacity and blur aren't supported by USD */
namespace blender::render::hydra { namespace blender::io::hydra {
WorldData::WorldData(BlenderSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id) WorldData::WorldData(HydraSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id)
: LightData(scene_delegate, nullptr, prim_id) : LightData(scene_delegate, nullptr, prim_id)
{ {
prim_type_ = pxr::HdPrimTypeTokens->domeLight; prim_type_ = pxr::HdPrimTypeTokens->domeLight;
@ -79,8 +79,8 @@ void WorldData::init()
return; return;
} }
bNodeSocket color_input = input_node->input_by_identifier("Color"); const bNodeSocket &color_input = input_node->input_by_identifier("Color");
bNodeSocket strength_input = input_node->input_by_identifier("Strength"); const bNodeSocket &strength_input = input_node->input_by_identifier("Strength");
float const *strength = strength_input.default_value_typed<float>(); float const *strength = strength_input.default_value_typed<float>();
float const *input_color = color_input.default_value_typed<float>(); float const *input_color = color_input.default_value_typed<float>();
@ -94,7 +94,7 @@ void WorldData::init()
Image *image = (Image *)color_input_node->id; Image *image = (Image *)color_input_node->id;
if (image) { if (image) {
std::string image_path = cache_or_get_image_file( std::string image_path = cache_or_get_image_file(
image, scene_delegate_->context, &tex->iuser); scene_delegate_->bmain, scene_delegate_->scene, image, &tex->iuser);
if (!image_path.empty()) { if (!image_path.empty()) {
texture_file = pxr::SdfAssetPath(image_path, image_path); texture_file = pxr::SdfAssetPath(image_path, image_path);
} }
@ -153,4 +153,4 @@ void WorldData::write_transform()
} }
} }
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1,12 +1,12 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
#include <map> #include <map>
#include "pxr/base/tf/staticTokens.h"
#include <pxr/base/gf/matrix4d.h> #include <pxr/base/gf/matrix4d.h>
#include <pxr/base/tf/staticTokens.h>
#include <pxr/base/vt/value.h> #include <pxr/base/vt/value.h>
#include <pxr/usd/sdf/assetPath.h> #include <pxr/usd/sdf/assetPath.h>
#include <pxr/usd/sdf/path.h> #include <pxr/usd/sdf/path.h>
@ -16,11 +16,13 @@
#include "light.h" #include "light.h"
namespace blender::render::hydra { namespace blender::io::hydra {
class WorldData : public LightData { class WorldData : public LightData {
public: public:
WorldData(BlenderSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id); pxr::GfMatrix4d transform;
WorldData(HydraSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id);
void init() override; void init() override;
void update() override; void update() override;
@ -29,4 +31,4 @@ class WorldData : public LightData {
void write_transform() override; void write_transform() override;
}; };
} // namespace blender::render::hydra } // namespace blender::io::hydra

View File

@ -1007,6 +1007,14 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_define_verify_sdna(1); 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) static void rna_def_render_result(BlenderRNA *brna)
{ {
StructRNA *srna; StructRNA *srna;
@ -1235,6 +1243,7 @@ static void rna_def_render_pass(BlenderRNA *brna)
void RNA_def_render(BlenderRNA *brna) void RNA_def_render(BlenderRNA *brna)
{ {
rna_def_render_engine(brna); rna_def_render_engine(brna);
rna_def_hydra_render_engine(brna);
rna_def_render_result(brna); rna_def_render_result(brna);
rna_def_render_view(brna); rna_def_render_view(brna);
rna_def_render_layer(brna); rna_def_render_layer(brna);

View File

@ -1,9 +1,18 @@
# SPDX-FileCopyrightText: 2011-2022 Blender Foundation
#
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# Copyright 2011-2022 Blender Foundation
# This suppresses the warning "This file includes at least one deprecated or antiquated
# header which may be removed without further notice at a future date", which is caused
# by the USD library including <ext/hash_set> on Linux. This has been reported at:
# https://github.com/PixarAnimationStudios/USD/issues/1057.
if(UNIX AND NOT APPLE)
add_definitions(-D_GLIBCXX_PERMIT_BACKWARD_HASH)
endif()
if(WIN32) if(WIN32)
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -DBOOST_DEBUG_PYTHON) add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -DBOOST_DEBUG_PYTHON)
endif() endif()
add_definitions(-DBOOST_ALL_NO_LIB)
# Precompiled Linux libs are made with GCC, and USD uses some extensions # Precompiled Linux libs are made with GCC, and USD uses some extensions
# which lead to an incompatible ABI for Clang. Using those extensions with # which lead to an incompatible ABI for Clang. Using those extensions with
@ -12,7 +21,6 @@ if(UNIX AND NOT APPLE)
if(CMAKE_C_COMPILER_ID MATCHES "Clang") if(CMAKE_C_COMPILER_ID MATCHES "Clang")
if(EXISTS ${LIBDIR}) if(EXISTS ${LIBDIR})
add_definitions(-DARCH_HAS_GNU_STL_EXTENSIONS) add_definitions(-DARCH_HAS_GNU_STL_EXTENSIONS)
add_cxx_flag("-Wno-deprecated")
endif() endif()
endif() endif()
endif() endif()
@ -20,15 +28,11 @@ endif()
# USD headers use deprecated TBB headers, silence warning. # USD headers use deprecated TBB headers, silence warning.
add_definitions(-DTBB_SUPPRESS_DEPRECATED_MESSAGES=1) add_definitions(-DTBB_SUPPRESS_DEPRECATED_MESSAGES=1)
add_definitions(${GFLAGS_DEFINES})
add_definitions(-DBLENDER_GFLAGS_NAMESPACE=${GFLAGS_NAMESPACE})
add_definitions(-DBOOST_ALL_NO_LIB)
if(WIN32) if(WIN32)
# Some USD library headers trigger the "unreferenced formal parameter" warning alert. # Some USD library headers trigger the "unreferenced formal parameter"
# warning alert.
# Silence them by restore warn C4100 back to w4 # Silence them by restore warn C4100 back to w4
remove_cc_flag(/w34100) remove_cc_flag("/w34100")
endif() endif()
set(INC set(INC
@ -46,8 +50,9 @@ set(INC
../../gpu ../../gpu
../../gpu/intern ../../gpu/intern
../../python/intern ../../python/intern
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
.. ..
${CMAKE_BINARY_DIR}/source/blender/makesrna/intern
) )
set(INC_SYS set(INC_SYS
@ -65,64 +70,27 @@ set(LIB
${BOOST_LIBRARIES} ${BOOST_LIBRARIES}
${USD_LIBRARIES} ${USD_LIBRARIES}
${TBB_LIBRARIES} ${TBB_LIBRARIES}
bf_usd
) )
if(WITH_MATERIALX)
add_definitions(-DWITH_MATERIALX)
list(APPEND LIB MaterialXCore)
endif()
set(SRC set(SRC
python.cc
camera.h
camera.cc
engine.h
engine.cc engine.cc
final_engine.h
final_engine.cc final_engine.cc
preview_engine.h light_tasks_delegate.cc
preview_engine.cc preview_engine.cc
viewport_engine.h python.cc
render_task_delegate.cc
viewport_engine.cc viewport_engine.cc
render_task_delegate.cc engine.h
render_task_delegate.h final_engine.h
light_tasks_delegate.cc
light_tasks_delegate.h light_tasks_delegate.h
preview_engine.h
settings.h render_task_delegate.h
viewport_engine.h
scene_delegate/blender_scene_delegate.cc
scene_delegate/blender_scene_delegate.h
scene_delegate/curves.cc
scene_delegate/curves.h
scene_delegate/id.cc
scene_delegate/id.h
scene_delegate/image.cc
scene_delegate/image.h
scene_delegate/instancer.cc
scene_delegate/instancer.h
scene_delegate/light.cc
scene_delegate/light.h
scene_delegate/material.cc
scene_delegate/material.h
scene_delegate/mesh.cc
scene_delegate/mesh.h
scene_delegate/mtlx_hydra_adapter.cc
scene_delegate/mtlx_hydra_adapter.h
scene_delegate/object.cc
scene_delegate/object.h
scene_delegate/usd_scene_delegate.cc
scene_delegate/usd_scene_delegate.hh
scene_delegate/volume.cc
scene_delegate/volume.h
scene_delegate/volume_modifier.cc
scene_delegate/volume_modifier.h
scene_delegate/world.cc
scene_delegate/world.h
) )
blender_add_lib(bf_render_hydra "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") blender_add_lib(bf_render_hydra "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# RNA_prototypes.h
add_dependencies(bf_render_hydra bf_rna) add_dependencies(bf_render_hydra bf_rna)

View File

@ -1,5 +1,7 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "engine.h"
#include <pxr/base/plug/plugin.h> #include <pxr/base/plug/plugin.h>
#include <pxr/base/plug/registry.h> #include <pxr/base/plug/registry.h>
@ -10,18 +12,22 @@
#include "BLI_path_util.h" #include "BLI_path_util.h"
#include "BKE_context.h"
#include "GPU_context.h" #include "GPU_context.h"
#include "DEG_depsgraph_query.h" #include "DEG_depsgraph_query.h"
#include "engine.h" #include "RE_engine.h"
#include "CLG_log.h"
namespace blender::render::hydra { namespace blender::render::hydra {
CLG_LOGREF_DECLARE_GLOBAL(LOG_RENDER_HYDRA, "render.hydra"); CLG_LOGREF_DECLARE_GLOBAL(LOG_RENDER_HYDRA, "render.hydra");
Engine::Engine(RenderEngine *bl_engine, const std::string &render_delegate_name) Engine::Engine(RenderEngine *bl_engine, const std::string &render_delegate_name)
: render_delegate_name(render_delegate_name), bl_engine_(bl_engine) : render_delegate_name_(render_delegate_name), bl_engine_(bl_engine)
{ {
pxr::HdRendererPluginRegistry &registry = pxr::HdRendererPluginRegistry::GetInstance(); pxr::HdRendererPluginRegistry &registry = pxr::HdRendererPluginRegistry::GetInstance();
@ -39,10 +45,10 @@ Engine::Engine(RenderEngine *bl_engine, const std::string &render_delegate_name)
hd_drivers.push_back(&hgi_driver_); hd_drivers.push_back(&hgi_driver_);
} }
render_delegate_ = registry.CreateRenderDelegate(pxr::TfToken(render_delegate_name)); render_delegate_ = registry.CreateRenderDelegate(pxr::TfToken(render_delegate_name_));
if (!render_delegate_) { if (!render_delegate_) {
throw std::runtime_error("Cannot create render delegate: " + render_delegate_name); throw std::runtime_error("Cannot create render delegate: " + render_delegate_name_);
} }
render_index_.reset(pxr::HdRenderIndex::New(render_delegate_.Get(), hd_drivers)); render_index_.reset(pxr::HdRenderIndex::New(render_delegate_.Get(), hd_drivers));
@ -59,7 +65,7 @@ Engine::Engine(RenderEngine *bl_engine, const std::string &render_delegate_name)
} }
render_task_delegate_->set_camera(free_camera_delegate_->GetCameraId()); render_task_delegate_->set_camera(free_camera_delegate_->GetCameraId());
if (render_delegate_name == "HdStormRendererPlugin") { if (render_delegate_name_ == "HdStormRendererPlugin") {
light_tasks_delegate_ = std::make_unique<LightTasksDelegate>( light_tasks_delegate_ = std::make_unique<LightTasksDelegate>(
render_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("lightTasks")); render_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("lightTasks"));
light_tasks_delegate_->set_camera(free_camera_delegate_->GetCameraId()); light_tasks_delegate_->set_camera(free_camera_delegate_->GetCameraId());
@ -78,10 +84,10 @@ void Engine::sync(Depsgraph *depsgraph, bContext *context)
if (!hydra_scene_delegate_) { if (!hydra_scene_delegate_) {
pxr::SdfPath scene_path = pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"); pxr::SdfPath scene_path = pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene");
hydra_scene_delegate_ = std::make_unique<BlenderSceneDelegate>( hydra_scene_delegate_ = std::make_unique<io::hydra::HydraSceneDelegate>(
render_index_.get(), scene_path, scene_delegate_settings_); render_index_.get(), scene_path, scene_delegate_settings_);
} }
hydra_scene_delegate_->populate(depsgraph, context); hydra_scene_delegate_->populate(depsgraph, CTX_wm_view3d(context));
} }
else { else {
/* Slow USD export for reference. */ /* Slow USD export for reference. */
@ -93,10 +99,10 @@ void Engine::sync(Depsgraph *depsgraph, bContext *context)
if (!usd_scene_delegate_) { if (!usd_scene_delegate_) {
pxr::SdfPath scene_path = pxr::SdfPath::AbsoluteRootPath().AppendElementString("usd_scene"); pxr::SdfPath scene_path = pxr::SdfPath::AbsoluteRootPath().AppendElementString("usd_scene");
usd_scene_delegate_ = std::make_unique<USDSceneDelegate>( usd_scene_delegate_ = std::make_unique<io::hydra::USDSceneDelegate>(
render_index_.get(), scene_path, scene_delegate_settings_); render_index_.get(), scene_path, scene_delegate_settings_);
} }
usd_scene_delegate_->populate(depsgraph, context); usd_scene_delegate_->populate(depsgraph);
} }
} }

View File

@ -1,9 +1,10 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
#include <chrono> #include <memory>
#include <string>
#include <pxr/imaging/hd/driver.h> #include <pxr/imaging/hd/driver.h>
#include <pxr/imaging/hd/engine.h> #include <pxr/imaging/hd/engine.h>
@ -13,21 +14,46 @@
#include <pxr/usd/usd/stage.h> #include <pxr/usd/usd/stage.h>
#include <pxr/usdImaging/usdImaging/delegate.h> #include <pxr/usdImaging/usdImaging/delegate.h>
#include "RE_engine.h" #include "hydra/hydra_scene_delegate.h"
#include "hydra/settings.h"
#include "CLG_log.h" #include "hydra/usd_scene_delegate.h"
#include "light_tasks_delegate.h" #include "light_tasks_delegate.h"
#include "render_task_delegate.h" #include "render_task_delegate.h"
#include "scene_delegate/blender_scene_delegate.h" struct bContext;
#include "scene_delegate/usd_scene_delegate.hh" struct RenderEngine;
struct CLG_LogRef;
namespace blender::render::hydra { namespace blender::render::hydra {
extern struct CLG_LogRef *LOG_RENDER_HYDRA; extern struct CLG_LogRef *LOG_RENDER_HYDRA;
struct RenderDelegateSettings {
Map<std::string, pxr::TfToken> aovs;
};
class Engine { class Engine {
protected:
std::string render_delegate_name_;
RenderEngine *bl_engine_ = nullptr;
/* The order is important due to deletion order */
pxr::HgiUniquePtr hgi_;
pxr::HdDriver hgi_driver_;
pxr::HdPluginRenderDelegateUniqueHandle render_delegate_;
std::unique_ptr<pxr::HdRenderIndex> render_index_;
io::hydra::HydraDelegateSettings scene_delegate_settings_;
std::unique_ptr<io::hydra::HydraSceneDelegate> hydra_scene_delegate_;
std::unique_ptr<io::hydra::USDSceneDelegate> usd_scene_delegate_;
RenderDelegateSettings render_delegate_settings_;
std::unique_ptr<RenderTaskDelegate> render_task_delegate_;
std::unique_ptr<pxr::HdxFreeCameraSceneDelegate> free_camera_delegate_;
std::unique_ptr<LightTasksDelegate> light_tasks_delegate_;
std::unique_ptr<pxr::HdEngine> engine_;
public: public:
Engine(RenderEngine *bl_engine, const std::string &render_delegate_name); Engine(RenderEngine *bl_engine, const std::string &render_delegate_name);
virtual ~Engine() = default; virtual ~Engine() = default;
@ -38,28 +64,8 @@ class Engine {
void set_sync_setting(const std::string &key, const pxr::VtValue &val); void set_sync_setting(const std::string &key, const pxr::VtValue &val);
void set_render_setting(const std::string &key, const pxr::VtValue &val); void set_render_setting(const std::string &key, const pxr::VtValue &val);
std::string render_delegate_name;
protected: protected:
float renderer_percent_done(); float renderer_percent_done();
RenderEngine *bl_engine_ = nullptr;
/* The order is important due to deletion order */
pxr::HgiUniquePtr hgi_;
pxr::HdDriver hgi_driver_;
pxr::HdPluginRenderDelegateUniqueHandle render_delegate_;
std::unique_ptr<pxr::HdRenderIndex> render_index_;
SceneDelegateSettings scene_delegate_settings_;
std::unique_ptr<BlenderSceneDelegate> hydra_scene_delegate_;
std::unique_ptr<USDSceneDelegate> usd_scene_delegate_;
RenderDelegateSettings render_delegate_settings_;
std::unique_ptr<RenderTaskDelegate> render_task_delegate_;
std::unique_ptr<pxr::HdxFreeCameraSceneDelegate> free_camera_delegate_;
std::unique_ptr<LightTasksDelegate> light_tasks_delegate_;
std::unique_ptr<pxr::HdEngine> engine_;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -1,18 +1,25 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "final_engine.h"
#include <pxr/imaging/hd/light.h> #include <pxr/imaging/hd/light.h>
#include <pxr/imaging/hd/renderBuffer.h> #include <pxr/imaging/hd/renderBuffer.h>
#include "BKE_lib_id.h" #include "DNA_scene_types.h"
#include "BLI_timecode.h" #include "BLI_timecode.h"
#include "DEG_depsgraph_query.h"
#include "PIL_time.h" #include "PIL_time.h"
#include "BKE_lib_id.h"
#include "DEG_depsgraph_query.h"
#include "IMB_imbuf_types.h" #include "IMB_imbuf_types.h"
#include "camera.h" #include "RE_engine.h"
#include "final_engine.h"
#include "hydra/camera.h"
namespace blender::render::hydra { namespace blender::render::hydra {
@ -21,8 +28,8 @@ void FinalEngine::render(Depsgraph *depsgraph)
const Scene *scene = DEG_get_evaluated_scene(depsgraph); const Scene *scene = DEG_get_evaluated_scene(depsgraph);
const ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); const ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
char scene_name[MAX_NAME]; char scene_name[MAX_ID_FULL_NAME];
BKE_id_full_name_get(scene_name, (ID *)scene, 0); BKE_id_full_name_get(scene_name, &scene->id, 0);
scene_name_ = scene_name; scene_name_ = scene_name;
layer_name_ = view_layer->name; layer_name_ = view_layer->name;
@ -37,7 +44,7 @@ void FinalEngine::render(Depsgraph *depsgraph)
pxr::GfVec2i image_res(r.xsch * r.size / 100, r.ysch * r.size / 100); pxr::GfVec2i image_res(r.xsch * r.size / 100, r.ysch * r.size / 100);
resolution_ = pxr::GfVec2i(int(image_res[0] * border[2]), int(image_res[1] * border[3])); resolution_ = pxr::GfVec2i(int(image_res[0] * border[2]), int(image_res[1] * border[3]));
pxr::GfCamera camera = pxr::GfCamera camera =
CameraData(scene->camera, image_res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(border); io::hydra::CameraData(scene->camera, image_res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(border);
free_camera_delegate_->SetCamera(camera); free_camera_delegate_->SetCamera(camera);
render_task_delegate_->set_viewport(pxr::GfVec4d(0, 0, resolution_[0], resolution_[1])); render_task_delegate_->set_viewport(pxr::GfVec4d(0, 0, resolution_[0], resolution_[1]));
@ -107,19 +114,22 @@ void FinalEngine::notify_status(float progress, const std::string &title, const
void FinalEngine::update_render_result() void FinalEngine::update_render_result()
{ {
RenderResult *result = RE_engine_begin_result( RenderResult *rr = RE_engine_begin_result(
bl_engine_, 0, 0, resolution_[0], resolution_[1], layer_name_.c_str(), nullptr); bl_engine_, 0, 0, resolution_[0], resolution_[1], layer_name_.c_str(), nullptr);
/* TODO: only for the first render layer */ RenderLayer *rlayer = static_cast<RenderLayer *>(
RenderLayer *layer = (RenderLayer *)result->layers.first; BLI_findstring(&rr->layers, layer_name_.c_str(), offsetof(RenderLayer, name)));
for (RenderPass *pass = (RenderPass *)layer->passes.first; pass != nullptr; pass = pass->next) {
pxr::TfToken *aov_token = render_delegate_settings_.aovs.lookup_ptr(pass->name); if (rlayer) {
if (aov_token) { LISTBASE_FOREACH (RenderPass *, rpass, &rlayer->passes) {
render_task_delegate_->read_aov(*aov_token, pass->ibuf->float_buffer.data); pxr::TfToken *aov_token = render_delegate_settings_.aovs.lookup_ptr(rpass->name);
if (aov_token) {
render_task_delegate_->read_aov(*aov_token, rpass->ibuf->float_buffer.data);
}
} }
} }
RE_engine_end_result(bl_engine_, result, false, false, false); RE_engine_end_result(bl_engine_, rr, false, false, false);
} }
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
@ -8,6 +8,11 @@
namespace blender::render::hydra { namespace blender::render::hydra {
class FinalEngine : public Engine { class FinalEngine : public Engine {
protected:
std::string scene_name_;
std::string layer_name_;
pxr::GfVec2i resolution_;
public: public:
using Engine::Engine; using Engine::Engine;
@ -16,10 +21,6 @@ class FinalEngine : public Engine {
protected: protected:
virtual void notify_status(float progress, const std::string &title, const std::string &info); virtual void notify_status(float progress, const std::string &title, const std::string &info);
void update_render_result(); void update_render_result();
std::string scene_name_;
std::string layer_name_;
pxr::GfVec2i resolution_;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "light_tasks_delegate.h" #include "light_tasks_delegate.h"
#include "engine.h" #include "engine.h"

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once

View File

@ -1,13 +1,13 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "preview_engine.h" #include "preview_engine.h"
namespace blender::render::hydra { namespace blender::render::hydra {
void PreviewEngine::notify_status(float progress, void PreviewEngine::notify_status(float /* progress */,
const std::string &title, const std::string & /* title */,
const std::string &info) const std::string & /* info */)
{ {
/* Empty fucntion */ /* Empty fucntion */
} }

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once

View File

@ -1,58 +1,30 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include <Python.h>
#include <boost/python/extract.hpp>
#include <pxr/base/plug/plugin.h>
#include <pxr/base/plug/registry.h>
#include <pxr/usd/usd/stage.h>
#include <pxr/usdImaging/usdImagingGL/engine.h>
#include "BKE_appdir.h"
#include "BLI_fileops.h"
#include "BLI_path_util.h"
#include "final_engine.h" #include "final_engine.h"
#include "preview_engine.h" #include "preview_engine.h"
#include "scene_delegate/image.h"
#include "viewport_engine.h" #include "viewport_engine.h"
#include <Python.h>
#include "RE_engine.h"
#include "bpy_rna.h"
#include "BKE_context.h"
#include "RE_engine.h"
#include "RNA_prototypes.h"
#include "hydra/image.h"
namespace blender::render::hydra { namespace blender::render::hydra {
static PyObject *register_plugins_func(PyObject * /*self*/, PyObject *args) template<typename T> T *pyrna_to_pointer(PyObject *pyobject, const StructRNA *rnatype)
{ {
PyObject *pyplugin_dirs; const PointerRNA *ptr = pyrna_struct_as_ptr_or_null(pyobject, rnatype);
if (!PyArg_ParseTuple(args, "O", &pyplugin_dirs)) { return (ptr) ? static_cast<T *>(ptr->data) : nullptr;
Py_RETURN_NONE;
}
std::vector<std::string> plugin_dirs;
PyObject *pyiter, *pyitem;
pyiter = PyObject_GetIter(pyplugin_dirs);
if (pyiter) {
while ((pyitem = PyIter_Next(pyiter))) {
plugin_dirs.push_back(PyUnicode_AsUTF8(pyitem));
Py_DECREF(pyitem);
}
Py_DECREF(pyiter);
}
pxr::PlugRegistry &registry = pxr::PlugRegistry::GetInstance();
registry.RegisterPlugins(plugin_dirs);
/* logging */
std::stringstream ss;
ss << "plugins=[";
for (auto &s : plugin_dirs) {
ss << s << ", ";
}
ss << "]";
CLOG_INFO(LOG_RENDER_HYDRA, 0, "Register %s", ss.str().c_str());
Py_RETURN_NONE;
} }
static PyObject *engine_create_func(PyObject * /*self*/, PyObject *args) static PyObject *engine_create_func(PyObject * /*self*/, PyObject *args)
@ -63,7 +35,7 @@ static PyObject *engine_create_func(PyObject * /*self*/, PyObject *args)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
RenderEngine *bl_engine = (RenderEngine *)PyLong_AsVoidPtr(pyengine); RenderEngine *bl_engine = pyrna_to_pointer<RenderEngine>(pyengine, &RNA_RenderEngine);
Engine *engine = nullptr; Engine *engine = nullptr;
try { try {
@ -94,23 +66,23 @@ static PyObject *engine_free_func(PyObject * /*self*/, PyObject *args)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
Engine *engine = (Engine *)PyLong_AsVoidPtr(pyengine); Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
delete engine; delete engine;
CLOG_INFO(LOG_RENDER_HYDRA, 1, "Engine %p", engine); CLOG_INFO(LOG_RENDER_HYDRA, 1, "Engine %p", engine);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject *engine_sync_func(PyObject * /*self*/, PyObject *args) static PyObject *engine_update_func(PyObject * /*self*/, PyObject *args)
{ {
PyObject *pyengine, *pydepsgraph, *pycontext; PyObject *pyengine, *pydepsgraph, *pycontext;
if (!PyArg_ParseTuple(args, "OOO", &pyengine, &pydepsgraph, &pycontext)) { if (!PyArg_ParseTuple(args, "OOO", &pyengine, &pydepsgraph, &pycontext)) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
Engine *engine = (Engine *)PyLong_AsVoidPtr(pyengine); Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
Depsgraph *depsgraph = (Depsgraph *)PyLong_AsVoidPtr(pydepsgraph); Depsgraph *depsgraph = pyrna_to_pointer<Depsgraph>(pydepsgraph, &RNA_Depsgraph);
bContext *context = (bContext *)PyLong_AsVoidPtr(pycontext); bContext *context = pyrna_to_pointer<bContext>(pycontext, &RNA_Context);
CLOG_INFO(LOG_RENDER_HYDRA, 2, "Engine %p", engine); CLOG_INFO(LOG_RENDER_HYDRA, 2, "Engine %p", engine);
engine->sync(depsgraph, context); engine->sync(depsgraph, context);
@ -126,8 +98,8 @@ static PyObject *engine_render_func(PyObject * /*self*/, PyObject *args)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
Engine *engine = (Engine *)PyLong_AsVoidPtr(pyengine); Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
Depsgraph *depsgraph = (Depsgraph *)PyLong_AsVoidPtr(pydepsgraph); Depsgraph *depsgraph = pyrna_to_pointer<Depsgraph>(pydepsgraph, &RNA_Depsgraph);
CLOG_INFO(LOG_RENDER_HYDRA, 2, "Engine %p", engine); CLOG_INFO(LOG_RENDER_HYDRA, 2, "Engine %p", engine);
@ -146,9 +118,9 @@ static PyObject *engine_view_draw_func(PyObject * /*self*/, PyObject *args)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
ViewportEngine *engine = (ViewportEngine *)PyLong_AsVoidPtr(pyengine); ViewportEngine *engine = static_cast<ViewportEngine *>(PyLong_AsVoidPtr(pyengine));
Depsgraph *depsgraph = (Depsgraph *)PyLong_AsVoidPtr(pydepsgraph); Depsgraph *depsgraph = pyrna_to_pointer<Depsgraph>(pydepsgraph, &RNA_Depsgraph);
bContext *context = (bContext *)PyLong_AsVoidPtr(pycontext); bContext *context = pyrna_to_pointer<bContext>(pycontext, &RNA_Context);
CLOG_INFO(LOG_RENDER_HYDRA, 3, "Engine %p", engine); CLOG_INFO(LOG_RENDER_HYDRA, 3, "Engine %p", engine);
@ -186,7 +158,7 @@ static PyObject *engine_set_sync_setting_func(PyObject * /*self*/, PyObject *arg
Py_RETURN_NONE; Py_RETURN_NONE;
} }
Engine *engine = (Engine *)PyLong_AsVoidPtr(pyengine); Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
CLOG_INFO(LOG_RENDER_HYDRA, 3, "Engine %p: %s", engine, key); CLOG_INFO(LOG_RENDER_HYDRA, 3, "Engine %p: %s", engine, key);
engine->set_sync_setting(key, get_setting_val(pyval)); engine->set_sync_setting(key, get_setting_val(pyval));
@ -202,7 +174,7 @@ static PyObject *engine_set_render_setting_func(PyObject * /*self*/, PyObject *a
Py_RETURN_NONE; Py_RETURN_NONE;
} }
Engine *engine = (Engine *)PyLong_AsVoidPtr(pyengine); Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
CLOG_INFO(LOG_RENDER_HYDRA, 3, "Engine %p: %s", engine, key); CLOG_INFO(LOG_RENDER_HYDRA, 3, "Engine %p: %s", engine, key);
engine->set_render_setting(key, get_setting_val(pyval)); engine->set_render_setting(key, get_setting_val(pyval));
@ -217,19 +189,18 @@ static PyObject *cache_or_get_image_file_func(PyObject * /*self*/, PyObject *arg
Py_RETURN_NONE; Py_RETURN_NONE;
} }
bContext *context = (bContext *)PyLong_AsVoidPtr(pycontext); bContext *context = static_cast<bContext *>(PyLong_AsVoidPtr(pycontext));
Image *image = (Image *)PyLong_AsVoidPtr(pyimage); Image *image = static_cast<Image *>(PyLong_AsVoidPtr(pyimage));
std::string image_path = cache_or_get_image_file(image, context, nullptr); std::string image_path = io::hydra::cache_or_get_image_file(
CTX_data_main(context), CTX_data_scene(context), image, nullptr);
return PyUnicode_FromString(image_path.c_str()); return PyUnicode_FromString(image_path.c_str());
} }
static PyMethodDef methods[] = { static PyMethodDef methods[] = {
{"register_plugins", register_plugins_func, METH_VARARGS, ""},
{"engine_create", engine_create_func, METH_VARARGS, ""}, {"engine_create", engine_create_func, METH_VARARGS, ""},
{"engine_free", engine_free_func, METH_VARARGS, ""}, {"engine_free", engine_free_func, METH_VARARGS, ""},
{"engine_sync", engine_sync_func, METH_VARARGS, ""}, {"engine_update", engine_update_func, METH_VARARGS, ""},
{"engine_render", engine_render_func, METH_VARARGS, ""}, {"engine_render", engine_render_func, METH_VARARGS, ""},
{"engine_view_draw", engine_view_draw_func, METH_VARARGS, ""}, {"engine_view_draw", engine_view_draw_func, METH_VARARGS, ""},
{"engine_set_sync_setting", engine_set_sync_setting_func, METH_VARARGS, ""}, {"engine_set_sync_setting", engine_set_sync_setting_func, METH_VARARGS, ""},
@ -258,6 +229,8 @@ static struct PyModuleDef module = {
extern "C" { extern "C" {
#endif #endif
PyObject *BPyInit_hydra(void);
PyObject *BPyInit_hydra(void) PyObject *BPyInit_hydra(void)
{ {
PyObject *mod = PyModule_Create(&blender::render::hydra::module); PyObject *mod = PyModule_Create(&blender::render::hydra::module);

View File

@ -1,8 +1,12 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "render_task_delegate.h"
#include <epoxy/gl.h> #include <epoxy/gl.h>
#include "GPU_context.h"
#include <pxr/imaging/hd/renderBuffer.h> #include <pxr/imaging/hd/renderBuffer.h>
#include <pxr/imaging/hd/renderDelegate.h> #include <pxr/imaging/hd/renderDelegate.h>
#include <pxr/imaging/hdx/renderTask.h> #include <pxr/imaging/hdx/renderTask.h>
@ -18,13 +22,13 @@ RenderTaskDelegate::RenderTaskDelegate(pxr::HdRenderIndex *parent_index,
pxr::SdfPath const &delegate_id) pxr::SdfPath const &delegate_id)
: pxr::HdSceneDelegate(parent_index, delegate_id) : pxr::HdSceneDelegate(parent_index, delegate_id)
{ {
render_task_id_ = GetDelegateID().AppendElementString("renderTask"); task_id_ = GetDelegateID().AppendElementString("renderTask");
GetRenderIndex().InsertTask<pxr::HdxRenderTask>(this, render_task_id_); GetRenderIndex().InsertTask<pxr::HdxRenderTask>(this, task_id_);
render_task_params_.enableLighting = true; task_params_.enableLighting = true;
render_task_params_.alphaThreshold = 0.1f; task_params_.alphaThreshold = 0.1f;
CLOG_INFO(LOG_RENDER_HYDRA, 1, "%s", render_task_id_.GetText()); CLOG_INFO(LOG_RENDER_HYDRA, 1, "%s", task_id_.GetText());
} }
pxr::VtValue RenderTaskDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key) pxr::VtValue RenderTaskDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
@ -32,7 +36,7 @@ pxr::VtValue RenderTaskDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const
CLOG_INFO(LOG_RENDER_HYDRA, 3, "%s, %s", id.GetText(), key.GetText()); CLOG_INFO(LOG_RENDER_HYDRA, 3, "%s, %s", id.GetText(), key.GetText());
if (key == pxr::HdTokens->params) { if (key == pxr::HdTokens->params) {
return pxr::VtValue(render_task_params_); return pxr::VtValue(task_params_);
} }
if (key == pxr::HdTokens->collection) { if (key == pxr::HdTokens->collection) {
return pxr::VtValue(pxr::HdRprimCollection( return pxr::VtValue(pxr::HdRprimCollection(
@ -57,32 +61,32 @@ pxr::HdRenderBufferDescriptor RenderTaskDelegate::GetRenderBufferDescriptor(pxr:
pxr::HdTaskSharedPtr RenderTaskDelegate::task() pxr::HdTaskSharedPtr RenderTaskDelegate::task()
{ {
return GetRenderIndex().GetTask(render_task_id_); return GetRenderIndex().GetTask(task_id_);
} }
void RenderTaskDelegate::set_camera(pxr::SdfPath const &camera_id) void RenderTaskDelegate::set_camera(pxr::SdfPath const &camera_id)
{ {
if (render_task_params_.camera == camera_id) { if (task_params_.camera == camera_id) {
return; return;
} }
render_task_params_.camera = camera_id; task_params_.camera = camera_id;
GetRenderIndex().GetChangeTracker().MarkTaskDirty(render_task_id_, GetRenderIndex().GetChangeTracker().MarkTaskDirty(task_id_,
pxr::HdChangeTracker::DirtyParams); pxr::HdChangeTracker::DirtyParams);
} }
bool RenderTaskDelegate::is_converged() bool RenderTaskDelegate::is_converged()
{ {
return ((pxr::HdxRenderTask *)task().get())->IsConverged(); return static_cast<pxr::HdxRenderTask *>(task().get())->IsConverged();
} }
void RenderTaskDelegate::set_viewport(pxr::GfVec4d const &viewport) void RenderTaskDelegate::set_viewport(pxr::GfVec4d const &viewport)
{ {
if (render_task_params_.viewport == viewport) { if (task_params_.viewport == viewport) {
return; return;
} }
auto &render_index = GetRenderIndex(); auto &render_index = GetRenderIndex();
render_task_params_.viewport = viewport; task_params_.viewport = viewport;
render_index.GetChangeTracker().MarkTaskDirty(render_task_id_, render_index.GetChangeTracker().MarkTaskDirty(task_id_,
pxr::HdChangeTracker::DirtyParams); pxr::HdChangeTracker::DirtyParams);
int w = viewport[2] - viewport[0]; int w = viewport[2] - viewport[0];
@ -108,8 +112,8 @@ void RenderTaskDelegate::add_aov(pxr::TfToken const &aov_key)
return; return;
} }
int w = render_task_params_.viewport[2] - render_task_params_.viewport[0]; int w = task_params_.viewport[2] - task_params_.viewport[0];
int h = render_task_params_.viewport[3] - render_task_params_.viewport[1]; int h = task_params_.viewport[3] - task_params_.viewport[1];
render_index.InsertBprim(pxr::HdPrimTypeTokens->renderBuffer, this, buf_id); render_index.InsertBprim(pxr::HdPrimTypeTokens->renderBuffer, this, buf_id);
buffer_descriptors_[buf_id] = pxr::HdRenderBufferDescriptor( buffer_descriptors_[buf_id] = pxr::HdRenderBufferDescriptor(
pxr::GfVec3i(w, h, 1), aov_desc.format, aov_desc.multiSampled); pxr::GfVec3i(w, h, 1), aov_desc.format, aov_desc.multiSampled);
@ -118,8 +122,8 @@ void RenderTaskDelegate::add_aov(pxr::TfToken const &aov_key)
binding.aovName = aov_key; binding.aovName = aov_key;
binding.renderBufferId = buf_id; binding.renderBufferId = buf_id;
binding.aovSettings = aov_desc.aovSettings; binding.aovSettings = aov_desc.aovSettings;
render_task_params_.aovBindings.push_back(binding); task_params_.aovBindings.push_back(binding);
render_index.GetChangeTracker().MarkTaskDirty(render_task_id_, render_index.GetChangeTracker().MarkTaskDirty(task_id_,
pxr::HdChangeTracker::DirtyParams); pxr::HdChangeTracker::DirtyParams);
CLOG_INFO(LOG_RENDER_HYDRA, 1, "%s", aov_key.GetText()); CLOG_INFO(LOG_RENDER_HYDRA, 1, "%s", aov_key.GetText());
@ -127,8 +131,8 @@ void RenderTaskDelegate::add_aov(pxr::TfToken const &aov_key)
void RenderTaskDelegate::read_aov(pxr::TfToken const &aov_key, void *data) void RenderTaskDelegate::read_aov(pxr::TfToken const &aov_key, void *data)
{ {
pxr::HdRenderBuffer *buffer = (pxr::HdRenderBuffer *)GetRenderIndex().GetBprim( pxr::HdRenderBuffer *buffer = static_cast<pxr::HdRenderBuffer *>(
pxr::HdPrimTypeTokens->renderBuffer, buffer_id(aov_key)); GetRenderIndex().GetBprim(pxr::HdPrimTypeTokens->renderBuffer, buffer_id(aov_key)));
if (!buffer) { if (!buffer) {
return; return;
} }
@ -162,12 +166,12 @@ pxr::SdfPath RenderTaskDelegate::buffer_id(pxr::TfToken const &aov_key) const
void GPURenderTaskDelegate::set_viewport(pxr::GfVec4d const &viewport) void GPURenderTaskDelegate::set_viewport(pxr::GfVec4d const &viewport)
{ {
if (render_task_params_.viewport == viewport) { if (task_params_.viewport == viewport) {
return; return;
} }
auto &render_index = GetRenderIndex(); auto &render_index = GetRenderIndex();
render_task_params_.viewport = viewport; task_params_.viewport = viewport;
render_index.GetChangeTracker().MarkTaskDirty(render_task_id_, render_index.GetChangeTracker().MarkTaskDirty(task_id_,
pxr::HdChangeTracker::DirtyParams); pxr::HdChangeTracker::DirtyParams);
if (tex_color_) { if (tex_color_) {
@ -203,8 +207,8 @@ void GPURenderTaskDelegate::add_aov(pxr::TfToken const &aov_key)
} }
*tex = GPU_texture_create_2d(("tex_render_hydra_" + aov_key.GetString()).c_str(), *tex = GPU_texture_create_2d(("tex_render_hydra_" + aov_key.GetString()).c_str(),
render_task_params_.viewport[2] - render_task_params_.viewport[0], task_params_.viewport[2] - task_params_.viewport[0],
render_task_params_.viewport[3] - render_task_params_.viewport[1], task_params_.viewport[3] - task_params_.viewport[1],
1, 1,
format, format,
GPU_TEXTURE_USAGE_GENERAL, GPU_TEXTURE_USAGE_GENERAL,
@ -268,17 +272,21 @@ void GPURenderTaskDelegate::bind()
float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
GPU_framebuffer_clear_color_depth(framebuffer_, clear_color, 1.0f); GPU_framebuffer_clear_color_depth(framebuffer_, clear_color, 1.0f);
/* Important: we have to create and bind at least one Vertex Array Object (VAO) before render /* Workaround missing/buggy VAOs in hgiGL and hdSt. For OpenGL compatibility
* execution: More info at https://open.gl/drawing */ * profile this is not a problem, but for core profile it is. */
if (VAO_ == 0) { if (GPU_backend_get_type() == GPU_BACKEND_OPENGL) {
glGenVertexArrays(1, &VAO_); if (VAO_ == 0) {
glGenVertexArrays(1, &VAO_);
}
glBindVertexArray(VAO_);
} }
glBindVertexArray(VAO_);
} }
void GPURenderTaskDelegate::unbind() void GPURenderTaskDelegate::unbind()
{ {
glDeleteVertexArrays(1, &VAO_); if (GPU_backend_get_type() == GPU_BACKEND_OPENGL) {
glDeleteVertexArrays(1, &VAO_);
}
GPU_framebuffer_free(framebuffer_); GPU_framebuffer_free(framebuffer_);
GPU_texture_free(tex_color_); GPU_texture_free(tex_color_);
GPU_texture_free(tex_depth_); GPU_texture_free(tex_depth_);

View File

@ -1,18 +1,25 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
#include <pxr/imaging/hd/sceneDelegate.h> #include <pxr/imaging/hd/sceneDelegate.h>
#include <pxr/imaging/hdx/renderSetupTask.h> #include <pxr/imaging/hdx/renderSetupTask.h>
#include <pxr/imaging/hdx/visualizeAovTask.h>
#include "GPU_framebuffer.h" #include "GPU_framebuffer.h"
#include "GPU_texture.h" #include "GPU_texture.h"
namespace blender::render::hydra { namespace blender::render::hydra {
/* Delegate to create a render task with given camera, viewport and AOVs. */
class RenderTaskDelegate : public pxr::HdSceneDelegate { class RenderTaskDelegate : public pxr::HdSceneDelegate {
protected:
pxr::SdfPath task_id_;
pxr::HdxRenderTaskParams task_params_;
pxr::TfHashMap<pxr::SdfPath, pxr::HdRenderBufferDescriptor, pxr::SdfPath::Hash>
buffer_descriptors_;
public: public:
RenderTaskDelegate(pxr::HdRenderIndex *parent_index, pxr::SdfPath const &delegate_id); RenderTaskDelegate(pxr::HdRenderIndex *parent_index, pxr::SdfPath const &delegate_id);
~RenderTaskDelegate() override = default; ~RenderTaskDelegate() override = default;
@ -34,14 +41,15 @@ class RenderTaskDelegate : public pxr::HdSceneDelegate {
protected: protected:
pxr::SdfPath buffer_id(pxr::TfToken const &aov_key) const; pxr::SdfPath buffer_id(pxr::TfToken const &aov_key) const;
pxr::SdfPath render_task_id_;
pxr::HdxRenderTaskParams render_task_params_;
pxr::TfHashMap<pxr::SdfPath, pxr::HdRenderBufferDescriptor, pxr::SdfPath::Hash>
buffer_descriptors_;
}; };
class GPURenderTaskDelegate : public RenderTaskDelegate { class GPURenderTaskDelegate : public RenderTaskDelegate {
private:
GPUFrameBuffer *framebuffer_ = nullptr;
GPUTexture *tex_color_ = nullptr;
GPUTexture *tex_depth_ = nullptr;
unsigned int VAO_ = 0;
public: public:
using RenderTaskDelegate::RenderTaskDelegate; using RenderTaskDelegate::RenderTaskDelegate;
@ -51,12 +59,6 @@ class GPURenderTaskDelegate : public RenderTaskDelegate {
void read_aov(pxr::TfToken const &aov_key, GPUTexture *texture) override; void read_aov(pxr::TfToken const &aov_key, GPUTexture *texture) override;
void bind() override; void bind() override;
void unbind() override; void unbind() override;
private:
GPUFrameBuffer *framebuffer_ = nullptr;
GPUTexture *tex_color_ = nullptr;
GPUTexture *tex_depth_ = nullptr;
unsigned int VAO_ = 0;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -1,15 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include "BKE_lib_id.h"
#include "id.h"
namespace blender::render::hydra {
IdData::IdData(BlenderSceneDelegate *scene_delegate, ID *id, pxr::SdfPath const &prim_id)
: id(id), prim_id(prim_id), scene_delegate_(scene_delegate)
{
}
} // namespace blender::render::hydra

View File

@ -1,14 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#pragma once
#include "BKE_context.h"
#include "BKE_image.h"
namespace blender::render::hydra {
std::string cache_or_get_image_file(Image *image, bContext *context, ImageUser *iuser);
std::string cache_image_color(float color[4]);
} // namespace blender::render::hydra

View File

@ -1,321 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include <pxr/base/gf/vec2f.h>
#include <pxr/imaging/hd/light.h>
#include "DEG_depsgraph_query.h"
#include "blender_scene_delegate.h"
#include "instancer.h"
namespace blender::render::hydra {
InstancerData::InstancerData(BlenderSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id)
: IdData(scene_delegate, nullptr, prim_id)
{
}
bool InstancerData::is_instance_supported(Object *object)
{
switch (object->type) {
case OB_MESH:
case OB_SURF:
case OB_FONT:
case OB_CURVES_LEGACY:
case OB_MBALL:
case OB_LAMP:
return true;
default:
break;
}
return false;
}
void InstancerData::init() {}
void InstancerData::insert() {}
void InstancerData::remove()
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 1, "%s", prim_id.GetText());
for (auto &m_inst : mesh_instances_.values()) {
m_inst.data->remove();
}
if (!mesh_instances_.is_empty()) {
scene_delegate_->GetRenderIndex().RemoveInstancer(prim_id);
}
mesh_instances_.clear();
for (auto &l_inst : light_instances_.values()) {
l_inst.transforms.clear();
update_light_instance(l_inst);
}
light_instances_.clear();
}
void InstancerData::update() {}
pxr::VtValue InstancerData::get_data(pxr::TfToken const &key) const
{
ID_LOG(3, "%s", key.GetText());
if (key == pxr::HdInstancerTokens->instanceTransform) {
return pxr::VtValue(mesh_transforms_);
}
return pxr::VtValue();
}
pxr::GfMatrix4d InstancerData::get_transform(pxr::SdfPath const &id) const
{
LightInstance *l_inst = light_instance(id);
if (l_inst) {
return l_inst->transforms[light_prim_id_index(id)];
}
/* Mesh instance transform must be identity */
return pxr::GfMatrix4d(1.0);
}
pxr::HdPrimvarDescriptorVector InstancerData::primvar_descriptors(
pxr::HdInterpolation interpolation) const
{
pxr::HdPrimvarDescriptorVector primvars;
if (interpolation == pxr::HdInterpolationInstance) {
primvars.emplace_back(
pxr::HdInstancerTokens->instanceTransform, interpolation, pxr::HdPrimvarRoleTokens->none);
}
return primvars;
}
pxr::VtIntArray InstancerData::indices(pxr::SdfPath const &id) const
{
return mesh_instance(id)->indices;
}
ObjectData *InstancerData::object_data(pxr::SdfPath const &id) const
{
MeshInstance *m_inst = mesh_instance(id);
if (m_inst) {
return m_inst->data.get();
}
LightInstance *l_inst = light_instance(id);
if (l_inst) {
return l_inst->data.get();
}
return nullptr;
}
pxr::SdfPathVector InstancerData::prototypes() const
{
pxr::SdfPathVector paths;
for (auto &m_inst : mesh_instances_.values()) {
for (auto &p : m_inst.data->submesh_paths()) {
paths.push_back(p);
}
}
return paths;
}
void InstancerData::available_materials(Set<pxr::SdfPath> &paths) const
{
for (auto &m_inst : mesh_instances_.values()) {
((MeshData *)m_inst.data.get())->available_materials(paths);
}
}
void InstancerData::update_double_sided(MaterialData *mat_data)
{
for (auto &m_inst : mesh_instances_.values()) {
m_inst.data->update_double_sided(mat_data);
}
}
void InstancerData::pre_update()
{
mesh_transforms_.clear();
for (auto &m_inst : mesh_instances_.values()) {
m_inst.indices.clear();
}
for (auto &l_inst : light_instances_.values()) {
l_inst.transforms.clear();
}
}
void InstancerData::update_instance(Object *parent_ob, DupliObject *dupli)
{
if (!ObjectData::is_visible(scene_delegate_, parent_ob, OB_VISIBLE_INSTANCES)) {
return;
}
Object *ob = dupli->ob;
if (!is_instance_supported(ob)) {
return;
}
if (!scene_delegate_->shading_settings.use_scene_lights && ob->type == OB_LAMP) {
return;
}
pxr::SdfPath p_id = object_prim_id(ob);
if (ob->type == OB_LAMP) {
LightInstance *inst = light_instance(p_id);
if (!inst) {
inst = &light_instances_.lookup_or_add_default(p_id);
inst->data = std::make_unique<LightData>(scene_delegate_, ob, p_id);
inst->data->init();
}
ID_LOG(2, "Light %s %d", inst->data->id->name, (int)inst->transforms.size());
inst->transforms.push_back(gf_matrix_from_transform(dupli->mat));
}
else {
MeshInstance *inst = mesh_instance(p_id);
if (!inst) {
inst = &mesh_instances_.lookup_or_add_default(p_id);
inst->data = std::make_unique<MeshData>(scene_delegate_, ob, p_id);
inst->data->init();
inst->data->insert();
}
else {
inst->data->update();
}
ID_LOG(2, "Mesh %s %d", inst->data->id->name, (int)mesh_transforms_.size());
inst->indices.push_back(mesh_transforms_.size());
mesh_transforms_.push_back(gf_matrix_from_transform(dupli->mat));
}
}
void InstancerData::post_update()
{
/* Remove mesh intances without indices */
mesh_instances_.remove_if([&](auto item) {
bool res = item.value.indices.empty();
if (res) {
item.value.data->remove();
}
return res;
});
/* Update light intances and remove instances without transforms */
for (auto &l_inst : light_instances_.values()) {
update_light_instance(l_inst);
}
light_instances_.remove_if([&](auto item) { return item.value.transforms.empty(); });
/* Insert/remove/update instancer in RenderIndex */
pxr::HdRenderIndex &index = scene_delegate_->GetRenderIndex();
if (mesh_instances_.is_empty()) {
/* Important: removing instancer when light_instances_ are empty too */
if (index.HasInstancer(prim_id) && light_instances_.is_empty()) {
index.RemoveInstancer(prim_id);
ID_LOG(1, "Remove instancer");
}
}
else {
if (index.HasInstancer(prim_id)) {
index.GetChangeTracker().MarkInstancerDirty(prim_id, pxr::HdChangeTracker::AllDirty);
ID_LOG(1, "Update instancer");
}
else {
index.InsertInstancer(scene_delegate_, prim_id);
ID_LOG(1, "Insert instancer");
}
}
}
pxr::SdfPath InstancerData::object_prim_id(Object *object) const
{
/* Making id of object in form like <prefix>_<pointer in 16 hex digits format> */
char name[32];
snprintf(name, sizeof(name), "O_%p", object);
return prim_id.AppendElementString(name);
}
pxr::SdfPath InstancerData::light_prim_id(LightInstance const &inst, int index) const
{
char name[16];
snprintf(name, sizeof(name), "L_%08x", index);
return inst.data->prim_id.AppendElementString(name);
}
int InstancerData::light_prim_id_index(pxr::SdfPath const &id) const
{
int index;
sscanf(id.GetName().c_str(), "L_%x", &index);
return index;
}
void InstancerData::update_light_instance(LightInstance &inst)
{
auto &render_index = scene_delegate_->GetRenderIndex();
LightData &l_data = *inst.data;
int i;
pxr::SdfPath p;
/* Remove old light instances */
while (inst.count > inst.transforms.size()) {
--inst.count;
p = light_prim_id(inst, inst.count);
render_index.RemoveSprim(l_data.prim_type_, p);
ID_LOG(2, "Remove %s", p.GetText());
}
/* Update current light instances */
if (inst.data->prim_type((Light *)((Object *)l_data.id)->data) != l_data.prim_type_) {
/* Recreate instances when prim_type was changed */
for (i = 0; i < inst.count; ++i) {
p = light_prim_id(inst, i);
render_index.RemoveSprim(l_data.prim_type_, p);
ID_LOG(2, "Remove %s", p.GetText());
}
inst.data->init();
for (i = 0; i < inst.count; ++i) {
p = light_prim_id(inst, i);
render_index.InsertSprim(l_data.prim_type_, scene_delegate_, p);
ID_LOG(2, "Insert %s (%s)", p.GetText(), l_data.id->name);
}
}
else {
/* Update light instances*/
pxr::HdDirtyBits bits = pxr::HdLight::DirtyTransform;
Object *obj = (Object *)inst.data->id;
if (obj->id.recalc & ID_RECALC_GEOMETRY || ((ID *)obj->data)->recalc & ID_RECALC_GEOMETRY) {
l_data.init();
bits = pxr::HdLight::AllDirty;
}
for (i = 0; i < inst.count; ++i) {
p = light_prim_id(inst, i);
render_index.GetChangeTracker().MarkSprimDirty(p, bits);
ID_LOG(2, "Update %s (%s)", p.GetText(), l_data.id->name);
}
}
/* Add new light instances */
while (inst.count < inst.transforms.size()) {
p = light_prim_id(inst, inst.count);
render_index.InsertSprim(l_data.prim_type_, scene_delegate_, p);
ID_LOG(2, "Insert %s (%s)", p.GetText(), l_data.id->name);
++inst.count;
}
}
InstancerData::MeshInstance *InstancerData::mesh_instance(pxr::SdfPath const &id) const
{
auto m_inst = mesh_instances_.lookup_ptr(id.GetPathElementCount() == 4 ? id.GetParentPath() :
id);
if (!m_inst) {
return nullptr;
}
return const_cast<MeshInstance *>(m_inst);
}
InstancerData::LightInstance *InstancerData::light_instance(pxr::SdfPath const &id) const
{
auto l_inst = light_instances_.lookup_ptr(id.GetPathElementCount() == 4 ? id.GetParentPath() :
id);
if (!l_inst) {
return nullptr;
}
return const_cast<LightInstance *>(l_inst);
}
} // namespace blender::render::hydra

View File

@ -1,89 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include "BLI_utildefines.h"
#include <pxr/base/arch/fileSystem.h>
#include <pxr/usd/ar/resolver.h>
#include <pxr/usd/ar/resolverContextBinder.h>
#include <pxr/usd/ar/resolverScopedCache.h>
#ifdef WITH_MATERIALX
# include <pxr/usd/usdMtlx/reader.h>
# include <pxr/usd/usdMtlx/utils.h>
#endif
#include <pxr/usd/usdShade/material.h>
#include <pxr/usd/usdShade/shader.h>
#include <pxr/usdImaging/usdImaging/materialParamUtils.h>
#include <pxr/imaging/hd/material.h>
#include <pxr/imaging/hd/tokens.h>
#include "mtlx_hydra_adapter.h"
namespace blender::render::hydra {
void hdmtlx_convert_to_materialnetworkmap(std::string const &mtlx_path,
pxr::TfTokenVector const &shader_source_types,
pxr::TfTokenVector const &render_contexts,
pxr::HdMaterialNetworkMap *out)
{
#ifdef WITH_MATERIALX
if (mtlx_path.empty()) {
return;
}
std::string basePath = pxr::TfGetPathName(mtlx_path);
pxr::ArResolver &resolver = pxr::ArGetResolver();
const pxr::ArResolverContext context = resolver.CreateDefaultContextForAsset(mtlx_path);
pxr::ArResolverContextBinder binder(context);
pxr::ArResolverScopedCache resolver_cache;
std::string mtlxName = pxr::TfGetBaseName(mtlx_path);
std::string stage_id = pxr::TfStringPrintf(
"%s%s%s.usda", basePath.c_str(), ARCH_PATH_SEP, mtlxName.c_str());
pxr::UsdStageRefPtr stage = pxr::UsdStage::CreateInMemory(stage_id, context);
try {
MaterialX::DocumentPtr doc = pxr::UsdMtlxReadDocument(mtlx_path);
pxr::UsdMtlxRead(doc, stage);
}
catch (MaterialX::ExceptionFoundCycle &x) {
Tf_PostErrorHelper(pxr::TF_CALL_CONTEXT,
pxr::TF_DIAGNOSTIC_RUNTIME_ERROR_TYPE,
"MaterialX cycle found: %s\n",
x.what());
return;
}
catch (MaterialX::Exception &x) {
Tf_PostErrorHelper(pxr::TF_CALL_CONTEXT,
pxr::TF_DIAGNOSTIC_RUNTIME_ERROR_TYPE,
"MaterialX error: %s\n",
x.what());
return;
}
if (pxr::UsdPrim materials = stage->GetPrimAtPath(pxr::SdfPath("/MaterialX/Materials"))) {
if (pxr::UsdPrimSiblingRange children = materials.GetChildren()) {
if (auto material = pxr::UsdShadeMaterial(*children.begin())) {
if (pxr::UsdShadeShader mtlx_surface = material.ComputeSurfaceSource(render_contexts)) {
UsdImagingBuildHdMaterialNetworkFromTerminal(mtlx_surface.GetPrim(),
pxr::HdMaterialTerminalTokens->surface,
shader_source_types,
render_contexts,
out,
pxr::UsdTimeCode::Default());
}
}
}
}
#else
UNUSED_VARS(mtlx_path, shader_source_types, render_contexts, out);
#endif
}
} // namespace blender::render::hydra

View File

@ -1,16 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#pragma once
#include <pxr/base/tf/token.h>
#include <pxr/imaging/hd/material.h>
namespace blender::render::hydra {
void hdmtlx_convert_to_materialnetworkmap(std::string const &mtlx_path,
pxr::TfTokenVector const &shader_source_types,
pxr::TfTokenVector const &render_contexts,
pxr::HdMaterialNetworkMap *out);
} // namespace blender::render::hydra

View File

@ -1,17 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2023 Blender Foundation */
#pragma once
#include <pxr/base/tf/token.h>
#include "BLI_map.hh"
namespace blender::render::hydra {
struct SceneDelegateSettings {
pxr::TfToken mx_filename_key;
Map<pxr::TfToken, pxr::VtValue> render_tokens;
};
}; // namespace blender::render::hydra

View File

@ -1,23 +1,33 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#include "viewport_engine.h"
#include <pxr/base/gf/camera.h> #include <pxr/base/gf/camera.h>
#include <pxr/imaging/glf/drawTarget.h> #include <pxr/imaging/glf/drawTarget.h>
#include <pxr/usd/usdGeom/camera.h> #include <pxr/usd/usdGeom/camera.h>
#include "DNA_camera_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_vec_types.h" /* this include must be before BKE_camera.h due to "rctf" type */ #include "DNA_vec_types.h" /* this include must be before BKE_camera.h due to "rctf" type */
#include "DNA_view3d_types.h"
#include "BKE_camera.h"
#include "BLI_math_matrix.h" #include "BLI_math_matrix.h"
#include "BLI_timecode.h" #include "BLI_timecode.h"
#include "DEG_depsgraph_query.h"
#include "DNA_camera_types.h"
#include "DNA_screen_types.h"
#include "GPU_matrix.h"
#include "PIL_time.h" #include "PIL_time.h"
#include "camera.h" #include "BKE_camera.h"
#include "viewport_engine.h" #include "BKE_context.h"
#include "DEG_depsgraph_query.h"
#include "GPU_context.h"
#include "GPU_matrix.h"
#include "RE_engine.h"
#include "hydra/camera.h"
namespace blender::render::hydra { namespace blender::render::hydra {
@ -29,17 +39,18 @@ struct ViewSettings {
pxr::GfCamera gf_camera(); pxr::GfCamera gf_camera();
CameraData camera_data; io::hydra::CameraData camera_data;
int screen_width; int screen_width;
int screen_height; int screen_height;
pxr::GfVec4i border; pxr::GfVec4i border;
}; };
ViewSettings::ViewSettings(bContext *context) : camera_data(context) ViewSettings::ViewSettings(bContext *context)
: camera_data(CTX_wm_view3d(context), CTX_wm_region(context))
{ {
View3D *view3d = CTX_wm_view3d(context); View3D *view3d = CTX_wm_view3d(context);
RegionView3D *region_data = (RegionView3D *)CTX_wm_region_data(context); RegionView3D *region_data = static_cast<RegionView3D *>(CTX_wm_region_data(context));
ARegion *region = CTX_wm_region(context); ARegion *region = CTX_wm_region(context);
screen_width = region->winx; screen_width = region->winx;
@ -56,7 +67,7 @@ ViewSettings::ViewSettings(bContext *context) : camera_data(context)
Object *camera_obj = scene->camera; Object *camera_obj = scene->camera;
float camera_points[4][3]; float camera_points[4][3];
BKE_camera_view_frame(scene, (Camera *)camera_obj->data, camera_points); BKE_camera_view_frame(scene, static_cast<Camera *>(camera_obj->data), camera_points);
float screen_points[4][2]; float screen_points[4][2];
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
@ -175,8 +186,6 @@ void DrawTexture::write_data(int width, int height, const void *data)
GPU_RGBA16F, GPU_RGBA16F,
GPU_TEXTURE_USAGE_GENERAL, GPU_TEXTURE_USAGE_GENERAL,
(float *)data); (float *)data);
GPU_texture_filter_mode(texture_, true);
GPU_texture_mipmap_mode(texture_, true, true);
} }
void DrawTexture::draw(GPUShader *shader, const pxr::GfVec4d &viewport) void DrawTexture::draw(GPUShader *shader, const pxr::GfVec4d &viewport)
@ -232,6 +241,14 @@ void ViewportEngine::render(Depsgraph *depsgraph, bContext *context)
render_task_delegate_->add_aov(pxr::HdAovTokens->color); render_task_delegate_->add_aov(pxr::HdAovTokens->color);
} }
/* Workaround missing/buggy VAOs in hgiGL and hdSt. For OpenGL compatibility
* profile this is not a problem, but for core profile it is. */
GLuint VAO;
if (GPU_backend_get_type() == GPU_BACKEND_OPENGL) {
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
}
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_IMAGE); GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_IMAGE);
GPU_shader_bind(shader); GPU_shader_bind(shader);
@ -253,6 +270,10 @@ void ViewportEngine::render(Depsgraph *depsgraph, bContext *context)
GPU_shader_unbind(); GPU_shader_unbind();
if (GPU_backend_get_type() == GPU_BACKEND_OPENGL) {
glDeleteVertexArrays(1, &VAO);
}
if (renderer_percent_done() == 0.0f) { if (renderer_percent_done() == 0.0f) {
time_begin_ = PIL_check_seconds_timer(); time_begin_ = PIL_check_seconds_timer();
} }

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011-2022 Blender Foundation */ * SPDX-FileCopyrightText: 2011-2022 Blender Foundation */
#pragma once #pragma once
@ -14,6 +14,10 @@
namespace blender::render::hydra { namespace blender::render::hydra {
class DrawTexture { class DrawTexture {
private:
GPUTexture *texture_ = nullptr;
GPUBatch *batch_;
public: public:
DrawTexture(); DrawTexture();
~DrawTexture(); ~DrawTexture();
@ -24,11 +28,13 @@ class DrawTexture {
GPUTexture *texture() const; GPUTexture *texture() const;
private: private:
GPUTexture *texture_ = nullptr;
GPUBatch *batch_;
}; };
class ViewportEngine : public Engine { class ViewportEngine : public Engine {
private:
double time_begin_;
DrawTexture draw_texture_;
public: public:
using Engine::Engine; using Engine::Engine;
@ -37,11 +43,6 @@ class ViewportEngine : public Engine {
private: private:
void notify_status(const std::string &title, const std::string &info); void notify_status(const std::string &title, const std::string &info);
private:
double time_begin_;
DrawTexture draw_texture_;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -919,9 +919,16 @@ static void engine_render_view_layer(Render *re,
/* Sync data to engine, within draw lock so scene data can be accessed safely. */ /* Sync data to engine, within draw lock so scene data can be accessed safely. */
if (use_engine) { if (use_engine) {
const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT);
if (use_gpu_context) {
DRW_render_context_enable(engine->re);
}
if (engine->type->update) { if (engine->type->update) {
engine->type->update(engine, re->main, engine->depsgraph); engine->type->update(engine, re->main, engine->depsgraph);
} }
if (use_gpu_context) {
DRW_render_context_disable(engine->re);
}
} }
if (re->draw_lock) { if (re->draw_lock) {