Add scene setting to export through either Hydra or USD, for debugging #65

Merged
Brecht Van Lommel merged 7 commits from brecht/blender:hydra-usd-export into hydra-render 2023-07-14 19:41:17 +02:00
19 changed files with 404 additions and 136 deletions

View File

@ -950,6 +950,25 @@ class RENDER_PT_simplify_greasepencil(RenderButtonsPanel, Panel, GreasePencilSim
bl_options = {'DEFAULT_CLOSED'} bl_options = {'DEFAULT_CLOSED'}
class RENDER_PT_hydra_debug(RenderButtonsPanel, Panel):
bl_label = "Hydra Debug"
bl_options = {'DEFAULT_CLOSED'}
bl_order = 200
COMPAT_ENGINES = {'HYDRA_STORM'}
@classmethod
def poll(cls, context):
prefs = context.preferences
return (context.engine in cls.COMPAT_ENGINES) and prefs.view.show_developer_ui
def draw(self, context):
layout = self.layout
layout.use_property_split = True
hydra = context.scene.hydra
layout.prop(hydra, "export_method")
classes = ( classes = (
RENDER_PT_context, RENDER_PT_context,
RENDER_PT_eevee_sampling, RENDER_PT_eevee_sampling,
@ -985,6 +1004,7 @@ classes = (
RENDER_PT_opengl_color, RENDER_PT_opengl_color,
RENDER_PT_opengl_options, RENDER_PT_opengl_options,
RENDER_PT_opengl_film, RENDER_PT_opengl_film,
RENDER_PT_hydra_debug,
RENDER_PT_color_management, RENDER_PT_color_management,
RENDER_PT_color_management_curves, RENDER_PT_color_management_curves,
RENDER_PT_simplify, RENDER_PT_simplify,

View File

@ -93,6 +93,7 @@ set(SRC
intern/usd_reader_volume.cc intern/usd_reader_volume.cc
intern/usd_reader_xform.cc intern/usd_reader_xform.cc
usd.hh
usd.h usd.h
intern/usd_asset_utils.h intern/usd_asset_utils.h

View File

@ -3,6 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later */ * SPDX-License-Identifier: GPL-2.0-or-later */
#include "usd.h" #include "usd.h"
#include "usd.hh"
#include "usd_hierarchy_iterator.h" #include "usd_hierarchy_iterator.h"
#include <pxr/base/plug/registry.h> #include <pxr/base/plug/registry.h>
@ -198,67 +199,41 @@ static bool perform_usdz_conversion(const ExportJobData *data)
return true; return true;
} }
static void export_startjob(void *customdata, static pxr::UsdStageRefPtr export_to_stage(const USDExportParams &params,
/* Cannot be const, this function implements wm_jobs_start_callback. Depsgraph *depsgraph,
* NOLINTNEXTLINE: readability-non-const-parameter. */ const char *filepath,
bool *stop, bool *stop,
bool *do_update, bool *do_update,
float *progress) float *progress)
{ {
ExportJobData *data = static_cast<ExportJobData *>(customdata); pxr::UsdStageRefPtr usd_stage = pxr::UsdStage::CreateNew(filepath);
data->export_ok = false;
data->start_time = timeit::Clock::now();
G.is_rendering = true;
if (data->wm) {
WM_set_locked_interface(data->wm, true);
}
G.is_break = false;
/* Construct the depsgraph for exporting. */
Scene *scene = DEG_get_input_scene(data->depsgraph);
if (data->params.visible_objects_only) {
DEG_graph_build_from_view_layer(data->depsgraph);
}
else {
DEG_graph_build_for_all_objects(data->depsgraph);
}
BKE_scene_graph_update_tagged(data->depsgraph, data->bmain);
*progress = 0.0f;
*do_update = true;
/* For restoring the current frame after exporting animation is done. */
const int orig_frame = scene->r.cfra;
pxr::UsdStageRefPtr usd_stage = pxr::UsdStage::CreateNew(data->unarchived_filepath);
if (!usd_stage) { if (!usd_stage) {
/* This happens when the USD JSON files cannot be found. When that happens, return usd_stage;
* the USD library doesn't know it has the functionality to write USDA and
* USDC files, and creating a new UsdStage fails. */
WM_reportf(RPT_ERROR,
"USD Export: unable to find suitable USD plugin to write %s",
data->unarchived_filepath);
return;
} }
usd_stage->SetMetadata(pxr::UsdGeomTokens->upAxis, pxr::VtValue(pxr::UsdGeomTokens->z)); Scene *scene = DEG_get_input_scene(depsgraph);
Main *bmain = DEG_get_bmain(depsgraph);
usd_stage->SetMetadata(pxr::UsdGeomTokens->metersPerUnit, double(scene->unit.scale_length)); usd_stage->SetMetadata(pxr::UsdGeomTokens->metersPerUnit, double(scene->unit.scale_length));
usd_stage->GetRootLayer()->SetDocumentation(std::string("Blender v") + usd_stage->GetRootLayer()->SetDocumentation(std::string("Blender v") +
BKE_blender_version_string()); BKE_blender_version_string());
/* Set up the stage for animated data. */ /* Set up the stage for animated data. */
if (data->params.export_animation) { if (params.export_animation) {
usd_stage->SetTimeCodesPerSecond(FPS); usd_stage->SetTimeCodesPerSecond(FPS);
usd_stage->SetStartTimeCode(scene->r.sfra); usd_stage->SetStartTimeCode(scene->r.sfra);
usd_stage->SetEndTimeCode(scene->r.efra); usd_stage->SetEndTimeCode(scene->r.efra);
} }
ensure_root_prim(usd_stage, data->params); /* For restoring the current frame after exporting animation is done. */
const int orig_frame = scene->r.cfra;
USDHierarchyIterator iter(data->bmain, data->depsgraph, usd_stage, data->params); usd_stage->SetMetadata(pxr::UsdGeomTokens->upAxis, pxr::VtValue(pxr::UsdGeomTokens->z));
ensure_root_prim(usd_stage, params);
if (data->params.export_animation) { USDHierarchyIterator iter(bmain, depsgraph, usd_stage, params);
if (params.export_animation) {
/* Writing the animated frames is not 100% of the work, but it's our best guess. */ /* Writing the animated frames is not 100% of the work, but it's our best guess. */
float progress_per_frame = 1.0f / std::max(1, (scene->r.efra - scene->r.sfra + 1)); float progress_per_frame = 1.0f / std::max(1, (scene->r.efra - scene->r.sfra + 1));
@ -270,13 +245,17 @@ static void export_startjob(void *customdata,
/* Update the scene for the next frame to render. */ /* Update the scene for the next frame to render. */
scene->r.cfra = int(frame); scene->r.cfra = int(frame);
scene->r.subframe = frame - scene->r.cfra; scene->r.subframe = frame - scene->r.cfra;
BKE_scene_graph_update_for_newframe(data->depsgraph); BKE_scene_graph_update_for_newframe(depsgraph);
iter.set_export_frame(frame); iter.set_export_frame(frame);
iter.iterate_and_write(); iter.iterate_and_write();
*progress += progress_per_frame; if (progress) {
*do_update = true; *progress += progress_per_frame;
}
if (do_update) {
*do_update = true;
}
} }
} }
else { else {
@ -296,14 +275,65 @@ static void export_startjob(void *customdata,
} }
} }
usd_stage->GetRootLayer()->Save();
/* Finish up by going back to the keyframe that was current before we started. */ /* Finish up by going back to the keyframe that was current before we started. */
if (scene->r.cfra != orig_frame) { if (scene->r.cfra != orig_frame) {
scene->r.cfra = orig_frame; scene->r.cfra = orig_frame;
BKE_scene_graph_update_for_newframe(data->depsgraph); BKE_scene_graph_update_for_newframe(depsgraph);
} }
return usd_stage;
}
pxr::UsdStageRefPtr export_to_stage(const USDExportParams &params,
Depsgraph *depsgraph,
const char *filepath)
{
return export_to_stage(params, depsgraph, filepath, nullptr, nullptr, nullptr);
}
static void export_startjob(void *customdata,
/* Cannot be const, this function implements wm_jobs_start_callback.
* NOLINTNEXTLINE: readability-non-const-parameter. */
bool *stop,
bool *do_update,
float *progress)
{
ExportJobData *data = static_cast<ExportJobData *>(customdata);
data->export_ok = false;
data->start_time = timeit::Clock::now();
G.is_rendering = true;
if (data->wm) {
WM_set_locked_interface(data->wm, true);
}
G.is_break = false;
/* Construct the depsgraph for exporting. */
if (data->params.visible_objects_only) {
DEG_graph_build_from_view_layer(data->depsgraph);
}
else {
DEG_graph_build_for_all_objects(data->depsgraph);
}
BKE_scene_graph_update_tagged(data->depsgraph, data->bmain);
*progress = 0.0f;
*do_update = true;
pxr::UsdStageRefPtr usd_stage = export_to_stage(
data->params, data->depsgraph, data->unarchived_filepath, stop, do_update, progress);
if (!usd_stage) {
/* This happens when the USD JSON files cannot be found. When that happens,
* the USD library doesn't know it has the functionality to write USDA and
* USDC files, and creating a new UsdStage fails. */
WM_reportf(RPT_ERROR,
"USD Export: unable to find suitable USD plugin to write %s",
data->unarchived_filepath);
return;
}
usd_stage->GetRootLayer()->Save();
if (data->targets_usdz()) { if (data->targets_usdz()) {
bool usd_conversion_success = perform_usdz_conversion(data); bool usd_conversion_success = perform_usdz_conversion(data);
if (!usd_conversion_success) { if (!usd_conversion_success) {

View File

@ -0,0 +1,18 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <pxr/usd/usd/stage.h>
struct Depsgraph;
struct USDExportParams;
namespace blender::io::usd {
pxr::UsdStageRefPtr export_to_stage(const USDExportParams &params,
Depsgraph *depsgraph,
const char *filepath);
};

View File

@ -227,6 +227,11 @@
SCE_EEVEE_SSR_HALF_RESOLUTION | SCE_EEVEE_SHADOW_SOFT, \ SCE_EEVEE_SSR_HALF_RESOLUTION | SCE_EEVEE_SHADOW_SOFT, \
} }
#define _DNA_DEFAULT_SceneHydra \
{ \
.export_method = SCE_HYDRA_EXPORT_HYDRA, \
}
#define _DNA_DEFAULT_Scene \ #define _DNA_DEFAULT_Scene \
{ \ { \
.cursor = _DNA_DEFAULT_View3DCursor, \ .cursor = _DNA_DEFAULT_View3DCursor, \
@ -240,6 +245,8 @@
.safe_areas = _DNA_DEFAULT_DisplaySafeAreas, \ .safe_areas = _DNA_DEFAULT_DisplaySafeAreas, \
\ \
.eevee = _DNA_DEFAULT_SceneEEVEE, \ .eevee = _DNA_DEFAULT_SceneEEVEE, \
\
.hydra = _DNA_DEFAULT_SceneHydra, \
} }
/** \} */ /** \} */

View File

@ -1883,6 +1883,11 @@ typedef struct SceneGpencil {
char _pad[4]; char _pad[4];
} SceneGpencil; } SceneGpencil;
typedef struct SceneHydra {
int export_method;
int _pad0;
} SceneHydra;
/** \} */ /** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@ -2029,6 +2034,7 @@ typedef struct Scene {
struct SceneDisplay display; struct SceneDisplay display;
struct SceneEEVEE eevee; struct SceneEEVEE eevee;
struct SceneGpencil grease_pencil_settings; struct SceneGpencil grease_pencil_settings;
struct SceneHydra hydra;
} Scene; } Scene;
/** \} */ /** \} */
@ -2830,6 +2836,13 @@ enum {
SCE_DISPLAY_AA_SAMPLES_32 = 32, SCE_DISPLAY_AA_SAMPLES_32 = 32,
}; };
/** #SceneHydra->export_method */
enum {
SCE_HYDRA_EXPORT_HYDRA = 0,
SCE_HYDRA_EXPORT_USD = 1,
};
/** \} */ /** \} */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1197,6 +1197,11 @@ static char *rna_SceneGpencil_path(const PointerRNA * /*ptr*/)
return BLI_strdup("grease_pencil_settings"); return BLI_strdup("grease_pencil_settings");
} }
static char *rna_SceneHydra_path(const PointerRNA * /*ptr*/)
{
return BLI_strdup("hydra");
}
static int rna_RenderSettings_stereoViews_skip(CollectionPropertyIterator *iter, void * /*data*/) static int rna_RenderSettings_stereoViews_skip(CollectionPropertyIterator *iter, void * /*data*/)
{ {
ListBaseIterator *internal = &iter->internal.listbase; ListBaseIterator *internal = &iter->internal.listbase;
@ -7974,6 +7979,36 @@ static void rna_def_scene_gpencil(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, nullptr); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, nullptr);
} }
static void rna_def_scene_hydra(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static const EnumPropertyItem hydra_export_method_items[] = {
{SCE_HYDRA_EXPORT_HYDRA,
"HYDRA",
0,
"Hydra",
"Fast interactive editing through native Hydra integration"},
{SCE_HYDRA_EXPORT_USD,
"USD",
0,
"USD",
"Export scene through USD file, for accurate comparison with USD file export"},
{0, nullptr, 0, nullptr, nullptr},
};
srna = RNA_def_struct(brna, "SceneHydra", nullptr);
RNA_def_struct_path_func(srna, "rna_SceneHydra_path");
RNA_def_struct_ui_text(srna, "Scene Hydra", "Scene Hydra render engine settings");
prop = RNA_def_property(srna, "export_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, hydra_export_method_items);
RNA_def_property_ui_text(
prop, "Export Method", "How to export the Blender scene to the Hydra render engine");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, nullptr);
}
void RNA_def_scene(BlenderRNA *brna) void RNA_def_scene(BlenderRNA *brna)
{ {
StructRNA *srna; StructRNA *srna;
@ -8467,6 +8502,11 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "SceneGpencil"); RNA_def_property_struct_type(prop, "SceneGpencil");
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease Pencil settings for the scene"); RNA_def_property_ui_text(prop, "Grease Pencil", "Grease Pencil settings for the scene");
/* Hydra */
prop = RNA_def_property(srna, "hydra", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "SceneHydra");
RNA_def_property_ui_text(prop, "Hydra", "Hydra settings for the scene");
/* Nestled Data. */ /* Nestled Data. */
/* *** Non-Animated *** */ /* *** Non-Animated *** */
RNA_define_animate_sdna(false); RNA_define_animate_sdna(false);
@ -8485,6 +8525,7 @@ void RNA_def_scene(BlenderRNA *brna)
rna_def_display_safe_areas(brna); rna_def_display_safe_areas(brna);
rna_def_scene_display(brna); rna_def_scene_display(brna);
rna_def_scene_eevee(brna); rna_def_scene_eevee(brna);
rna_def_scene_hydra(brna);
rna_def_view_layer_aov(brna); rna_def_view_layer_aov(brna);
rna_def_view_layer_lightgroup(brna); rna_def_view_layer_lightgroup(brna);
rna_def_view_layer_eevee(brna); rna_def_view_layer_eevee(brna);

View File

@ -42,6 +42,7 @@ set(INC
../../depsgraph ../../depsgraph
../../blenkernel ../../blenkernel
../../imbuf ../../imbuf
../../io/usd
../../gpu ../../gpu
../../gpu/intern ../../gpu/intern
../../python/intern ../../python/intern
@ -90,30 +91,33 @@ set(SRC
simple_light_task_delegate.cc simple_light_task_delegate.cc
simple_light_task_delegate.h simple_light_task_delegate.h
scene_delegate/blender_scene_delegate.h
scene_delegate/blender_scene_delegate.cc scene_delegate/blender_scene_delegate.cc
scene_delegate/id.h scene_delegate/blender_scene_delegate.h
scene_delegate/id.cc
scene_delegate/object.h
scene_delegate/object.cc
scene_delegate/material.h
scene_delegate/material.cc
scene_delegate/mesh.h
scene_delegate/mesh.cc
scene_delegate/curves.h
scene_delegate/curves.cc scene_delegate/curves.cc
scene_delegate/mtlx_hydra_adapter.h scene_delegate/curves.h
scene_delegate/mtlx_hydra_adapter.cc scene_delegate/id.cc
scene_delegate/light.h scene_delegate/id.h
scene_delegate/light.cc
scene_delegate/world.h
scene_delegate/world.cc
scene_delegate/instancer.h
scene_delegate/instancer.cc
scene_delegate/image.h
scene_delegate/image.cc scene_delegate/image.cc
scene_delegate/volume.h 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/settings.h
scene_delegate/usd_scene_delegate.cc
scene_delegate/usd_scene_delegate.hh
scene_delegate/volume.cc scene_delegate/volume.cc
scene_delegate/volume.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}")

View File

@ -9,8 +9,11 @@
#include <pxr/usd/usdGeom/tokens.h> #include <pxr/usd/usdGeom/tokens.h>
#include "BLI_path_util.h" #include "BLI_path_util.h"
#include "GPU_context.h" #include "GPU_context.h"
#include "DEG_depsgraph_query.h"
#include "engine.h" #include "engine.h"
namespace blender::render::hydra { namespace blender::render::hydra {
@ -47,8 +50,6 @@ Engine::Engine(RenderEngine *bl_engine, const std::string &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));
free_camera_delegate_ = std::make_unique<pxr::HdxFreeCameraSceneDelegate>( free_camera_delegate_ = std::make_unique<pxr::HdxFreeCameraSceneDelegate>(
render_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("freeCamera")); render_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("freeCamera"));
scene_delegate_ = std::make_unique<BlenderSceneDelegate>(
render_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"), this);
render_task_delegate_ = std::make_unique<RenderTaskDelegate>( render_task_delegate_ = std::make_unique<RenderTaskDelegate>(
render_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("renderTask")); render_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("renderTask"));
if (render_delegate_name == "HdStormRendererPlugin") { if (render_delegate_name == "HdStormRendererPlugin") {
@ -62,21 +63,44 @@ Engine::Engine(RenderEngine *bl_engine, const std::string &render_delegate_name)
void Engine::sync(Depsgraph *depsgraph, bContext *context) void Engine::sync(Depsgraph *depsgraph, bContext *context)
{ {
scene_delegate_->populate(depsgraph, context); const Scene *scene = DEG_get_evaluated_scene(depsgraph);
}
void Engine::sync_usd(pxr::UsdStageRefPtr stage) if (scene->hydra.export_method == SCE_HYDRA_EXPORT_HYDRA) {
{ /* Fast path. */
if (!usd_delegate_) { usd_scene_delegate_.reset();
usd_delegate_ = std::make_unique<pxr::UsdImagingDelegate>(
render_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("usd")); if (!hydra_scene_delegate_) {
pxr::SdfPath scene_path = pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene");
hydra_scene_delegate_ = std::make_unique<BlenderSceneDelegate>(
render_index_.get(), scene_path, scene_delegate_settings_);
}
hydra_scene_delegate_->populate(depsgraph, context);
}
else {
/* Slow USD export for reference. */
if (hydra_scene_delegate_) {
/* Freeing the Hydra scene delegate crashes as something internal to USD
* still holds a pointer to it, only clear it instead. */
hydra_scene_delegate_->clear();
}
if (!usd_scene_delegate_) {
pxr::SdfPath scene_path = pxr::SdfPath::AbsoluteRootPath().AppendElementString("usd_scene");
usd_scene_delegate_ = std::make_unique<USDSceneDelegate>(
render_index_.get(), scene_path, scene_delegate_settings_);
}
usd_scene_delegate_->populate(depsgraph, context);
} }
usd_delegate_->Populate(stage->GetPseudoRoot());
} }
void Engine::set_sync_setting(const std::string &key, const pxr::VtValue &val) void Engine::set_sync_setting(const std::string &key, const pxr::VtValue &val)
{ {
scene_delegate_->set_setting(key, val); if (key == "MaterialXFilenameKey") {
scene_delegate_settings_.mx_filename_key = pxr::TfToken(val.Get<std::string>());
}
else {
scene_delegate_settings_.render_tokens.add_overwrite(pxr::TfToken(key), val);
}
} }
void Engine::set_render_setting(const std::string &key, const pxr::VtValue &val) void Engine::set_render_setting(const std::string &key, const pxr::VtValue &val)

View File

@ -18,9 +18,11 @@
#include "CLG_log.h" #include "CLG_log.h"
#include "render_task_delegate.h" #include "render_task_delegate.h"
#include "scene_delegate/blender_scene_delegate.h"
#include "simple_light_task_delegate.h" #include "simple_light_task_delegate.h"
#include "scene_delegate/blender_scene_delegate.h"
#include "scene_delegate/usd_scene_delegate.hh"
namespace blender::render::hydra { namespace blender::render::hydra {
extern struct CLG_LogRef *LOG_RENDER_HYDRA; extern struct CLG_LogRef *LOG_RENDER_HYDRA;
@ -31,7 +33,6 @@ class Engine {
virtual ~Engine() = default; virtual ~Engine() = default;
void sync(Depsgraph *depsgraph, bContext *context); void sync(Depsgraph *depsgraph, bContext *context);
void sync_usd(pxr::UsdStageRefPtr stage);
virtual void render(Depsgraph *depsgraph) = 0; virtual void render(Depsgraph *depsgraph) = 0;
void set_sync_setting(const std::string &key, const pxr::VtValue &val); void set_sync_setting(const std::string &key, const pxr::VtValue &val);
@ -42,18 +43,21 @@ class Engine {
protected: protected:
float renderer_percent_done(); float renderer_percent_done();
RenderEngine *bl_engine_; RenderEngine *bl_engine_ = nullptr;
/* The order is important due to deletion order */ /* The order is important due to deletion order */
pxr::HgiUniquePtr hgi_; pxr::HgiUniquePtr hgi_;
pxr::HdDriver hgi_driver_; pxr::HdDriver hgi_driver_;
pxr::HdPluginRenderDelegateUniqueHandle render_delegate_; pxr::HdPluginRenderDelegateUniqueHandle render_delegate_;
std::unique_ptr<pxr::HdRenderIndex> render_index_; std::unique_ptr<pxr::HdRenderIndex> render_index_;
std::unique_ptr<BlenderSceneDelegate> scene_delegate_;
SceneDelegateSettings scene_delegate_settings_;
std::unique_ptr<BlenderSceneDelegate> hydra_scene_delegate_;
std::unique_ptr<USDSceneDelegate> usd_scene_delegate_;
std::unique_ptr<RenderTaskDelegate> render_task_delegate_; std::unique_ptr<RenderTaskDelegate> render_task_delegate_;
std::unique_ptr<pxr::HdxFreeCameraSceneDelegate> free_camera_delegate_; std::unique_ptr<pxr::HdxFreeCameraSceneDelegate> free_camera_delegate_;
std::unique_ptr<SimpleLightTaskDelegate> simple_light_task_delegate_; std::unique_ptr<SimpleLightTaskDelegate> simple_light_task_delegate_;
std::unique_ptr<pxr::UsdImagingDelegate> usd_delegate_;
std::unique_ptr<pxr::HdEngine> engine_; std::unique_ptr<pxr::HdEngine> engine_;
}; };

View File

@ -148,14 +148,21 @@ void FinalEngineGPU::render(Depsgraph *depsgraph)
GPU_framebuffer_bind(framebuffer); GPU_framebuffer_bind(framebuffer);
float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
pxr::VtValue world_color = scene_delegate_->GetLightParamValue(
scene_delegate_->GetDelegateID().AppendElementString("World"), pxr::HdLightTokens->color); /* Workaround Storm rendering with transparent background. Does not currently work for
if (!world_color.IsEmpty()) { * USD, and should probably be optional depending on the Blender film transparency setting. */
auto &c = world_color.Get<pxr::GfVec3f>(); if (hydra_scene_delegate_ && render_delegate_name == "HdStormRendererPlugin") {
clear_color[0] = c[0]; pxr::VtValue world_color = hydra_scene_delegate_->GetLightParamValue(
clear_color[1] = c[1]; hydra_scene_delegate_->GetDelegateID().AppendElementString("World"),
clear_color[2] = c[2]; pxr::HdLightTokens->color);
if (!world_color.IsEmpty()) {
auto &c = world_color.Get<pxr::GfVec3f>();
clear_color[0] = c[0];
clear_color[1] = c[1];
clear_color[2] = c[2];
}
} }
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 /* Important: we have to create and bind at least one Vertex Array Object (VAO) before render

View File

@ -123,24 +123,6 @@ static PyObject *engine_sync_func(PyObject * /*self*/, PyObject *args)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject *engine_sync_usd_func(PyObject * /*self*/, PyObject *args)
{
PyObject *pyengine, *pystage;
if (!PyArg_ParseTuple(args, "OO", &pyengine, &pystage)) {
Py_RETURN_NONE;
}
Engine *engine = (Engine *)PyLong_AsVoidPtr(pyengine);
boost::python::extract<pxr::UsdStageRefPtr> extract(pystage);
pxr::UsdStagePtr stage = extract();
CLOG_INFO(LOG_RENDER_HYDRA, 2, "Engine %p", engine);
engine->sync_usd(stage);
Py_RETURN_NONE;
}
static PyObject *engine_render_func(PyObject * /*self*/, PyObject *args) static PyObject *engine_render_func(PyObject * /*self*/, PyObject *args)
{ {
PyObject *pyengine, *pydepsgraph; PyObject *pyengine, *pydepsgraph;
@ -253,7 +235,6 @@ static PyMethodDef methods[] = {
{"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_sync", engine_sync_func, METH_VARARGS, ""},
{"engine_sync_usd", engine_sync_usd_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, ""},

View File

@ -28,8 +28,8 @@ bool BlenderSceneDelegate::ShadingSettings::operator==(const ShadingSettings &ot
BlenderSceneDelegate::BlenderSceneDelegate(pxr::HdRenderIndex *parent_index, BlenderSceneDelegate::BlenderSceneDelegate(pxr::HdRenderIndex *parent_index,
pxr::SdfPath const &delegate_id, pxr::SdfPath const &delegate_id,
Engine *engine) const SceneDelegateSettings &settings)
: HdSceneDelegate(parent_index, delegate_id), engine(engine) : 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());
} }
@ -259,16 +259,6 @@ void BlenderSceneDelegate::clear()
view3d = nullptr; view3d = nullptr;
} }
void BlenderSceneDelegate::set_setting(const std::string &key, const pxr::VtValue &val)
{
if (key == "MaterialXFilenameKey") {
settings.mx_filename_key = pxr::TfToken(val.Get<std::string>());
}
else {
settings.render_tokens.add_overwrite(pxr::TfToken(key), val);
}
}
pxr::SdfPath BlenderSceneDelegate::prim_id(ID *id, const char *prefix) const pxr::SdfPath BlenderSceneDelegate::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> */

View File

@ -17,6 +17,7 @@
#include "light.h" #include "light.h"
#include "mesh.h" #include "mesh.h"
#include "object.h" #include "object.h"
#include "settings.h"
#include "volume.h" #include "volume.h"
#include "world.h" #include "world.h"
@ -34,11 +35,6 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
friend MaterialData; /* has access to objects and instancers */ friend MaterialData; /* has access to objects and instancers */
public: public:
struct Settings {
pxr::TfToken mx_filename_key;
Map<pxr::TfToken, pxr::VtValue> render_tokens;
};
struct ShadingSettings { struct ShadingSettings {
bool use_scene_lights = true; bool use_scene_lights = true;
bool use_scene_world = true; bool use_scene_world = true;
@ -51,7 +47,7 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
BlenderSceneDelegate(pxr::HdRenderIndex *parent_index, BlenderSceneDelegate(pxr::HdRenderIndex *parent_index,
pxr::SdfPath const &delegate_id, pxr::SdfPath const &delegate_id,
Engine *engine); const SceneDelegateSettings &settings);
~BlenderSceneDelegate() override = default; ~BlenderSceneDelegate() override = default;
/* Delegate methods */ /* Delegate methods */
@ -77,14 +73,12 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
void populate(Depsgraph *depsgraph, bContext *context); void populate(Depsgraph *depsgraph, bContext *context);
void clear(); void clear();
void set_setting(const std::string &key, const pxr::VtValue &val);
Depsgraph *depsgraph = nullptr; Depsgraph *depsgraph = nullptr;
bContext *context = nullptr; bContext *context = nullptr;
View3D *view3d = nullptr; View3D *view3d = nullptr;
Scene *scene = nullptr; Scene *scene = nullptr;
Engine *engine; const SceneDelegateSettings &settings;
Settings settings;
ShadingSettings shading_settings; ShadingSettings shading_settings;
private: private:

View File

@ -19,7 +19,7 @@ namespace blender::render::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)
{ {
char dir_path[FILE_MAX]; char dir_path[FILE_MAX];
BLI_path_join(dir_path, sizeof(dir_path), BKE_tempdir_session(), "hydra_image_cache"); BLI_path_join(dir_path, sizeof(dir_path), BKE_tempdir_session(), "hydra", "image_cache");
if (mkdir) { if (mkdir) {
BLI_dir_create_recursive(dir_path); BLI_dir_create_recursive(dir_path);
} }

View File

@ -140,7 +140,7 @@ pxr::VtValue LightData::get_data(pxr::TfToken const &key) const
return pxr::VtValue(it->second); return pxr::VtValue(it->second);
} }
pxr::VtValue *ret_ptr = scene_delegate_->settings.render_tokens.lookup_ptr(key); const pxr::VtValue *ret_ptr = scene_delegate_->settings.render_tokens.lookup_ptr(key);
if (ret_ptr) { if (ret_ptr) {
return *ret_ptr; return *ret_ptr;
} }

View File

@ -0,0 +1,17 @@
/* 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

@ -0,0 +1,79 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include "usd_scene_delegate.hh"
#include "BLI_fileops.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BKE_appdir.h"
#include "DEG_depsgraph_query.h"
#include "usd.h"
#include "usd.hh"
namespace blender::render::hydra {
USDSceneDelegate::USDSceneDelegate(pxr::HdRenderIndex *render_index,
pxr::SdfPath const &delegate_id,
const SceneDelegateSettings &settings)
: render_index_(render_index), delegate_id_(delegate_id), settings_(settings)
{
/* Temporary directory to write any additional files to, like image or VDB files. */
char unique_name[FILE_MAXFILE];
BLI_snprintf(unique_name, sizeof(unique_name), "%p", this);
char dir_path[FILE_MAX];
BLI_path_join(
dir_path, sizeof(dir_path), BKE_tempdir_session(), "usd_scene_delegate", unique_name);
BLI_dir_create_recursive(dir_path);
char file_path[FILE_MAX];
BLI_path_join(file_path, sizeof(file_path), dir_path, "scene.usdc");
temp_dir_ = dir_path;
temp_file_ = file_path;
}
USDSceneDelegate::~USDSceneDelegate()
{
BLI_delete(temp_dir_.c_str(), true, true);
}
void USDSceneDelegate::populate(Depsgraph *depsgraph, bContext * /*context*/)
{
/* TODO: implement MaterialX support in USD exporter. */
const bool use_materialx = !settings_.mx_filename_key.IsEmpty();
(void)use_materialx;
USDExportParams params = {};
params.export_hair = true;
params.export_uvmaps = true;
params.export_normals = true;
params.export_materials = true;
params.selected_objects_only = false;
params.visible_objects_only = true;
params.use_instancing = true;
params.evaluation_mode = DEG_get_mode(depsgraph);
params.generate_preview_surface = true;
params.export_textures = true;
params.overwrite_textures = true;
params.relative_paths = true;
/* Create clean directory for export. */
BLI_delete(temp_dir_.c_str(), true, true);
BLI_dir_create_recursive(temp_dir_.c_str());
/* Free previous delegate and stage first to save memory. */
delegate_.reset();
stage_.Reset();
/* Convert depsgraph to stage + aditional file in temp directory. */
stage_ = io::usd::export_to_stage(params, depsgraph, temp_file_.c_str());
delegate_ = std::make_unique<pxr::UsdImagingDelegate>(render_index_, delegate_id_);
delegate_->Populate(stage_->GetPseudoRoot());
}
} // namespace blender::render::hydra

View File

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