Create possibility to provide render settings via BlenderSceneDelegate #41

Merged
Bogdan Nagirniak merged 10 commits from BLEN-349 into hydra-render 2023-05-19 20:19:17 +02:00
17 changed files with 254 additions and 213 deletions

View File

@ -21,10 +21,15 @@ class CustomHydraRenderEngine(HydraRenderEngine):
bpy_hydra.register_plugins(["/path/to/plugin")]) bpy_hydra.register_plugins(["/path/to/plugin")])
def get_delegate_settings(self, engine_type): def get_sync_settings(self, engine_type):
Review

Consider to add a note that these settings refer to keys that Hydra asks.

Consider to add a note that these settings refer to keys that Hydra asks.
return { return {
'setting1': 1, 'MaterialXFilenameKey': "MaterialXFilename",
'setting2': "2", }
def get_render_settings(self, engine_type):
return {
'enableTinyPrimCulling': True,
'maxLights': 8,
} }
``` ```
""" """
@ -73,18 +78,38 @@ class HydraRenderEngine(bpy.types.RenderEngine):
def unregister(cls): def unregister(cls):
pass pass
def get_delegate_settings(self, engine_type): def get_sync_settings(self, engine_type):
"""

We need explanations of how these methods should be used / overridden

We need explanations of how these methods should be used / overridden
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 {} return {}
# final render # final render
def update(self, data, depsgraph): def update(self, data, depsgraph):
engine_type = 'PREVIEW' if self.is_preview else 'FINAL' engine_type = 'PREVIEW' if self.is_preview else 'FINAL'
self.engine_ptr = _bpy_hydra.engine_create(self.as_pointer(), engine_type, self.delegate_id) self.engine_ptr = _bpy_hydra.engine_create(self.as_pointer(), engine_type, self.delegate_id)
delegate_settings = self.get_delegate_settings(engine_type)
_bpy_hydra.engine_sync(self.engine_ptr, depsgraph.as_pointer(), bpy.context.as_pointer(), delegate_settings) 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 render(self, depsgraph): def render(self, depsgraph):
if self.engine_ptr: 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()) _bpy_hydra.engine_render(self.engine_ptr, depsgraph.as_pointer())
# viewport render # viewport render
@ -92,8 +117,13 @@ class HydraRenderEngine(bpy.types.RenderEngine):
if not self.engine_ptr: if not self.engine_ptr:
self.engine_ptr = _bpy_hydra.engine_create(self.as_pointer(), 'VIEWPORT', self.delegate_id) self.engine_ptr = _bpy_hydra.engine_create(self.as_pointer(), 'VIEWPORT', self.delegate_id)
delegate_settings = self.get_delegate_settings('VIEWPORT') for key, val in self.get_sync_settings('VIEWPORT').items():
_bpy_hydra.engine_sync(self.engine_ptr, depsgraph.as_pointer(), context.as_pointer(), delegate_settings) _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): def view_draw(self, context, depsgraph):
if not self.engine_ptr: if not self.engine_ptr:

View File

@ -18,12 +18,12 @@ 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)
: bl_engine_(bl_engine), render_delegate_name_(render_delegate_name) : render_delegate_name(render_delegate_name), bl_engine_(bl_engine)
{ {
pxr::HdRendererPluginRegistry &registry = pxr::HdRendererPluginRegistry::GetInstance(); pxr::HdRendererPluginRegistry &registry = pxr::HdRendererPluginRegistry::GetInstance();
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE(); pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
render_delegate_ = registry.CreateRenderDelegate(pxr::TfToken(render_delegate_name_)); render_delegate_ = registry.CreateRenderDelegate(pxr::TfToken(render_delegate_name));
/* USD has limited support for Vulkan. To make it works USD should be built /* USD has limited support for Vulkan. To make it works USD should be built
* with PXR_ENABLE_VULKAN_SUPPORT=TRUE which is not possible now */ * with PXR_ENABLE_VULKAN_SUPPORT=TRUE which is not possible now */
@ -43,9 +43,11 @@ 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") {
simple_light_task_delegate_ = std::make_unique<SimpleLightTaskDelegate>( simple_light_task_delegate_ = std::make_unique<SimpleLightTaskDelegate>(
render_index_.get(), render_index_.get(),
pxr::SdfPath::AbsoluteRootPath().AppendElementString("simpleLightTask")); pxr::SdfPath::AbsoluteRootPath().AppendElementString("simpleLightTask"));
@ -54,6 +56,21 @@ Engine::Engine(RenderEngine *bl_engine, const std::string &render_delegate_name)
engine_ = std::make_unique<pxr::HdEngine>(); engine_ = std::make_unique<pxr::HdEngine>();
} }
void Engine::sync(Depsgraph *depsgraph, bContext *context)
{
scene_delegate_->populate(depsgraph, context);
}
void Engine::set_sync_setting(const std::string &key, const pxr::VtValue &val)
{
scene_delegate_->set_setting(key, val);
}
void Engine::set_render_setting(const std::string &key, const pxr::VtValue &val)
{
render_delegate_->SetRenderSetting(pxr::TfToken(key), val);
}
float Engine::renderer_percent_done() float Engine::renderer_percent_done()
{ {
pxr::VtDictionary render_stats = render_delegate_->GetRenderStats(); pxr::VtDictionary render_stats = render_delegate_->GetRenderStats();

View File

@ -28,16 +28,18 @@ class Engine {
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;
virtual void sync(Depsgraph *depsgraph, void sync(Depsgraph *depsgraph, bContext *context);
bContext *context,
pxr::HdRenderSettingsMap &render_settings) = 0;
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_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_; RenderEngine *bl_engine_;
std::string render_delegate_name_;
/* The order is important due to deletion order */ /* The order is important due to deletion order */
pxr::HgiUniquePtr hgi_; pxr::HgiUniquePtr hgi_;

View File

@ -13,22 +13,6 @@
namespace blender::render::hydra { namespace blender::render::hydra {
void FinalEngine::sync(Depsgraph *depsgraph,
bContext *context,
pxr::HdRenderSettingsMap &render_settings)
{
scene_delegate_ = std::make_unique<BlenderSceneDelegate>(
render_index_.get(),
pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"),
BlenderSceneDelegate::EngineType::FINAL,
render_delegate_name_);
scene_delegate_->populate(depsgraph, context);
for (auto const &setting : render_settings) {
render_delegate_->SetRenderSetting(setting.first, setting.second);
}
}
void FinalEngine::render(Depsgraph *depsgraph) void FinalEngine::render(Depsgraph *depsgraph)
{ {
prepare_for_render(depsgraph); prepare_for_render(depsgraph);

View File

@ -11,10 +11,7 @@ class FinalEngine : public Engine {
public: public:
using Engine::Engine; using Engine::Engine;
virtual void sync(Depsgraph *depsgraph, void render(Depsgraph *b_depsgraph) override;
bContext *context,
pxr::HdRenderSettingsMap &render_settings) override;
virtual void render(Depsgraph *b_depsgraph) override;
protected: protected:
void update_render_result(); void update_render_result();

View File

@ -13,46 +13,36 @@ const double LIFETIME = 180.0;
std::unique_ptr<PreviewEngine> PreviewEngine::instance_; std::unique_ptr<PreviewEngine> PreviewEngine::instance_;
PreviewEngine *PreviewEngine::get_instance(RenderEngine *bl_engine, PreviewEngine *PreviewEngine::create(RenderEngine *bl_engine,
const std::string &render_delegate_name) const std::string &render_delegate_name)
{ {
if (!instance_) { if (!instance_) {
instance_ = std::make_unique<PreviewEngine>(bl_engine, render_delegate_name); instance_ = std::make_unique<PreviewEngine>(bl_engine, render_delegate_name);
} }
if (BLI_timer_is_registered((uintptr_t)instance_.get())) { else if (instance_->render_delegate_name != render_delegate_name) {
/* Unregister timer while PreviewEngine is working */ instance_->render_delegate_->Stop();
BLI_timer_unregister((uintptr_t)instance_.get()); instance_ = std::make_unique<PreviewEngine>(bl_engine, render_delegate_name);
}
else {
instance_->bl_engine_ = bl_engine;
}
instance_->scene_delegate_->clear();
if (BLI_timer_is_registered((uintptr_t)&instance_)) {
/* Unregister timer while PreviewEngine is working */
BLI_timer_unregister((uintptr_t)&instance_);
} }
instance_->update(bl_engine, render_delegate_name);
return instance_.get(); return instance_.get();
} }
void PreviewEngine::schedule_free() void PreviewEngine::free()
{ {
instance_->render_delegate_->Stop(); instance_->render_delegate_->Stop();
/* Register timer for schedule free PreviewEngine instance */ /* Register timer for schedule free PreviewEngine instance */
BLI_timer_register((uintptr_t)instance_.get(), free_instance, nullptr, nullptr, LIFETIME, true); BLI_timer_register((uintptr_t)&instance_, free_instance, nullptr, nullptr, LIFETIME, true);
}
void PreviewEngine::sync(Depsgraph *depsgraph,
bContext *context,
pxr::HdRenderSettingsMap &render_settings)
{
if (!scene_delegate_) {
scene_delegate_ = std::make_unique<BlenderSceneDelegate>(
render_index_.get(),
pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"),
BlenderSceneDelegate::EngineType::PREVIEW,
render_delegate_name_);
}
scene_delegate_->clear();
scene_delegate_->populate(depsgraph, context);
for (auto const &setting : render_settings) {
render_delegate_->SetRenderSetting(setting.first, setting.second);
}
} }
void PreviewEngine::render(Depsgraph *depsgraph) void PreviewEngine::render(Depsgraph *depsgraph)
@ -96,15 +86,6 @@ double PreviewEngine::free_instance(uintptr_t uuid, void *user_data)
return -1; return -1;
} }
void PreviewEngine::update(RenderEngine *bl_engine, const std::string &render_delegate_name)
{
bl_engine_ = bl_engine;
if (render_delegate_name != render_delegate_name_) {
render_delegate_->Stop();
instance_.reset(new PreviewEngine(bl_engine, render_delegate_name));
}
}
void PreviewEngine::update_render_result(std::vector<float> &pixels) void PreviewEngine::update_render_result(std::vector<float> &pixels)
{ {
RenderResult *result = RE_engine_begin_result( RenderResult *result = RE_engine_begin_result(

View File

@ -9,24 +9,19 @@ namespace blender::render::hydra {
class PreviewEngine : public FinalEngine { class PreviewEngine : public FinalEngine {
public: public:
using FinalEngine::FinalEngine; static PreviewEngine *create(RenderEngine *bl_engine, const std::string &render_delegate_name);
static void free();
static PreviewEngine *get_instance(RenderEngine *bl_engine,
const std::string &render_delegate_name);
static void schedule_free();
void sync(Depsgraph *depsgraph,
bContext *context,
pxr::HdRenderSettingsMap &render_settings) override;
void render(Depsgraph *depsgraph) override; void render(Depsgraph *depsgraph) override;
private: private:
/* Singleton class instance */ using FinalEngine::FinalEngine;
Review

Why did you move it here?

Why did you move it here?
Review

PreviewEngine should be created via PreviewEngine::create() therefore constructor moved to private section.

`PreviewEngine` should be created via `PreviewEngine::create()` therefore constructor moved to private section.
static double free_instance(uintptr_t uuid, void *user_data); static double free_instance(uintptr_t uuid, void *user_data);
static std::unique_ptr<PreviewEngine> instance_;
void update(RenderEngine *bl_engine, const std::string &render_delegate_name);
void update_render_result(std::vector<float> &pixels); void update_render_result(std::vector<float> &pixels);
/* Singleton class instance */
static std::unique_ptr<PreviewEngine> instance_;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -111,7 +111,7 @@ static PyObject *engine_create_func(PyObject * /*self*/, PyObject *args)
engine = new ViewportEngine(bl_engine, render_delegate_id); engine = new ViewportEngine(bl_engine, render_delegate_id);
} }
else if (STREQ(engine_type, "PREVIEW")) { else if (STREQ(engine_type, "PREVIEW")) {
engine = PreviewEngine::get_instance(bl_engine, render_delegate_id); engine = PreviewEngine::create(bl_engine, render_delegate_id);
} }
else { else {
if (bl_engine->type->flag & RE_USE_GPU_CONTEXT) { if (bl_engine->type->flag & RE_USE_GPU_CONTEXT) {
@ -123,7 +123,6 @@ static PyObject *engine_create_func(PyObject * /*self*/, PyObject *args)
} }
CLOG_INFO(LOG_RENDER_HYDRA, 2, "Engine %016llx %s", engine, engine_type); CLOG_INFO(LOG_RENDER_HYDRA, 2, "Engine %016llx %s", engine, engine_type);
return PyLong_FromVoidPtr(engine); return PyLong_FromVoidPtr(engine);
} }
@ -137,7 +136,7 @@ static PyObject *engine_free_func(PyObject * /*self*/, PyObject *args)
Engine *engine = (Engine *)PyLong_AsVoidPtr(pyengine); Engine *engine = (Engine *)PyLong_AsVoidPtr(pyengine);
PreviewEngine *preview_engine = dynamic_cast<PreviewEngine *>(engine); PreviewEngine *preview_engine = dynamic_cast<PreviewEngine *>(engine);
if (preview_engine) { if (preview_engine) {
PreviewEngine::schedule_free(); PreviewEngine::free();
} }
else { else {
delete engine; delete engine;
@ -149,8 +148,8 @@ static PyObject *engine_free_func(PyObject * /*self*/, PyObject *args)
static PyObject *engine_sync_func(PyObject * /*self*/, PyObject *args) static PyObject *engine_sync_func(PyObject * /*self*/, PyObject *args)
{ {
PyObject *pyengine, *pydepsgraph, *pycontext, *pysettings; PyObject *pyengine, *pydepsgraph, *pycontext;
if (!PyArg_ParseTuple(args, "OOOO", &pyengine, &pydepsgraph, &pycontext, &pysettings)) { if (!PyArg_ParseTuple(args, "OOO", &pyengine, &pydepsgraph, &pycontext)) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@ -158,29 +157,7 @@ static PyObject *engine_sync_func(PyObject * /*self*/, PyObject *args)
Depsgraph *depsgraph = (Depsgraph *)PyLong_AsVoidPtr(pydepsgraph); Depsgraph *depsgraph = (Depsgraph *)PyLong_AsVoidPtr(pydepsgraph);
bContext *context = (bContext *)PyLong_AsVoidPtr(pycontext); bContext *context = (bContext *)PyLong_AsVoidPtr(pycontext);
pxr::HdRenderSettingsMap settings; engine->sync(depsgraph, context);
PyObject *pyiter = PyObject_GetIter(pysettings);
if (pyiter) {
PyObject *pykey, *pyval;
while (pykey = PyIter_Next(pyiter)) {
pxr::TfToken key(PyUnicode_AsUTF8(pykey));
pyval = PyDict_GetItem(pysettings, pykey);
if (PyLong_Check(pyval)) {
settings[key] = PyLong_AsLong(pyval);
}
else if (PyFloat_Check(pyval)) {
settings[key] = PyFloat_AsDouble(pyval);
}
else if (PyUnicode_Check(pyval)) {
settings[key] = PyUnicode_AsUTF8(pyval);
}
Py_DECREF(pykey);
}
Py_DECREF(pyiter);
}
engine->sync(depsgraph, context, settings);
CLOG_INFO(LOG_RENDER_HYDRA, 2, "Engine %016llx", engine); CLOG_INFO(LOG_RENDER_HYDRA, 2, "Engine %016llx", engine);
Py_RETURN_NONE; Py_RETURN_NONE;
@ -226,6 +203,54 @@ static PyObject *engine_view_draw_func(PyObject * /*self*/, PyObject *args)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static pxr::VtValue get_setting_val(PyObject *pyval)
{
pxr::VtValue val;
if (PyBool_Check(pyval)) {
val = Py_IsTrue(pyval);
}
else if (PyLong_Check(pyval)) {
val = PyLong_AsLong(pyval);
}
else if (PyFloat_Check(pyval)) {
val = PyFloat_AsDouble(pyval);
}
else if (PyUnicode_Check(pyval)) {
val = std::string(PyUnicode_AsUTF8(pyval));
}
return val;
}
static PyObject *engine_set_sync_setting_func(PyObject * /*self*/, PyObject *args)
{
PyObject *pyengine, *pyval;
char *key;
if (!PyArg_ParseTuple(args, "OsO", &pyengine, &key, &pyval)) {
Py_RETURN_NONE;
}
Engine *engine = (Engine *)PyLong_AsVoidPtr(pyengine);
engine->set_sync_setting(key, get_setting_val(pyval));
CLOG_INFO(LOG_RENDER_HYDRA, 3, "Engine %016llx: %s", engine, key);
Py_RETURN_NONE;
}
static PyObject *engine_set_render_setting_func(PyObject * /*self*/, PyObject *args)
{
PyObject *pyengine, *pyval;
char *key;
if (!PyArg_ParseTuple(args, "OsO", &pyengine, &key, &pyval)) {
Py_RETURN_NONE;
}
Engine *engine = (Engine *)PyLong_AsVoidPtr(pyengine);
engine->set_render_setting(key, get_setting_val(pyval));
CLOG_INFO(LOG_RENDER_HYDRA, 3, "Engine %016llx: %s", engine, key);
Py_RETURN_NONE;
}
static PyMethodDef methods[] = { static PyMethodDef methods[] = {
{"init", init_func, METH_VARARGS, ""}, {"init", init_func, METH_VARARGS, ""},
{"register_plugins", register_plugins_func, METH_VARARGS, ""}, {"register_plugins", register_plugins_func, METH_VARARGS, ""},
@ -236,6 +261,8 @@ static PyMethodDef methods[] = {
{"engine_sync", engine_sync_func, METH_VARARGS, ""}, {"engine_sync", engine_sync_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_render_setting", engine_set_render_setting_func, METH_VARARGS, ""},
{NULL, NULL, 0, NULL}, {NULL, NULL, 0, NULL},
}; };

View File

@ -14,11 +14,8 @@ CLG_LOGREF_DECLARE_GLOBAL(LOG_RENDER_HYDRA_SCENE, "render.hydra.scene");
BlenderSceneDelegate::BlenderSceneDelegate(pxr::HdRenderIndex *parent_index, BlenderSceneDelegate::BlenderSceneDelegate(pxr::HdRenderIndex *parent_index,
pxr::SdfPath const &delegate_id, pxr::SdfPath const &delegate_id,
BlenderSceneDelegate::EngineType engine_type, Engine *engine)
const std::string &render_delegate_name) : HdSceneDelegate(parent_index, delegate_id), engine(engine)
: HdSceneDelegate(parent_index, delegate_id),
engine_type(engine_type),
render_delegate_name(render_delegate_name)
{ {
} }
@ -206,6 +203,13 @@ 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>());
}
}
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> */
@ -376,8 +380,8 @@ void BlenderSceneDelegate::check_updates()
DEGIDIterData data = {0}; DEGIDIterData data = {0};
data.graph = depsgraph; data.graph = depsgraph;
data.only_updated = true; data.only_updated = true;
ITER_BEGIN ( ITER_BEGIN (DEG_iterator_ids_begin, DEG_iterator_ids_next, DEG_iterator_ids_end, &data, ID *, id)
DEG_iterator_ids_begin, DEG_iterator_ids_next, DEG_iterator_ids_end, &data, ID *, id) { {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
2, 2,
@ -451,7 +455,8 @@ void BlenderSceneDelegate::add_new_objects()
DEG_iterator_objects_end, DEG_iterator_objects_end,
&data, &data,
Object *, Object *,
object) { object)
{
update_objects(object); update_objects(object);
update_instancers(object); update_instancers(object);
@ -476,7 +481,8 @@ void BlenderSceneDelegate::remove_unused_objects()
DEG_iterator_objects_end, DEG_iterator_objects_end,
&data, &data,
Object *, Object *,
object) { object)
{
if (ObjectData::is_supported(object)) { if (ObjectData::is_supported(object)) {
available_objects.insert(object_prim_id(object).GetName()); available_objects.insert(object_prim_id(object).GetName());
} }
@ -554,7 +560,8 @@ void BlenderSceneDelegate::update_visibility()
DEG_iterator_objects_end, DEG_iterator_objects_end,
&data, &data,
Object *, Object *,
object) { object)
{
if (!object_data(object_prim_id(object))) { if (!object_data(object_prim_id(object))) {
update_objects(object); update_objects(object);

View File

@ -21,18 +21,21 @@ namespace blender::render::hydra {
extern struct CLG_LogRef *LOG_RENDER_HYDRA_SCENE; extern struct CLG_LogRef *LOG_RENDER_HYDRA_SCENE;
class Engine;
class BlenderSceneDelegate : public pxr::HdSceneDelegate { class BlenderSceneDelegate : public pxr::HdSceneDelegate {
friend ObjectData; /* has access to instances */ friend ObjectData; /* has access to instances */
friend MeshData; /* has access to materials */ friend MeshData; /* has access to materials */
friend MaterialData; /* has access to objects and instancers */ friend MaterialData; /* has access to objects and instancers */
public: public:
enum class EngineType { VIEWPORT = 1, FINAL, PREVIEW }; struct Settings {
pxr::TfToken mx_filename_key;
};
BlenderSceneDelegate(pxr::HdRenderIndex *parent_index, BlenderSceneDelegate(pxr::HdRenderIndex *parent_index,
pxr::SdfPath const &delegate_id, pxr::SdfPath const &delegate_id,
BlenderSceneDelegate::EngineType engine_type, Engine *engine);
const std::string &render_delegate_name);
~BlenderSceneDelegate() override = default; ~BlenderSceneDelegate() override = default;
/* Delegate methods */ /* Delegate methods */
@ -55,14 +58,14 @@ 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);
EngineType engine_type;
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;
std::string render_delegate_name; Settings settings;
private: private:
pxr::SdfPath prim_id(ID *id, const char *prefix) const; pxr::SdfPath prim_id(ID *id, const char *prefix) const;

View File

@ -66,7 +66,8 @@ void InstancerData::update()
Object *object = (Object *)id; Object *object = (Object *)id;
if (id->recalc & ID_RECALC_GEOMETRY || if (id->recalc & ID_RECALC_GEOMETRY ||
(object->data && ((ID *)object->data)->recalc & ID_RECALC_GEOMETRY) || (object->data && ((ID *)object->data)->recalc & ID_RECALC_GEOMETRY) ||
id->recalc & ID_RECALC_TRANSFORM) { id->recalc & ID_RECALC_TRANSFORM)
{
set_instances(); set_instances();
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty( scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
prim_id, pxr::HdChangeTracker::AllDirty); prim_id, pxr::HdChangeTracker::AllDirty);
@ -174,7 +175,8 @@ void InstancerData::check_update(Object *object)
if (l_it != light_instances_.end()) { if (l_it != light_instances_.end()) {
Object *obj = (Object *)l_it->second.data->id; Object *obj = (Object *)l_it->second.data->id;
if (obj->id.recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY) || if (obj->id.recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY) ||
((ID *)obj->data)->recalc & ID_RECALC_GEOMETRY) { ((ID *)obj->data)->recalc & ID_RECALC_GEOMETRY)
{
set_instances(); set_instances();
} }
return; return;

View File

@ -14,6 +14,7 @@
#include "RNA_blender_cpp.h" #include "RNA_blender_cpp.h"
#include "bpy_rna.h" #include "bpy_rna.h"
#include "../engine.h"
#include "blender_scene_delegate.h" #include "blender_scene_delegate.h"
#include "material.h" #include "material.h"
#include "mtlx_hydra_adapter.h" #include "mtlx_hydra_adapter.h"
@ -31,8 +32,65 @@ void MaterialData::init()
{ {
ID_LOG(2, ""); ID_LOG(2, "");
double_sided = (((Material *)id)->blend_flag & MA_BL_CULL_BACKFACE) == 0; double_sided = (((Material *)id)->blend_flag & MA_BL_CULL_BACKFACE) == 0;
material_network_map_ = pxr::VtValue();
export_mtlx();
if (scene_delegate_->settings.mx_filename_key.IsEmpty()) {
write_material_network_map();
}
}
void MaterialData::insert()
{
ID_LOG(2, "");
scene_delegate_->GetRenderIndex().InsertSprim(
pxr::HdPrimTypeTokens->material, scene_delegate_, prim_id);
}
void MaterialData::remove()
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", prim_id.GetText());
scene_delegate_->GetRenderIndex().RemoveSprim(pxr::HdPrimTypeTokens->material, prim_id);
}
void MaterialData::update()
{
ID_LOG(2, "");
bool prev_double_sided = double_sided;
init();
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(prim_id,
pxr::HdMaterial::AllDirty);
if (prev_double_sided != double_sided) {
for (auto &it : scene_delegate_->objects_) {
MeshData *m_data = dynamic_cast<MeshData *>(it.second.get());
if (m_data) {
m_data->update_double_sided(this);
}
}
for (auto &it : scene_delegate_->instancers_) {
it.second->update_double_sided(this);
}
}
}
pxr::VtValue MaterialData::get_data(pxr::TfToken const &key) const
{
pxr::VtValue ret;
if (key == scene_delegate_->settings.mx_filename_key) {
if (!mtlx_path_.GetResolvedPath().empty()) {
ret = mtlx_path_;
}
ID_LOG(3, "%s", key.GetText());
}
return ret;
}
pxr::VtValue MaterialData::get_material_resource() const
{
return material_network_map_;
}
void MaterialData::export_mtlx()
{
/* Call of python function hydra.export_mtlx() */ /* Call of python function hydra.export_mtlx() */
PyGILState_STATE gstate; PyGILState_STATE gstate;
@ -87,71 +145,25 @@ void MaterialData::init()
mtlx_path_ = pxr::SdfAssetPath(path, path); mtlx_path_ = pxr::SdfAssetPath(path, path);
ID_LOG(2, "mtlx=%s", mtlx_path_.GetResolvedPath().c_str()); ID_LOG(2, "mtlx=%s", mtlx_path_.GetResolvedPath().c_str());
}
void MaterialData::write_material_network_map()
{
ID_LOG(2, "");
if (mtlx_path_.GetResolvedPath().empty()) {
material_network_map_ = pxr::VtValue();
return;
}
/* Calculate material network map */
if (!path.empty()) {
pxr::HdRenderDelegate *render_delegate = scene_delegate_->GetRenderIndex().GetRenderDelegate(); pxr::HdRenderDelegate *render_delegate = scene_delegate_->GetRenderIndex().GetRenderDelegate();
pxr::TfTokenVector shader_source_types = render_delegate->GetShaderSourceTypes(); pxr::TfTokenVector shader_source_types = render_delegate->GetShaderSourceTypes();
pxr::TfTokenVector render_contexts = render_delegate->GetMaterialRenderContexts(); pxr::TfTokenVector render_contexts = render_delegate->GetMaterialRenderContexts();
pxr::HdMaterialNetworkMap network_map; pxr::HdMaterialNetworkMap network_map;
hdmtlx_convert_to_materialnetworkmap(path, shader_source_types, render_contexts, &network_map); hdmtlx_convert_to_materialnetworkmap(
mtlx_path_.GetResolvedPath(), shader_source_types, render_contexts, &network_map);
material_network_map_ = network_map; material_network_map_ = network_map;
}
else {
material_network_map_ = pxr::VtValue();
}
}
void MaterialData::insert()
{
ID_LOG(2, "");
scene_delegate_->GetRenderIndex().InsertSprim(
pxr::HdPrimTypeTokens->material, scene_delegate_, prim_id);
}
void MaterialData::remove()
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", prim_id.GetText());
scene_delegate_->GetRenderIndex().RemoveSprim(pxr::HdPrimTypeTokens->material, prim_id);
}
void MaterialData::update()
{
ID_LOG(2, "");
bool prev_double_sided = double_sided;
init();
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(prim_id,
pxr::HdMaterial::AllDirty);
if (prev_double_sided != double_sided) {
for (auto &it : scene_delegate_->objects_) {
MeshData *m_data = dynamic_cast<MeshData *>(it.second.get());
if (m_data) {
m_data->update_double_sided(this);
}
}
for (auto &it : scene_delegate_->instancers_) {
it.second->update_double_sided(this);
}
}
}
pxr::VtValue MaterialData::get_data(pxr::TfToken const &key) const
{
pxr::VtValue ret;
if (key.GetString() == "MaterialXFilename") {
if (!mtlx_path_.GetResolvedPath().empty()) {
ret = mtlx_path_;
}
ID_LOG(3, "%s", key.GetText());
}
return ret;
}
pxr::VtValue MaterialData::get_material_resource() const
{
return material_network_map_;
} }
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -30,6 +30,9 @@ class MaterialData : public IdData {
bool double_sided = true; bool double_sided = true;
private: private:
void export_mtlx();
void write_material_network_map();
pxr::SdfAssetPath mtlx_path_; pxr::SdfAssetPath mtlx_path_;
pxr::VtValue material_network_map_; pxr::VtValue material_network_map_;
}; };

View File

@ -27,7 +27,8 @@ void MeshData::init()
Object *object = (Object *)id; Object *object = (Object *)id;
if (object->type == OB_MESH && object->mode == OB_MODE_OBJECT && if (object->type == OB_MESH && object->mode == OB_MODE_OBJECT &&
BLI_listbase_is_empty(&object->modifiers)) { BLI_listbase_is_empty(&object->modifiers))
{
write_mesh((Mesh *)object->data); write_mesh((Mesh *)object->data);
} }
else { else {

View File

@ -19,6 +19,7 @@
#include "BLI_path_util.h" #include "BLI_path_util.h"
#include "NOD_shader.h" #include "NOD_shader.h"
#include "../engine.h"
#include "blender_scene_delegate.h" #include "blender_scene_delegate.h"
#include "image.h" #include "image.h"
#include "world.h" #include "world.h"
@ -143,7 +144,7 @@ void WorldData::write_transform()
transform = pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -90), pxr::GfVec3d()); transform = pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -90), pxr::GfVec3d());
/* TODO : do this check via RenderSettings*/ /* TODO : do this check via RenderSettings*/
if (scene_delegate_->render_delegate_name == "HdRprPlugin") { if (scene_delegate_->engine->render_delegate_name == "HdRprPlugin") {
transform *= pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -180), transform *= pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -180),
pxr::GfVec3d()); pxr::GfVec3d());
transform *= pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(0.0, 0.0, 1.0), 90.0), transform *= pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(0.0, 0.0, 1.0), 90.0),

View File

@ -217,24 +217,6 @@ void DrawTexture::free()
texture_ = nullptr; texture_ = nullptr;
} }
void ViewportEngine::sync(Depsgraph *depsgraph,
bContext *context,
pxr::HdRenderSettingsMap &render_settings)
{
if (!scene_delegate_) {
scene_delegate_ = std::make_unique<BlenderSceneDelegate>(
render_index_.get(),
pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"),
BlenderSceneDelegate::EngineType::VIEWPORT,
render_delegate_name_);
}
scene_delegate_->populate(depsgraph, context);
for (auto const &setting : render_settings) {
render_delegate_->SetRenderSetting(setting.first, setting.second);
}
}
void ViewportEngine::render(Depsgraph *depsgraph) void ViewportEngine::render(Depsgraph *depsgraph)
{ {
/* Empty function */ /* Empty function */

View File

@ -34,9 +34,6 @@ class ViewportEngine : public Engine {
public: public:
using Engine::Engine; using Engine::Engine;
void sync(Depsgraph *depsgraph,
bContext *context,
pxr::HdRenderSettingsMap &render_settings) override;
void render(Depsgraph *depsgraph) override; void render(Depsgraph *depsgraph) override;
void render(Depsgraph *depsgraph, bContext *context); void render(Depsgraph *depsgraph, bContext *context);