forked from blender/blender
Add scene setting to export through either Hydra or USD, for debugging #65
@ -950,6 +950,25 @@ class RENDER_PT_simplify_greasepencil(RenderButtonsPanel, Panel, GreasePencilSim
|
||||
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 = (
|
||||
RENDER_PT_context,
|
||||
RENDER_PT_eevee_sampling,
|
||||
@ -985,6 +1004,7 @@ classes = (
|
||||
RENDER_PT_opengl_color,
|
||||
RENDER_PT_opengl_options,
|
||||
RENDER_PT_opengl_film,
|
||||
RENDER_PT_hydra_debug,
|
||||
RENDER_PT_color_management,
|
||||
RENDER_PT_color_management_curves,
|
||||
RENDER_PT_simplify,
|
||||
|
@ -93,6 +93,7 @@ set(SRC
|
||||
intern/usd_reader_volume.cc
|
||||
intern/usd_reader_xform.cc
|
||||
|
||||
usd.hh
|
||||
usd.h
|
||||
|
||||
intern/usd_asset_utils.h
|
||||
|
@ -3,6 +3,7 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "usd.h"
|
||||
#include "usd.hh"
|
||||
#include "usd_hierarchy_iterator.h"
|
||||
|
||||
#include <pxr/base/plug/registry.h>
|
||||
@ -198,67 +199,41 @@ static bool perform_usdz_conversion(const ExportJobData *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void export_startjob(void *customdata,
|
||||
/* Cannot be const, this function implements wm_jobs_start_callback.
|
||||
* NOLINTNEXTLINE: readability-non-const-parameter. */
|
||||
static pxr::UsdStageRefPtr export_to_stage(const USDExportParams ¶ms,
|
||||
Depsgraph *depsgraph,
|
||||
const char *filepath,
|
||||
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. */
|
||||
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);
|
||||
pxr::UsdStageRefPtr usd_stage = pxr::UsdStage::CreateNew(filepath);
|
||||
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;
|
||||
return usd_stage;
|
||||
}
|
||||
|
||||
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->GetRootLayer()->SetDocumentation(std::string("Blender v") +
|
||||
BKE_blender_version_string());
|
||||
|
||||
/* Set up the stage for animated data. */
|
||||
if (data->params.export_animation) {
|
||||
if (params.export_animation) {
|
||||
usd_stage->SetTimeCodesPerSecond(FPS);
|
||||
usd_stage->SetStartTimeCode(scene->r.sfra);
|
||||
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. */
|
||||
float progress_per_frame = 1.0f / std::max(1, (scene->r.efra - scene->r.sfra + 1));
|
||||
|
||||
@ -270,15 +245,19 @@ static void export_startjob(void *customdata,
|
||||
/* Update the scene for the next frame to render. */
|
||||
scene->r.cfra = int(frame);
|
||||
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.iterate_and_write();
|
||||
|
||||
if (progress) {
|
||||
*progress += progress_per_frame;
|
||||
}
|
||||
if (do_update) {
|
||||
*do_update = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* If we're not animating, a single iteration over all objects is enough. */
|
||||
iter.iterate_and_write();
|
||||
@ -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. */
|
||||
if (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 ¶ms,
|
||||
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()) {
|
||||
bool usd_conversion_success = perform_usdz_conversion(data);
|
||||
if (!usd_conversion_success) {
|
||||
|
18
source/blender/io/usd/usd.hh
Normal file
18
source/blender/io/usd/usd.hh
Normal 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 ¶ms,
|
||||
Depsgraph *depsgraph,
|
||||
const char *filepath);
|
||||
|
||||
};
|
@ -227,6 +227,11 @@
|
||||
SCE_EEVEE_SSR_HALF_RESOLUTION | SCE_EEVEE_SHADOW_SOFT, \
|
||||
}
|
||||
|
||||
#define _DNA_DEFAULT_SceneHydra \
|
||||
{ \
|
||||
.export_method = SCE_HYDRA_EXPORT_HYDRA, \
|
||||
}
|
||||
|
||||
#define _DNA_DEFAULT_Scene \
|
||||
{ \
|
||||
.cursor = _DNA_DEFAULT_View3DCursor, \
|
||||
@ -240,6 +245,8 @@
|
||||
.safe_areas = _DNA_DEFAULT_DisplaySafeAreas, \
|
||||
\
|
||||
.eevee = _DNA_DEFAULT_SceneEEVEE, \
|
||||
\
|
||||
.hydra = _DNA_DEFAULT_SceneHydra, \
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -1883,6 +1883,11 @@ typedef struct SceneGpencil {
|
||||
char _pad[4];
|
||||
} SceneGpencil;
|
||||
|
||||
typedef struct SceneHydra {
|
||||
int export_method;
|
||||
int _pad0;
|
||||
} SceneHydra;
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@ -2029,6 +2034,7 @@ typedef struct Scene {
|
||||
struct SceneDisplay display;
|
||||
struct SceneEEVEE eevee;
|
||||
struct SceneGpencil grease_pencil_settings;
|
||||
struct SceneHydra hydra;
|
||||
} Scene;
|
||||
|
||||
/** \} */
|
||||
@ -2830,6 +2836,13 @@ enum {
|
||||
SCE_DISPLAY_AA_SAMPLES_32 = 32,
|
||||
};
|
||||
|
||||
/** #SceneHydra->export_method */
|
||||
|
||||
enum {
|
||||
SCE_HYDRA_EXPORT_HYDRA = 0,
|
||||
SCE_HYDRA_EXPORT_USD = 1,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -1197,6 +1197,11 @@ static char *rna_SceneGpencil_path(const PointerRNA * /*ptr*/)
|
||||
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*/)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@ -8467,6 +8502,11 @@ void RNA_def_scene(BlenderRNA *brna)
|
||||
RNA_def_property_struct_type(prop, "SceneGpencil");
|
||||
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. */
|
||||
/* *** Non-Animated *** */
|
||||
RNA_define_animate_sdna(false);
|
||||
@ -8485,6 +8525,7 @@ void RNA_def_scene(BlenderRNA *brna)
|
||||
rna_def_display_safe_areas(brna);
|
||||
rna_def_scene_display(brna);
|
||||
rna_def_scene_eevee(brna);
|
||||
rna_def_scene_hydra(brna);
|
||||
rna_def_view_layer_aov(brna);
|
||||
rna_def_view_layer_lightgroup(brna);
|
||||
rna_def_view_layer_eevee(brna);
|
||||
|
@ -42,6 +42,7 @@ set(INC
|
||||
../../depsgraph
|
||||
../../blenkernel
|
||||
../../imbuf
|
||||
../../io/usd
|
||||
../../gpu
|
||||
../../gpu/intern
|
||||
../../python/intern
|
||||
@ -90,30 +91,33 @@ set(SRC
|
||||
simple_light_task_delegate.cc
|
||||
simple_light_task_delegate.h
|
||||
|
||||
scene_delegate/blender_scene_delegate.h
|
||||
scene_delegate/blender_scene_delegate.cc
|
||||
scene_delegate/id.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/blender_scene_delegate.h
|
||||
scene_delegate/curves.cc
|
||||
scene_delegate/mtlx_hydra_adapter.h
|
||||
scene_delegate/mtlx_hydra_adapter.cc
|
||||
scene_delegate/light.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/curves.h
|
||||
scene_delegate/id.cc
|
||||
scene_delegate/id.h
|
||||
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.h
|
||||
scene_delegate/world.cc
|
||||
scene_delegate/world.h
|
||||
)
|
||||
|
||||
blender_add_lib(bf_render_hydra "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
@ -9,8 +9,11 @@
|
||||
#include <pxr/usd/usdGeom/tokens.h>
|
||||
|
||||
#include "BLI_path_util.h"
|
||||
|
||||
#include "GPU_context.h"
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "engine.h"
|
||||
|
||||
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));
|
||||
free_camera_delegate_ = std::make_unique<pxr::HdxFreeCameraSceneDelegate>(
|
||||
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_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("renderTask"));
|
||||
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)
|
||||
{
|
||||
scene_delegate_->populate(depsgraph, context);
|
||||
const Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
||||
|
||||
if (scene->hydra.export_method == SCE_HYDRA_EXPORT_HYDRA) {
|
||||
/* Fast path. */
|
||||
usd_scene_delegate_.reset();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void Engine::sync_usd(pxr::UsdStageRefPtr stage)
|
||||
{
|
||||
if (!usd_delegate_) {
|
||||
usd_delegate_ = std::make_unique<pxr::UsdImagingDelegate>(
|
||||
render_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("usd"));
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
@ -18,9 +18,11 @@
|
||||
#include "CLG_log.h"
|
||||
|
||||
#include "render_task_delegate.h"
|
||||
#include "scene_delegate/blender_scene_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 {
|
||||
|
||||
extern struct CLG_LogRef *LOG_RENDER_HYDRA;
|
||||
@ -31,7 +33,6 @@ class Engine {
|
||||
virtual ~Engine() = default;
|
||||
|
||||
void sync(Depsgraph *depsgraph, bContext *context);
|
||||
void sync_usd(pxr::UsdStageRefPtr stage);
|
||||
virtual void render(Depsgraph *depsgraph) = 0;
|
||||
|
||||
void set_sync_setting(const std::string &key, const pxr::VtValue &val);
|
||||
@ -42,18 +43,21 @@ class Engine {
|
||||
protected:
|
||||
float renderer_percent_done();
|
||||
|
||||
RenderEngine *bl_engine_;
|
||||
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_;
|
||||
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<pxr::HdxFreeCameraSceneDelegate> free_camera_delegate_;
|
||||
std::unique_ptr<SimpleLightTaskDelegate> simple_light_task_delegate_;
|
||||
std::unique_ptr<pxr::UsdImagingDelegate> usd_delegate_;
|
||||
std::unique_ptr<pxr::HdEngine> engine_;
|
||||
};
|
||||
|
||||
|
@ -148,14 +148,21 @@ void FinalEngineGPU::render(Depsgraph *depsgraph)
|
||||
GPU_framebuffer_bind(framebuffer);
|
||||
|
||||
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
|
||||
* USD, and should probably be optional depending on the Blender film transparency setting. */
|
||||
if (hydra_scene_delegate_ && render_delegate_name == "HdStormRendererPlugin") {
|
||||
pxr::VtValue world_color = hydra_scene_delegate_->GetLightParamValue(
|
||||
hydra_scene_delegate_->GetDelegateID().AppendElementString("World"),
|
||||
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);
|
||||
|
||||
/* Important: we have to create and bind at least one Vertex Array Object (VAO) before render
|
||||
|
@ -123,24 +123,6 @@ static PyObject *engine_sync_func(PyObject * /*self*/, PyObject *args)
|
||||
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)
|
||||
{
|
||||
PyObject *pyengine, *pydepsgraph;
|
||||
@ -253,7 +235,6 @@ static PyMethodDef methods[] = {
|
||||
{"engine_create", engine_create_func, METH_VARARGS, ""},
|
||||
{"engine_free", engine_free_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_view_draw", engine_view_draw_func, METH_VARARGS, ""},
|
||||
{"engine_set_sync_setting", engine_set_sync_setting_func, METH_VARARGS, ""},
|
||||
|
@ -28,8 +28,8 @@ bool BlenderSceneDelegate::ShadingSettings::operator==(const ShadingSettings &ot
|
||||
|
||||
BlenderSceneDelegate::BlenderSceneDelegate(pxr::HdRenderIndex *parent_index,
|
||||
pxr::SdfPath const &delegate_id,
|
||||
Engine *engine)
|
||||
: HdSceneDelegate(parent_index, delegate_id), engine(engine)
|
||||
const SceneDelegateSettings &settings)
|
||||
: HdSceneDelegate(parent_index, delegate_id), settings(settings)
|
||||
{
|
||||
instancer_data_ = std::make_unique<InstancerData>(this, instancer_prim_id());
|
||||
}
|
||||
@ -259,16 +259,6 @@ void BlenderSceneDelegate::clear()
|
||||
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
|
||||
{
|
||||
/* Making id of object in form like <prefix>_<pointer in 16 hex digits format> */
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "light.h"
|
||||
#include "mesh.h"
|
||||
#include "object.h"
|
||||
#include "settings.h"
|
||||
#include "volume.h"
|
||||
#include "world.h"
|
||||
|
||||
@ -34,11 +35,6 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
|
||||
friend MaterialData; /* has access to objects and instancers */
|
||||
|
||||
public:
|
||||
struct Settings {
|
||||
pxr::TfToken mx_filename_key;
|
||||
Map<pxr::TfToken, pxr::VtValue> render_tokens;
|
||||
};
|
||||
|
||||
struct ShadingSettings {
|
||||
bool use_scene_lights = true;
|
||||
bool use_scene_world = true;
|
||||
@ -51,7 +47,7 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
|
||||
|
||||
BlenderSceneDelegate(pxr::HdRenderIndex *parent_index,
|
||||
pxr::SdfPath const &delegate_id,
|
||||
Engine *engine);
|
||||
const SceneDelegateSettings &settings);
|
||||
~BlenderSceneDelegate() override = default;
|
||||
|
||||
/* Delegate methods */
|
||||
@ -77,14 +73,12 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
|
||||
|
||||
void populate(Depsgraph *depsgraph, bContext *context);
|
||||
void clear();
|
||||
void set_setting(const std::string &key, const pxr::VtValue &val);
|
||||
|
||||
Depsgraph *depsgraph = nullptr;
|
||||
bContext *context = nullptr;
|
||||
View3D *view3d = nullptr;
|
||||
Scene *scene = nullptr;
|
||||
Engine *engine;
|
||||
Settings settings;
|
||||
const SceneDelegateSettings &settings;
|
||||
ShadingSettings shading_settings;
|
||||
|
||||
private:
|
||||
|
@ -19,7 +19,7 @@ namespace blender::render::hydra {
|
||||
static std::string get_cache_file(const std::string &file_name, bool mkdir = true)
|
||||
{
|
||||
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) {
|
||||
BLI_dir_create_recursive(dir_path);
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ pxr::VtValue LightData::get_data(pxr::TfToken const &key) const
|
||||
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) {
|
||||
return *ret_ptr;
|
||||
}
|
||||
|
17
source/blender/render/hydra/scene_delegate/settings.h
Normal file
17
source/blender/render/hydra/scene_delegate/settings.h
Normal 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
|
@ -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
|
@ -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
|
Loading…
Reference in New Issue
Block a user