forked from blender/blender
Support multimaterials on one mesh #44
@ -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):
|
||||||
return {
|
return {
|
||||||
'setting1': 1,
|
'MaterialXFilenameKey': "MaterialXFilename",
|
||||||
'setting2': "2",
|
}
|
||||||
|
|
||||||
|
def get_render_settings(self, engine_type):
|
||||||
|
return {
|
||||||
|
'enableTinyPrimCulling': True,
|
||||||
|
'maxLights': 8,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
@ -73,27 +78,52 @@ 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):
|
||||||
|
"""
|
||||||
|
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:
|
||||||
_bpy_hydra.engine_render(self.engine_ptr, depsgraph.as_pointer())
|
return
|
||||||
|
|
||||||
|
for key, val in self.get_render_settings('PREVIEW' if self.is_preview else 'FINAL').items():
|
||||||
|
_bpy_hydra.engine_set_render_setting(self.engine_ptr, key, val)
|
||||||
|
|
||||||
|
_bpy_hydra.engine_render(self.engine_ptr, depsgraph.as_pointer())
|
||||||
|
|
||||||
# viewport render
|
# viewport render
|
||||||
def view_update(self, context, depsgraph):
|
def view_update(self, context, depsgraph):
|
||||||
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:
|
||||||
|
@ -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 ®istry = pxr::HdRendererPluginRegistry::GetInstance();
|
pxr::HdRendererPluginRegistry ®istry = 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();
|
||||||
|
@ -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_;
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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(
|
||||||
|
@ -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;
|
||||||
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
|
||||||
|
@ -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},
|
||||||
};
|
};
|
||||||
|
@ -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> */
|
||||||
|
@ -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;
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate material network map */
|
void MaterialData::write_material_network_map()
|
||||||
if (!path.empty()) {
|
{
|
||||||
pxr::HdRenderDelegate *render_delegate = scene_delegate_->GetRenderIndex().GetRenderDelegate();
|
ID_LOG(2, "");
|
||||||
pxr::TfTokenVector shader_source_types = render_delegate->GetShaderSourceTypes();
|
if (mtlx_path_.GetResolvedPath().empty()) {
|
||||||
pxr::TfTokenVector render_contexts = render_delegate->GetMaterialRenderContexts();
|
|
||||||
|
|
||||||
pxr::HdMaterialNetworkMap network_map;
|
|
||||||
hdmtlx_convert_to_materialnetworkmap(path, shader_source_types, render_contexts, &network_map);
|
|
||||||
|
|
||||||
material_network_map_ = network_map;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
material_network_map_ = pxr::VtValue();
|
material_network_map_ = pxr::VtValue();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialData::insert()
|
pxr::HdRenderDelegate *render_delegate = scene_delegate_->GetRenderIndex().GetRenderDelegate();
|
||||||
{
|
pxr::TfTokenVector shader_source_types = render_delegate->GetShaderSourceTypes();
|
||||||
ID_LOG(2, "");
|
pxr::TfTokenVector render_contexts = render_delegate->GetMaterialRenderContexts();
|
||||||
scene_delegate_->GetRenderIndex().InsertSprim(
|
|
||||||
pxr::HdPrimTypeTokens->material, scene_delegate_, prim_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialData::remove()
|
pxr::HdMaterialNetworkMap network_map;
|
||||||
{
|
hdmtlx_convert_to_materialnetworkmap(
|
||||||
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", prim_id.GetText());
|
mtlx_path_.GetResolvedPath(), shader_source_types, render_contexts, &network_map);
|
||||||
scene_delegate_->GetRenderIndex().RemoveSprim(pxr::HdPrimTypeTokens->material, prim_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialData::update()
|
material_network_map_ = network_map;
|
||||||
{
|
|
||||||
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
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
@ -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),
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user