forked from blender/blender
Optimized SubMesh to hold only used vertices #84
@ -7,6 +7,7 @@ USD Hydra Based Renderer
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
|
|
||||||
class CustomHydraRenderEngine(bpy.types.HydraRenderEngine):
|
class CustomHydraRenderEngine(bpy.types.HydraRenderEngine):
|
||||||
# Identifier and name in the user interface.
|
# Identifier and name in the user interface.
|
||||||
bl_idname = "CUSTOM_HYDRA_RENDERER"
|
bl_idname = "CUSTOM_HYDRA_RENDERER"
|
||||||
@ -53,8 +54,10 @@ class CustomHydraRenderEngine(bpy.types.HydraRenderEngine):
|
|||||||
def register():
|
def register():
|
||||||
bpy.utils.register_class(CustomHydraRenderEngine)
|
bpy.utils.register_class(CustomHydraRenderEngine)
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
bpy.utils.unregister_class(CustomHydraRenderEngine)
|
bpy.utils.unregister_class(CustomHydraRenderEngine)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
register()
|
register()
|
||||||
|
@ -4,13 +4,10 @@ __all__ = (
|
|||||||
"export_mtlx",
|
"export_mtlx",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def export_mtlx(material):
|
def export_mtlx(material):
|
||||||
""" Exports material to .mtlx file. It is called from Blender source code. """
|
""" Exports material to .mtlx file. It is called from Blender source code. """
|
||||||
try:
|
|
||||||
import materialx.utils as mx_utils
|
import materialx.utils as mx_utils
|
||||||
except ImportError:
|
|
||||||
print("ERROR: no MaterialX addon available")
|
|
||||||
return ""
|
|
||||||
|
|
||||||
doc = mx_utils.export(material, None)
|
doc = mx_utils.export(material, None)
|
||||||
if not doc:
|
if not doc:
|
||||||
|
@ -113,9 +113,34 @@ pxr::HdCullStyle MaterialData::cull_style() const
|
|||||||
|
|
||||||
void MaterialData::export_mtlx()
|
void MaterialData::export_mtlx()
|
||||||
{
|
{
|
||||||
/* Call of python function hydra.export_mtlx() */
|
|
||||||
|
|
||||||
PyGILState_STATE gstate;
|
PyGILState_STATE gstate;
|
||||||
|
|
||||||
|
/* Checking materialx addon */
|
||||||
|
static bool matx_addon_checked = false;
|
||||||
|
static bool has_matx_addon = false;
|
||||||
|
|
||||||
|
if (!matx_addon_checked) {
|
||||||
|
gstate = PyGILState_Ensure();
|
||||||
|
/* Adding second check into the lock, good practice to make this fully correct */
|
||||||
|
if (!matx_addon_checked) {
|
||||||
|
PyObject *mx_module = PyImport_ImportModule("materialx");
|
||||||
|
has_matx_addon = mx_module != nullptr;
|
||||||
|
Py_XDECREF(mx_module);
|
||||||
|
|
||||||
|
if (!has_matx_addon) {
|
||||||
|
PyErr_Print();
|
||||||
|
CLOG_WARN(LOG_HYDRA_SCENE, "No MaterialX addon, materials won't be exported.");
|
||||||
|
}
|
||||||
|
matx_addon_checked = true;
|
||||||
|
}
|
||||||
|
PyGILState_Release(gstate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_matx_addon) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call of python function bpy_hydra.export_mtlx() */
|
||||||
gstate = PyGILState_Ensure();
|
gstate = PyGILState_Ensure();
|
||||||
|
|
||||||
PyObject *module, *dict, *func, *result;
|
PyObject *module, *dict, *func, *result;
|
||||||
|
@ -62,6 +62,7 @@ set(INC_SYS
|
|||||||
${BOOST_INCLUDE_DIR}
|
${BOOST_INCLUDE_DIR}
|
||||||
${TBB_INCLUDE_DIR}
|
${TBB_INCLUDE_DIR}
|
||||||
${GFLAGS_INCLUDE_DIRS}
|
${GFLAGS_INCLUDE_DIRS}
|
||||||
|
${EIGEN3_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIB
|
set(LIB
|
||||||
|
@ -55,7 +55,7 @@ Engine::Engine(RenderEngine *bl_engine, const std::string &render_delegate_name)
|
|||||||
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"));
|
||||||
|
|
||||||
if (bl_engine->type->flag & RE_USE_GPU_CONTEXT) {
|
if (bl_engine->type->flag & RE_USE_GPU_CONTEXT && GPU_backend_get_type() == GPU_BACKEND_OPENGL) {
|
||||||
render_task_delegate_ = std::make_unique<GPURenderTaskDelegate>(
|
render_task_delegate_ = std::make_unique<GPURenderTaskDelegate>(
|
||||||
render_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("renderTask"));
|
render_index_.get(), pxr::SdfPath::AbsoluteRootPath().AppendElementString("renderTask"));
|
||||||
}
|
}
|
||||||
@ -133,4 +133,22 @@ float Engine::renderer_percent_done()
|
|||||||
return (float)it->second.UncheckedGet<double>();
|
return (float)it->second.UncheckedGet<double>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pxr::HdTaskSharedPtrVector Engine::tasks()
|
||||||
|
{
|
||||||
|
pxr::HdTaskSharedPtrVector res;
|
||||||
|
if (light_tasks_delegate_) {
|
||||||
|
if (scene_->r.alphamode != R_ALPHAPREMUL) {
|
||||||
|
#ifndef __APPLE__
|
||||||
|
/* TODO: Temporary disable skydome task for MacOS due to crash with error:
|
||||||
|
* Failed to created pipeline state, error depthAttachmentPixelFormat is not valid
|
||||||
|
* and shader writes to depth */
|
||||||
|
res.push_back(light_tasks_delegate_->skydome_task());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
res.push_back(light_tasks_delegate_->simple_task());
|
||||||
|
}
|
||||||
|
res.push_back(render_task_delegate_->task());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -64,7 +64,10 @@ class Engine {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
float renderer_percent_done();
|
float renderer_percent_done();
|
||||||
virtual void notify_status(float progress, const std::string &title, const std::string &info) = 0;
|
pxr::HdTaskSharedPtrVector tasks();
|
||||||
|
virtual void notify_status(float progress,
|
||||||
|
const std::string &title,
|
||||||
|
const std::string &info) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -66,18 +66,10 @@ void FinalEngine::render()
|
|||||||
render_task_delegate_->add_aov(pxr::HdAovTokens->depth);
|
render_task_delegate_->add_aov(pxr::HdAovTokens->depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::HdTaskSharedPtrVector tasks;
|
|
||||||
if (light_tasks_delegate_) {
|
|
||||||
if (scene_->r.alphamode != R_ALPHAPREMUL) {
|
|
||||||
tasks.push_back(light_tasks_delegate_->skydome_task());
|
|
||||||
}
|
|
||||||
tasks.push_back(light_tasks_delegate_->simple_task());
|
|
||||||
}
|
|
||||||
tasks.push_back(render_task_delegate_->task());
|
|
||||||
|
|
||||||
render_task_delegate_->bind();
|
render_task_delegate_->bind();
|
||||||
|
|
||||||
engine_->Execute(render_index_.get(), &tasks);
|
auto t = tasks();
|
||||||
|
engine_->Execute(render_index_.get(), &t);
|
||||||
|
|
||||||
char elapsed_time[32];
|
char elapsed_time[32];
|
||||||
double time_begin = PIL_check_seconds_timer();
|
double time_begin = PIL_check_seconds_timer();
|
||||||
|
@ -37,6 +37,7 @@ static PyObject *engine_create_func(PyObject * /*self*/, PyObject *args)
|
|||||||
|
|
||||||
RenderEngine *bl_engine = pyrna_to_pointer<RenderEngine>(pyengine, &RNA_RenderEngine);
|
RenderEngine *bl_engine = pyrna_to_pointer<RenderEngine>(pyengine, &RNA_RenderEngine);
|
||||||
|
|
||||||
|
CLOG_INFO(LOG_HYDRA_RENDER, 1, "Engine %s", engine_type);
|
||||||
Engine *engine = nullptr;
|
Engine *engine = nullptr;
|
||||||
try {
|
try {
|
||||||
if (STREQ(engine_type, "VIEWPORT")) {
|
if (STREQ(engine_type, "VIEWPORT")) {
|
||||||
@ -53,9 +54,7 @@ static PyObject *engine_create_func(PyObject * /*self*/, PyObject *args)
|
|||||||
CLOG_ERROR(LOG_HYDRA_RENDER, "%s", e.what());
|
CLOG_ERROR(LOG_HYDRA_RENDER, "%s", e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (engine) {
|
CLOG_INFO(LOG_HYDRA_RENDER, 1, "Engine %p", engine);
|
||||||
CLOG_INFO(LOG_HYDRA_RENDER, 1, "Engine %p %s", engine, engine_type);
|
|
||||||
}
|
|
||||||
return PyLong_FromVoidPtr(engine);
|
return PyLong_FromVoidPtr(engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,9 +66,9 @@ static PyObject *engine_free_func(PyObject * /*self*/, PyObject *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
|
Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
|
||||||
|
CLOG_INFO(LOG_HYDRA_RENDER, 1, "Engine %p", engine);
|
||||||
delete engine;
|
delete engine;
|
||||||
|
|
||||||
CLOG_INFO(LOG_HYDRA_RENDER, 1, "Engine %p", engine);
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,8 +13,9 @@
|
|||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "Eigen/Core"
|
||||||
|
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "render_task_delegate.h"
|
|
||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
@ -107,6 +108,16 @@ void RenderTaskDelegate::add_aov(pxr::TfToken const &aov_key)
|
|||||||
aov_key);
|
aov_key);
|
||||||
|
|
||||||
if (aov_desc.format == pxr::HdFormatInvalid) {
|
if (aov_desc.format == pxr::HdFormatInvalid) {
|
||||||
|
CLOG_ERROR(LOG_HYDRA_RENDER, "Invalid AOV: %s", aov_key.GetText());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!ELEM(
|
||||||
|
pxr::HdGetComponentFormat(aov_desc.format), pxr::HdFormatFloat32, pxr::HdFormatFloat16))
|
||||||
|
{
|
||||||
|
CLOG_WARN(LOG_HYDRA_RENDER,
|
||||||
|
"Unsupported data format %s for AOV %s",
|
||||||
|
pxr::TfEnum::GetName(aov_desc.format).c_str(),
|
||||||
|
aov_key.GetText());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +131,7 @@ void RenderTaskDelegate::add_aov(pxr::TfToken const &aov_key)
|
|||||||
binding.aovName = aov_key;
|
binding.aovName = aov_key;
|
||||||
binding.renderBufferId = buf_id;
|
binding.renderBufferId = buf_id;
|
||||||
binding.aovSettings = aov_desc.aovSettings;
|
binding.aovSettings = aov_desc.aovSettings;
|
||||||
binding.clearValue = pxr::VtValue(pxr::GfVec4f(0));
|
binding.clearValue = aov_desc.clearValue;
|
||||||
task_params_.aovBindings.push_back(binding);
|
task_params_.aovBindings.push_back(binding);
|
||||||
render_index.GetChangeTracker().MarkTaskDirty(task_id_, pxr::HdChangeTracker::DirtyParams);
|
render_index.GetChangeTracker().MarkTaskDirty(task_id_, pxr::HdChangeTracker::DirtyParams);
|
||||||
|
|
||||||
@ -134,12 +145,26 @@ void RenderTaskDelegate::read_aov(pxr::TfToken const &aov_key, void *data)
|
|||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pxr::HdFormat format = buffer->GetFormat();
|
||||||
|
size_t len = buffer->GetWidth() * buffer->GetHeight() * pxr::HdGetComponentCount(format);
|
||||||
|
if (pxr::HdGetComponentFormat(format) == pxr::HdFormatFloat32) {
|
||||||
void *buf_data = buffer->Map();
|
void *buf_data = buffer->Map();
|
||||||
memcpy(data,
|
memcpy(data, buf_data, len * sizeof(float));
|
||||||
buf_data,
|
|
||||||
buffer->GetWidth() * buffer->GetHeight() * pxr::HdDataSizeOfFormat(buffer->GetFormat()));
|
|
||||||
buffer->Unmap();
|
buffer->Unmap();
|
||||||
}
|
}
|
||||||
|
else if (pxr::HdGetComponentFormat(format) == pxr::HdFormatFloat16) {
|
||||||
|
Eigen::half *buf_data = (Eigen::half *)buffer->Map();
|
||||||
|
float *fdata = (float *)data;
|
||||||
|
for (size_t i = 0; i < len; ++i) {
|
||||||
|
fdata[i] = buf_data[i];
|
||||||
|
}
|
||||||
|
buffer->Unmap();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RenderTaskDelegate::read_aov(pxr::TfToken const &aov_key, GPUTexture *texture)
|
void RenderTaskDelegate::read_aov(pxr::TfToken const &aov_key, GPUTexture *texture)
|
||||||
{
|
{
|
||||||
@ -210,6 +235,7 @@ void GPURenderTaskDelegate::add_aov(pxr::TfToken const &aov_key)
|
|||||||
tex = &tex_depth_;
|
tex = &tex_depth_;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
CLOG_ERROR(LOG_HYDRA_RENDER, "Invalid AOV: %s", aov_key.GetText());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,14 +279,11 @@ void GPURenderTaskDelegate::read_aov(pxr::TfToken const &aov_key, void *data)
|
|||||||
void GPURenderTaskDelegate::read_aov(pxr::TfToken const &aov_key, GPUTexture *texture)
|
void GPURenderTaskDelegate::read_aov(pxr::TfToken const &aov_key, GPUTexture *texture)
|
||||||
{
|
{
|
||||||
GPUTexture *tex = nullptr;
|
GPUTexture *tex = nullptr;
|
||||||
int c;
|
|
||||||
if (aov_key == pxr::HdAovTokens->color) {
|
if (aov_key == pxr::HdAovTokens->color) {
|
||||||
tex = tex_color_;
|
tex = tex_color_;
|
||||||
c = 4;
|
|
||||||
}
|
}
|
||||||
else if (aov_key == pxr::HdAovTokens->depth) {
|
else if (aov_key == pxr::HdAovTokens->depth) {
|
||||||
tex = tex_depth_;
|
tex = tex_depth_;
|
||||||
c = 1;
|
|
||||||
}
|
}
|
||||||
if (!tex) {
|
if (!tex) {
|
||||||
return;
|
return;
|
||||||
|
@ -232,19 +232,11 @@ void ViewportEngine::render()
|
|||||||
render_task_delegate_->add_aov(pxr::HdAovTokens->color);
|
render_task_delegate_->add_aov(pxr::HdAovTokens->color);
|
||||||
render_task_delegate_->add_aov(pxr::HdAovTokens->depth);
|
render_task_delegate_->add_aov(pxr::HdAovTokens->depth);
|
||||||
|
|
||||||
pxr::HdTaskSharedPtrVector tasks;
|
|
||||||
if (light_tasks_delegate_) {
|
|
||||||
if (scene_->r.alphamode != R_ALPHAPREMUL) {
|
|
||||||
tasks.push_back(light_tasks_delegate_->skydome_task());
|
|
||||||
}
|
|
||||||
tasks.push_back(light_tasks_delegate_->simple_task());
|
|
||||||
}
|
|
||||||
tasks.push_back(render_task_delegate_->task());
|
|
||||||
|
|
||||||
GPUFrameBuffer *view_framebuffer = GPU_framebuffer_active_get();
|
GPUFrameBuffer *view_framebuffer = GPU_framebuffer_active_get();
|
||||||
render_task_delegate_->bind();
|
render_task_delegate_->bind();
|
||||||
|
|
||||||
engine_->Execute(render_index_.get(), &tasks);
|
auto t = tasks();
|
||||||
|
engine_->Execute(render_index_.get(), &t);
|
||||||
|
|
||||||
render_task_delegate_->unbind();
|
render_task_delegate_->unbind();
|
||||||
|
|
||||||
@ -293,7 +285,8 @@ void ViewportEngine::render(bContext *context)
|
|||||||
render();
|
render();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewportEngine::notify_status(float /*progress*/, const std::string &info,
|
void ViewportEngine::notify_status(float /*progress*/,
|
||||||
|
const std::string &info,
|
||||||
const std::string &status)
|
const std::string &status)
|
||||||
{
|
{
|
||||||
RE_engine_update_stats(bl_engine_, status.c_str(), info.c_str());
|
RE_engine_update_stats(bl_engine_, status.c_str(), info.c_str());
|
||||||
|
Loading…
Reference in New Issue
Block a user