Support several instancers on one object #24

Merged
Bogdan Nagirniak merged 16 commits from BLEN-383 into hydra-render 2023-04-19 02:46:24 +02:00
33 changed files with 1113 additions and 1020 deletions
Showing only changes of commit 784e12f012 - Show all commits

View File

@ -9,15 +9,92 @@
namespace blender::render::hydra { namespace blender::render::hydra {
CameraData::CameraData(bContext *context)
{
View3D *view3d = CTX_wm_view3d(context);
RegionView3D *region_data = (RegionView3D *)CTX_wm_region_data(context);
ARegion *region = CTX_wm_region(context);
/* This constant was found experimentally, didn't find such option in
* context.view3d or context.region_data. */
float VIEWPORT_SENSOR_SIZE = 72.0;
pxr::GfVec2i res(region->winx, region->winy);
float ratio = (float)res[0] / res[1];
transform_ = gf_matrix_from_transform(region_data->viewmat).GetInverse();
switch (region_data->persp) {
case RV3D_PERSP: {
mode_ = CAM_PERSP;
clip_range_ = pxr::GfRange1f(view3d->clip_start, view3d->clip_end);
lens_shift_ = pxr::GfVec2f(0.0, 0.0);
focal_length_ = view3d->lens;
if (ratio > 1.0) {
sensor_size_ = pxr::GfVec2f(VIEWPORT_SENSOR_SIZE, VIEWPORT_SENSOR_SIZE / ratio);
}
else {
sensor_size_ = pxr::GfVec2f(VIEWPORT_SENSOR_SIZE * ratio, VIEWPORT_SENSOR_SIZE);
}
break;
}
case RV3D_ORTHO: {
mode_ = CAM_ORTHO;
lens_shift_ = pxr::GfVec2f(0.0f, 0.0f);
float o_size = region_data->dist * VIEWPORT_SENSOR_SIZE / view3d->lens;
float o_depth = view3d->clip_end;
clip_range_ = pxr::GfRange1f(-o_depth * 0.5, o_depth * 0.5);
if (ratio > 1.0f) {
ortho_size_ = pxr::GfVec2f(o_size, o_size / ratio);
}
else {
ortho_size_ = pxr::GfVec2f(o_size * ratio, o_size);
}
break;
}
case RV3D_CAMOB: {
pxr::GfMatrix4d mat = transform_;
*this = CameraData(view3d->camera, res, pxr::GfVec4f(0, 0, 1, 1));
transform_ = mat;
/* This formula was taken from previous plugin with corresponded comment.
* See blender/intern/cycles/blender/blender_camera.cpp:blender_camera_from_view (look
* for 1.41421f). */
float zoom = 4.0 / pow((pow(2.0, 0.5) + region_data->camzoom / 50.0), 2);
/* Updating l_shift due to viewport zoom and view_camera_offset
* view_camera_offset should be multiplied by 2. */
lens_shift_ = pxr::GfVec2f((lens_shift_[0] + region_data->camdx * 2) / zoom,
(lens_shift_[1] + region_data->camdy * 2) / zoom);
if (mode_ == CAM_ORTHO) {
ortho_size_ *= zoom;
}
else {
sensor_size_ *= zoom;
}
break;
}
default:
break;
}
}
CameraData::CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile) CameraData::CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile)
{ {
Camera *camera = (Camera *)camera_obj->data; Camera *camera = (Camera *)camera_obj->data;
float t_pos[2] = {tile[0], tile[1]}; float t_pos[2] = {tile[0], tile[1]};
float t_size[2] = {tile[2], tile[3]}; float t_size[2] = {tile[2], tile[3]};
transform = gf_matrix_from_transform(camera_obj->object_to_world); transform_ = gf_matrix_from_transform(camera_obj->object_to_world);
clip_range = pxr::GfRange1f(camera->clip_start, camera->clip_end); clip_range_ = pxr::GfRange1f(camera->clip_start, camera->clip_end);
mode = camera->type; mode_ = camera->type;
if (camera->dof.flag & CAM_DOF_ENABLED) { if (camera->dof.flag & CAM_DOF_ENABLED) {
float focus_distance; float focus_distance;
@ -28,11 +105,11 @@ CameraData::CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile)
pxr::GfVec3f obj_pos(camera->dof.focus_object->object_to_world[0][3], pxr::GfVec3f obj_pos(camera->dof.focus_object->object_to_world[0][3],
camera->dof.focus_object->object_to_world[1][3], camera->dof.focus_object->object_to_world[1][3],
camera->dof.focus_object->object_to_world[2][3]); camera->dof.focus_object->object_to_world[2][3]);
pxr::GfVec3f cam_pos(transform[0][3], transform[1][3], transform[2][3]); pxr::GfVec3f cam_pos(transform_[0][3], transform_[1][3], transform_[2][3]);
focus_distance = (obj_pos - cam_pos).GetLength(); focus_distance = (obj_pos - cam_pos).GetLength();
} }
dof_data = std::tuple( dof_data_ = std::tuple(
std::max(focus_distance, 0.001f), camera->dof.aperture_fstop, camera->dof.aperture_blades); std::max(focus_distance, 0.001f), camera->dof.aperture_fstop, camera->dof.aperture_blades);
} }
@ -40,184 +117,112 @@ CameraData::CameraData(Object *camera_obj, pxr::GfVec2i res, pxr::GfVec4f tile)
switch (camera->sensor_fit) { switch (camera->sensor_fit) {
case CAMERA_SENSOR_FIT_VERT: case CAMERA_SENSOR_FIT_VERT:
lens_shift = pxr::GfVec2f(camera->shiftx / ratio, camera->shifty); lens_shift_ = pxr::GfVec2f(camera->shiftx / ratio, camera->shifty);
break; break;
case CAMERA_SENSOR_FIT_HOR: case CAMERA_SENSOR_FIT_HOR:
lens_shift = pxr::GfVec2f(camera->shiftx, camera->shifty * ratio); lens_shift_ = pxr::GfVec2f(camera->shiftx, camera->shifty * ratio);
break; break;
case CAMERA_SENSOR_FIT_AUTO: case CAMERA_SENSOR_FIT_AUTO:
if (ratio > 1.0f) { if (ratio > 1.0f) {
lens_shift = pxr::GfVec2f(camera->shiftx, camera->shifty * ratio); lens_shift_ = pxr::GfVec2f(camera->shiftx, camera->shifty * ratio);
} }
else { else {
lens_shift = pxr::GfVec2f(camera->shiftx / ratio, camera->shifty); lens_shift_ = pxr::GfVec2f(camera->shiftx / ratio, camera->shifty);
} }
break; break;
default: default:
lens_shift = pxr::GfVec2f(camera->shiftx, camera->shifty); lens_shift_ = pxr::GfVec2f(camera->shiftx, camera->shifty);
break; break;
} }
lens_shift = pxr::GfVec2f( lens_shift_ = pxr::GfVec2f(
lens_shift[0] / t_size[0] + (t_pos[0] + t_size[0] * 0.5 - 0.5) / t_size[0], lens_shift_[0] / t_size[0] + (t_pos[0] + t_size[0] * 0.5 - 0.5) / t_size[0],
lens_shift[1] / t_size[1] + (t_pos[1] + t_size[1] * 0.5 - 0.5) / t_size[1]); lens_shift_[1] / t_size[1] + (t_pos[1] + t_size[1] * 0.5 - 0.5) / t_size[1]);
switch (camera->type) { switch (camera->type) {
case CAM_PERSP: case CAM_PERSP:
focal_length = camera->lens; focal_length_ = camera->lens;
switch (camera->sensor_fit) { switch (camera->sensor_fit) {
case CAMERA_SENSOR_FIT_VERT: case CAMERA_SENSOR_FIT_VERT:
sensor_size = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y); sensor_size_ = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y);
break; break;
case CAMERA_SENSOR_FIT_HOR: case CAMERA_SENSOR_FIT_HOR:
sensor_size = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio); sensor_size_ = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio);
break; break;
case CAMERA_SENSOR_FIT_AUTO: case CAMERA_SENSOR_FIT_AUTO:
if (ratio > 1.0f) { if (ratio > 1.0f) {
sensor_size = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio); sensor_size_ = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio);
} }
else { else {
sensor_size = pxr::GfVec2f(camera->sensor_x * ratio, camera->sensor_x); sensor_size_ = pxr::GfVec2f(camera->sensor_x * ratio, camera->sensor_x);
} }
break; break;
default: default:
sensor_size = pxr::GfVec2f(camera->sensor_x, camera->sensor_y); sensor_size_ = pxr::GfVec2f(camera->sensor_x, camera->sensor_y);
break; break;
} }
sensor_size = pxr::GfVec2f(sensor_size[0] * t_size[0], sensor_size[1] * t_size[1]); sensor_size_ = pxr::GfVec2f(sensor_size_[0] * t_size[0], sensor_size_[1] * t_size[1]);
break; break;
case CAM_ORTHO: case CAM_ORTHO:
focal_length = 0.0f; focal_length_ = 0.0f;
switch (camera->sensor_fit) { switch (camera->sensor_fit) {
case CAMERA_SENSOR_FIT_VERT: case CAMERA_SENSOR_FIT_VERT:
ortho_size = pxr::GfVec2f(camera->ortho_scale * ratio, camera->ortho_scale); ortho_size_ = pxr::GfVec2f(camera->ortho_scale * ratio, camera->ortho_scale);
break; break;
case CAMERA_SENSOR_FIT_HOR: case CAMERA_SENSOR_FIT_HOR:
ortho_size = pxr::GfVec2f(camera->ortho_scale, camera->ortho_scale / ratio); ortho_size_ = pxr::GfVec2f(camera->ortho_scale, camera->ortho_scale / ratio);
break; break;
case CAMERA_SENSOR_FIT_AUTO: case CAMERA_SENSOR_FIT_AUTO:
if (ratio > 1.0f) { if (ratio > 1.0f) {
ortho_size = pxr::GfVec2f(camera->ortho_scale, camera->ortho_scale / ratio); ortho_size_ = pxr::GfVec2f(camera->ortho_scale, camera->ortho_scale / ratio);
} }
else { else {
ortho_size = pxr::GfVec2f(camera->ortho_scale * ratio, camera->ortho_scale); ortho_size_ = pxr::GfVec2f(camera->ortho_scale * ratio, camera->ortho_scale);
} }
break; break;
default: default:
ortho_size = pxr::GfVec2f(camera->ortho_scale, camera->ortho_scale); ortho_size_ = pxr::GfVec2f(camera->ortho_scale, camera->ortho_scale);
break; break;
} }
ortho_size = pxr::GfVec2f(ortho_size[0] * t_size[0], ortho_size[1] * t_size[1]); ortho_size_ = pxr::GfVec2f(ortho_size_[0] * t_size[0], ortho_size_[1] * t_size[1]);
break; break;
case CAM_PANO: case CAM_PANO:
/* TODO: Recheck parameters for PANO camera */ /* TODO: Recheck parameters for PANO camera */
focal_length = camera->lens; focal_length_ = camera->lens;
switch (camera->sensor_fit) { switch (camera->sensor_fit) {
case CAMERA_SENSOR_FIT_VERT: case CAMERA_SENSOR_FIT_VERT:
sensor_size = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y); sensor_size_ = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y);
break; break;
case CAMERA_SENSOR_FIT_HOR: case CAMERA_SENSOR_FIT_HOR:
sensor_size = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio); sensor_size_ = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio);
break; break;
case CAMERA_SENSOR_FIT_AUTO: case CAMERA_SENSOR_FIT_AUTO:
if (ratio > 1.0f) { if (ratio > 1.0f) {
sensor_size = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio); sensor_size_ = pxr::GfVec2f(camera->sensor_x, camera->sensor_x / ratio);
} }
else { else {
sensor_size = pxr::GfVec2f(camera->sensor_x * ratio, camera->sensor_x); sensor_size_ = pxr::GfVec2f(camera->sensor_x * ratio, camera->sensor_x);
} }
break; break;
default: default:
sensor_size = pxr::GfVec2f(camera->sensor_x, camera->sensor_y); sensor_size_ = pxr::GfVec2f(camera->sensor_x, camera->sensor_y);
break; break;
} }
sensor_size = pxr::GfVec2f(sensor_size[0] * t_size[0], sensor_size[1] * t_size[1]); sensor_size_ = pxr::GfVec2f(sensor_size_[0] * t_size[0], sensor_size_[1] * t_size[1]);
default: default:
focal_length = camera->lens; focal_length_ = camera->lens;
sensor_size = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y); sensor_size_ = pxr::GfVec2f(camera->sensor_y * ratio, camera->sensor_y);
} }
} }
CameraData::CameraData(bContext *context) pxr::GfCamera CameraData::gf_camera()
{ {
View3D *view3d = CTX_wm_view3d(context); return gf_camera(pxr::GfVec4f(0, 0, 1, 1));
RegionView3D *region_data = (RegionView3D *)CTX_wm_region_data(context);
ARegion *region = CTX_wm_region(context);
// this constant was found experimentally, didn't find such option in
// context.view3d or context.region_data
float VIEWPORT_SENSOR_SIZE = 72.0;
pxr::GfVec2i res(region->winx, region->winy);
float ratio = (float)res[0] / res[1];
transform = gf_matrix_from_transform(region_data->viewmat).GetInverse();
switch (region_data->persp) {
case RV3D_PERSP: {
mode = CAM_PERSP;
clip_range = pxr::GfRange1f(view3d->clip_start, view3d->clip_end);
lens_shift = pxr::GfVec2f(0.0, 0.0);
focal_length = view3d->lens;
if (ratio > 1.0) {
sensor_size = pxr::GfVec2f(VIEWPORT_SENSOR_SIZE, VIEWPORT_SENSOR_SIZE / ratio);
}
else {
sensor_size = pxr::GfVec2f(VIEWPORT_SENSOR_SIZE * ratio, VIEWPORT_SENSOR_SIZE);
}
break;
}
case RV3D_ORTHO: {
mode = CAM_ORTHO;
lens_shift = pxr::GfVec2f(0.0f, 0.0f);
float o_size = region_data->dist * VIEWPORT_SENSOR_SIZE / view3d->lens;
float o_depth = view3d->clip_end;
clip_range = pxr::GfRange1f(-o_depth * 0.5, o_depth * 0.5);
if (ratio > 1.0f) {
ortho_size = pxr::GfVec2f(o_size, o_size / ratio);
}
else {
ortho_size = pxr::GfVec2f(o_size * ratio, o_size);
}
break;
}
case RV3D_CAMOB: {
pxr::GfMatrix4d mat = transform;
*this = CameraData(view3d->camera, res, pxr::GfVec4f(0, 0, 1, 1));
transform = mat;
// This formula was taken from previous plugin with corresponded comment
// See blender/intern/cycles/blender/blender_camera.cpp:blender_camera_from_view (look
// for 1.41421f)
float zoom = 4.0 / pow((pow(2.0, 0.5) + region_data->camzoom / 50.0), 2);
// Updating l_shift due to viewport zoom and view_camera_offset
// view_camera_offset should be multiplied by 2
lens_shift = pxr::GfVec2f((lens_shift[0] + region_data->camdx * 2) / zoom,
(lens_shift[1] + region_data->camdy * 2) / zoom);
if (mode == CAM_ORTHO) {
ortho_size *= zoom;
}
else {
sensor_size *= zoom;
}
break;
}
default:
break;
}
} }
pxr::GfCamera CameraData::gf_camera(pxr::GfVec4f tile) pxr::GfCamera CameraData::gf_camera(pxr::GfVec4f tile)
@ -226,19 +231,19 @@ pxr::GfCamera CameraData::gf_camera(pxr::GfVec4f tile)
pxr::GfCamera gf_camera = pxr::GfCamera(); pxr::GfCamera gf_camera = pxr::GfCamera();
gf_camera.SetClippingRange(clip_range); gf_camera.SetClippingRange(clip_range_);
float l_shift[2] = {(lens_shift[0] + t_pos[0] + t_size[0] * 0.5f - 0.5f) / t_size[0], float l_shift[2] = {(lens_shift_[0] + t_pos[0] + t_size[0] * 0.5f - 0.5f) / t_size[0],
(lens_shift[1] + t_pos[1] + t_size[1] * 0.5f - 0.5f) / t_size[1]}; (lens_shift_[1] + t_pos[1] + t_size[1] * 0.5f - 0.5f) / t_size[1]};
switch (mode) { switch (mode_) {
case CAM_PERSP: case CAM_PERSP:
case CAM_PANO: { case CAM_PANO: {
/* TODO: store panoramic camera settings */ /* TODO: store panoramic camera settings */
gf_camera.SetProjection(pxr::GfCamera::Projection::Perspective); gf_camera.SetProjection(pxr::GfCamera::Projection::Perspective);
gf_camera.SetFocalLength(focal_length); gf_camera.SetFocalLength(focal_length_);
float s_size[2] = {sensor_size[0] * t_size[0], sensor_size[1] * t_size[1]}; float s_size[2] = {sensor_size_[0] * t_size[0], sensor_size_[1] * t_size[1]};
gf_camera.SetHorizontalAperture(s_size[0]); gf_camera.SetHorizontalAperture(s_size[0]);
gf_camera.SetVerticalAperture(s_size[1]); gf_camera.SetVerticalAperture(s_size[1]);
@ -250,9 +255,9 @@ pxr::GfCamera CameraData::gf_camera(pxr::GfVec4f tile)
case CAM_ORTHO: { case CAM_ORTHO: {
gf_camera.SetProjection(pxr::GfCamera::Projection::Orthographic); gf_camera.SetProjection(pxr::GfCamera::Projection::Orthographic);
// Use tenths of a world unit accorging to USD docs /* Use tenths of a world unit accorging to USD docs
// https://graphics.pixar.com/usd/docs/api/class_gf_camera.html * https://graphics.pixar.com/usd/docs/api/class_gf_camera.html */
float o_size[2] = {ortho_size[0] * t_size[0] * 10, ortho_size[1] * t_size[1] * 10}; float o_size[2] = {ortho_size_[0] * t_size[0] * 10, ortho_size_[1] * t_size[1] * 10};
gf_camera.SetHorizontalAperture(o_size[0]); gf_camera.SetHorizontalAperture(o_size[0]);
gf_camera.SetVerticalAperture(o_size[1]); gf_camera.SetVerticalAperture(o_size[1]);
@ -265,13 +270,8 @@ pxr::GfCamera CameraData::gf_camera(pxr::GfVec4f tile)
break; break;
} }
gf_camera.SetTransform(transform); gf_camera.SetTransform(transform_);
return gf_camera; return gf_camera;
} }
pxr::GfCamera CameraData::gf_camera()
{
return gf_camera(pxr::GfVec4f(0, 0, 1, 1));
}
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -23,14 +23,14 @@ class CameraData {
pxr::GfCamera gf_camera(pxr::GfVec4f tile); pxr::GfCamera gf_camera(pxr::GfVec4f tile);
private: private:
int mode; int mode_;
pxr::GfRange1f clip_range; pxr::GfRange1f clip_range_;
float focal_length; float focal_length_;
pxr::GfVec2f sensor_size; pxr::GfVec2f sensor_size_;
pxr::GfMatrix4d transform; pxr::GfMatrix4d transform_;
pxr::GfVec2f lens_shift; pxr::GfVec2f lens_shift_;
pxr::GfVec2f ortho_size; pxr::GfVec2f ortho_size_;
std::tuple<float, float, int> dof_data; std::tuple<float, float, int> dof_data_;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -14,51 +14,39 @@ namespace blender::render::hydra {
CLG_LOGREF_DECLARE_GLOBAL(LOG_EN, "rhd.en"); CLG_LOGREF_DECLARE_GLOBAL(LOG_EN, "rhd.en");
Engine::Engine(RenderEngine *bl_engine, const std::string &delegate_id) : bl_engine(bl_engine) Engine::Engine(RenderEngine *bl_engine, const std::string &delegate_id) : 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(delegate_id)); render_delegate_ = registry.CreateRenderDelegate(pxr::TfToken(delegate_id));
pxr::HdDriverVector hd_drivers; pxr::HdDriverVector hd_drivers;
if (bl_engine->type->flag & RE_USE_GPU_CONTEXT) { if (bl_engine->type->flag & RE_USE_GPU_CONTEXT) {
hgi = pxr::Hgi::CreatePlatformDefaultHgi(); hgi_ = pxr::Hgi::CreatePlatformDefaultHgi();
hgi_driver.name = pxr::HgiTokens->renderDriver; hgi_driver_.name = pxr::HgiTokens->renderDriver;
hgi_driver.driver = pxr::VtValue(hgi.get()); hgi_driver_.driver = pxr::VtValue(hgi_.get());
hd_drivers.push_back(&hgi_driver); hd_drivers.push_back(&hgi_driver_);
} }
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"));
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->GetRendererDisplayName() == "GL") { if (render_delegate_->GetRendererDisplayName() == "GL") {
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"));
} }
engine = std::make_unique<pxr::HdEngine>(); engine_ = std::make_unique<pxr::HdEngine>();
}
Engine::~Engine()
{
scene_delegate = nullptr;
render_task_delegate = nullptr;
free_camera_delegate = nullptr;
simple_light_task_delegate = nullptr;
render_index = nullptr;
render_delegate = nullptr;
engine = nullptr;
hgi = nullptr;
} }
float Engine::renderer_percent_done() float Engine::renderer_percent_done()
{ {
pxr::VtDictionary render_stats = render_delegate->GetRenderStats(); pxr::VtDictionary render_stats = render_delegate_->GetRenderStats();
auto it = render_stats.find("percentDone"); auto it = render_stats.find("percentDone");
if (it == render_stats.end()) { if (it == render_stats.end()) {
return 0.0; return 0.0;

View File

@ -5,8 +5,6 @@
#include <chrono> #include <chrono>
#include <Python.h>
#include <pxr/imaging/hd/driver.h> #include <pxr/imaging/hd/driver.h>
#include <pxr/imaging/hd/engine.h> #include <pxr/imaging/hd/engine.h>
#include <pxr/imaging/hd/pluginRenderDelegateUniqueHandle.h> #include <pxr/imaging/hd/pluginRenderDelegateUniqueHandle.h>
@ -28,7 +26,7 @@ extern struct CLG_LogRef *LOG_EN; /* EN - Engine */
class Engine { class Engine {
public: public:
Engine(RenderEngine *bl_engine, const std::string &render_delegate_id); Engine(RenderEngine *bl_engine, const std::string &render_delegate_id);
virtual ~Engine(); virtual ~Engine() = default;
virtual void sync(Depsgraph *depsgraph, virtual void sync(Depsgraph *depsgraph,
bContext *context, bContext *context,
@ -38,19 +36,19 @@ class Engine {
protected: protected:
float renderer_percent_done(); float renderer_percent_done();
protected: RenderEngine *bl_engine_;
RenderEngine *bl_engine;
pxr::HdPluginRenderDelegateUniqueHandle render_delegate; /* The order is important due to deletion order */
std::unique_ptr<pxr::HdRenderIndex> render_index; pxr::HdPluginRenderDelegateUniqueHandle render_delegate_;
std::unique_ptr<BlenderSceneDelegate> scene_delegate; std::unique_ptr<pxr::HdRenderIndex> render_index_;
std::unique_ptr<RenderTaskDelegate> render_task_delegate; std::unique_ptr<BlenderSceneDelegate> scene_delegate_;
std::unique_ptr<pxr::HdxFreeCameraSceneDelegate> free_camera_delegate; std::unique_ptr<RenderTaskDelegate> render_task_delegate_;
std::unique_ptr<SimpleLightTaskDelegate> simple_light_task_delegate; std::unique_ptr<pxr::HdxFreeCameraSceneDelegate> free_camera_delegate_;
std::unique_ptr<pxr::HdEngine> engine; std::unique_ptr<SimpleLightTaskDelegate> simple_light_task_delegate_;
std::unique_ptr<pxr::HdEngine> engine_;
pxr::HgiUniquePtr hgi; pxr::HgiUniquePtr hgi_;
pxr::HdDriver hgi_driver; pxr::HdDriver hgi_driver_;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -16,27 +16,27 @@ void FinalEngine::sync(Depsgraph *depsgraph,
bContext *context, bContext *context,
pxr::HdRenderSettingsMap &render_settings) pxr::HdRenderSettingsMap &render_settings)
{ {
scene_delegate = std::make_unique<BlenderSceneDelegate>( scene_delegate_ = std::make_unique<BlenderSceneDelegate>(
render_index.get(), render_index_.get(),
pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"), pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"),
BlenderSceneDelegate::EngineType::FINAL); BlenderSceneDelegate::EngineType::FINAL);
scene_delegate->populate(depsgraph, context); scene_delegate_->populate(depsgraph, context);
for (auto const &setting : render_settings) { for (auto const &setting : render_settings) {
render_delegate->SetRenderSetting(setting.first, setting.second); render_delegate_->SetRenderSetting(setting.first, setting.second);
} }
} }
void FinalEngine::render(Depsgraph *depsgraph) void FinalEngine::render(Depsgraph *depsgraph)
{ {
Scene *scene = DEG_get_input_scene(depsgraph); const Scene *scene = DEG_get_evaluated_scene(depsgraph);
ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); const ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
std::string scene_name(MAX_ID_FULL_NAME, 0); std::string scene_name(MAX_ID_FULL_NAME, 0);
BKE_id_full_name_get(scene_name.data(), (ID *)scene, 0); BKE_id_full_name_get(scene_name.data(), (ID *)scene, 0);
std::string layer_name = view_layer->name; std::string layer_name = view_layer->name;
RenderData &r = scene->r; const RenderData &r = scene->r;
pxr::GfVec4f border(0, 0, 1, 1); pxr::GfVec4f border(0, 0, 1, 1);
if (r.mode & R_BORDER) { if (r.mode & R_BORDER) {
border = pxr::GfVec4f(r.border.xmin, border = pxr::GfVec4f(r.border.xmin,
@ -49,19 +49,19 @@ void FinalEngine::render(Depsgraph *depsgraph)
pxr::GfCamera camera = pxr::GfCamera camera =
CameraData(scene->camera, image_res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(border); CameraData(scene->camera, image_res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(border);
free_camera_delegate->SetCamera(camera); free_camera_delegate_->SetCamera(camera);
render_task_delegate->set_camera_and_viewport(free_camera_delegate->GetCameraId(), render_task_delegate_->set_camera_and_viewport(free_camera_delegate_->GetCameraId(),
pxr::GfVec4d(0, 0, res[0], res[1])); pxr::GfVec4d(0, 0, res[0], res[1]));
render_task_delegate->set_renderer_aov(pxr::HdAovTokens->color); render_task_delegate_->set_renderer_aov(pxr::HdAovTokens->color);
if (simple_light_task_delegate) { if (simple_light_task_delegate_) {
simple_light_task_delegate->set_camera_path(free_camera_delegate->GetCameraId()); simple_light_task_delegate_->set_camera_path(free_camera_delegate_->GetCameraId());
} }
pxr::HdTaskSharedPtrVector tasks; pxr::HdTaskSharedPtrVector tasks;
if (simple_light_task_delegate) { if (simple_light_task_delegate_) {
tasks.push_back(simple_light_task_delegate->get_task()); tasks.push_back(simple_light_task_delegate_->get_task());
} }
tasks.push_back(render_task_delegate->get_task()); tasks.push_back(render_task_delegate_->get_task());
std::chrono::time_point<std::chrono::steady_clock> time_begin = std::chrono::steady_clock::now(), std::chrono::time_point<std::chrono::steady_clock> time_begin = std::chrono::steady_clock::now(),
time_current; time_current;
@ -70,17 +70,17 @@ void FinalEngine::render(Depsgraph *depsgraph)
float percent_done = 0.0; float percent_done = 0.0;
std::map<std::string, std::vector<float>> render_images{ std::map<std::string, std::vector<float>> render_images{
{"Combined", std::vector<float>(res[0] * res[1] * 4)}}; // 4 - number of channels {"Combined", std::vector<float>(res[0] * res[1] * 4)}}; /* 4 - number of channels. */
std::vector<float> &pixels = render_images["Combined"]; std::vector<float> &pixels = render_images["Combined"];
{ {
// Release the GIL before calling into hydra, in case any hydra plugins call into python. /* Release the GIL before calling into hydra, in case any hydra plugins call into python. */
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE(); pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
engine->Execute(render_index.get(), &tasks); engine_->Execute(render_index_.get(), &tasks);
} }
while (true) { while (true) {
if (RE_engine_test_break(bl_engine)) { if (RE_engine_test_break(bl_engine_)) {
break; break;
} }
@ -94,15 +94,15 @@ void FinalEngine::render(Depsgraph *depsgraph)
"Render Time: " + format_duration(elapsed_time) + "Render Time: " + format_duration(elapsed_time) +
" | Done: " + std::to_string(int(percent_done)) + "%"); " | Done: " + std::to_string(int(percent_done)) + "%");
if (render_task_delegate->is_converged()) { if (render_task_delegate_->is_converged()) {
break; break;
} }
render_task_delegate->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data()); render_task_delegate_->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data());
update_render_result(render_images, layer_name, res[0], res[1]); update_render_result(render_images, layer_name, res[0], res[1]);
} }
render_task_delegate->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data()); render_task_delegate_->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data());
update_render_result(render_images, layer_name, res[0], res[1]); update_render_result(render_images, layer_name, res[0], res[1]);
} }
@ -124,7 +124,7 @@ void FinalEngine::update_render_result(std::map<std::string, std::vector<float>>
int height) int height)
{ {
RenderResult *result = RE_engine_begin_result( RenderResult *result = RE_engine_begin_result(
bl_engine, 0, 0, width, height, layer_name.c_str(), nullptr); bl_engine_, 0, 0, width, height, layer_name.c_str(), nullptr);
/* TODO: only for the first render layer */ /* TODO: only for the first render layer */
RenderLayer *layer = (RenderLayer *)result->layers.first; RenderLayer *layer = (RenderLayer *)result->layers.first;
@ -138,25 +138,25 @@ void FinalEngine::update_render_result(std::map<std::string, std::vector<float>>
sizeof(float) * pass->rectx * pass->recty * pass->channels); sizeof(float) * pass->rectx * pass->recty * pass->channels);
} }
RE_engine_end_result(bl_engine, result, false, false, false); RE_engine_end_result(bl_engine_, result, false, false, false);
} }
void FinalEngine::notify_status(float progress, const std::string &title, const std::string &info) void FinalEngine::notify_status(float progress, const std::string &title, const std::string &info)
{ {
RE_engine_update_progress(bl_engine, progress); RE_engine_update_progress(bl_engine_, progress);
RE_engine_update_stats(bl_engine, title.c_str(), info.c_str()); RE_engine_update_stats(bl_engine_, title.c_str(), info.c_str());
} }
void FinalEngineGL::render(Depsgraph *depsgraph) void FinalEngineGL::render(Depsgraph *depsgraph)
{ {
Scene *scene = DEG_get_input_scene(depsgraph); const Scene *scene = DEG_get_evaluated_scene(depsgraph);
ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); const ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
std::string scene_name(MAX_ID_FULL_NAME, 0); std::string scene_name(MAX_ID_FULL_NAME, 0);
BKE_id_full_name_get(scene_name.data(), (ID *)scene, 0); BKE_id_full_name_get(scene_name.data(), (ID *)scene, 0);
std::string layer_name = view_layer->name; std::string layer_name = view_layer->name;
RenderData &r = scene->r; const RenderData &r = scene->r;
pxr::GfVec4f border(0, 0, 1, 1); pxr::GfVec4f border(0, 0, 1, 1);
if (r.mode & R_BORDER) { if (r.mode & R_BORDER) {
border = pxr::GfVec4f(r.border.xmin, border = pxr::GfVec4f(r.border.xmin,
@ -169,21 +169,21 @@ void FinalEngineGL::render(Depsgraph *depsgraph)
pxr::GfCamera camera = pxr::GfCamera camera =
CameraData(scene->camera, image_res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(border); CameraData(scene->camera, image_res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(border);
free_camera_delegate->SetCamera(camera); free_camera_delegate_->SetCamera(camera);
render_task_delegate->set_camera_and_viewport(free_camera_delegate->GetCameraId(), render_task_delegate_->set_camera_and_viewport(free_camera_delegate_->GetCameraId(),
pxr::GfVec4d(0, 0, res[0], res[1])); pxr::GfVec4d(0, 0, res[0], res[1]));
if (simple_light_task_delegate) { if (simple_light_task_delegate_) {
simple_light_task_delegate->set_camera_path(free_camera_delegate->GetCameraId()); simple_light_task_delegate_->set_camera_path(free_camera_delegate_->GetCameraId());
} }
pxr::HdTaskSharedPtrVector tasks; pxr::HdTaskSharedPtrVector tasks;
if (simple_light_task_delegate) { if (simple_light_task_delegate_) {
/* TODO: Uncomment this and fix GL error: /* TODO: Uncomment this and fix GL error:
invalid operation, reported from void __cdecl * invalid operation, reported from void __cdecl
pxrInternal_v0_22__pxrReserved__::HgiGLResourceBindings::BindResources(void) */ * pxrInternal_v0_22__pxrReserved__::HgiGLResourceBindings::BindResources(void) */
// tasks.push_back(simple_light_task_delegate->get_task()); // tasks.push_back(simple_light_task_delegate_->get_task());
} }
tasks.push_back(render_task_delegate->get_task()); tasks.push_back(render_task_delegate_->get_task());
std::chrono::time_point<std::chrono::steady_clock> time_begin = std::chrono::steady_clock::now(), std::chrono::time_point<std::chrono::steady_clock> time_begin = std::chrono::steady_clock::now(),
time_current; time_current;
@ -192,11 +192,11 @@ void FinalEngineGL::render(Depsgraph *depsgraph)
float percent_done = 0.0; float percent_done = 0.0;
std::map<std::string, std::vector<float>> render_images{ std::map<std::string, std::vector<float>> render_images{
{"Combined", std::vector<float>(res[0] * res[1] * 4)}}; // 4 - number of channels {"Combined", std::vector<float>(res[0] * res[1] * 4)}}; /* 4 - number of channels. */
std::vector<float> &pixels = render_images["Combined"]; std::vector<float> &pixels = render_images["Combined"];
GPUFrameBuffer *framebuffer = GPU_framebuffer_create("fbHydraRenderFinal"); GPUFrameBuffer *framebuffer = GPU_framebuffer_create("fb_hdyra_render_final");
GPUTexture *texture = GPU_texture_create_2d("texHydraRenderFinal", GPUTexture *texture = GPU_texture_create_2d("tex_hydra_render_final",
res[0], res[0],
res[1], res[1],
1, 1,
@ -212,13 +212,13 @@ void FinalEngineGL::render(Depsgraph *depsgraph)
GPU_framebuffer_clear_color_depth(framebuffer, clear_color, 1.0); GPU_framebuffer_clear_color_depth(framebuffer, clear_color, 1.0);
{ {
// Release the GIL before calling into hydra, in case any hydra plugins call into python. /* Release the GIL before calling into hydra, in case any hydra plugins call into python. */
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE(); pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
engine->Execute(render_index.get(), &tasks); engine_->Execute(render_index_.get(), &tasks);
} }
while (true) { while (true) {
if (RE_engine_test_break(bl_engine)) { if (RE_engine_test_break(bl_engine_)) {
break; break;
} }
@ -232,7 +232,7 @@ void FinalEngineGL::render(Depsgraph *depsgraph)
"Render Time: " + format_duration(elapsed_time) + "Render Time: " + format_duration(elapsed_time) +
" | Done: " + std::to_string(int(percent_done)) + "%"); " | Done: " + std::to_string(int(percent_done)) + "%");
if (render_task_delegate->is_converged()) { if (render_task_delegate_->is_converged()) {
break; break;
} }

View File

@ -12,6 +12,7 @@ namespace blender::render::hydra {
class FinalEngine : public Engine { class FinalEngine : public Engine {
public: public:
using Engine::Engine; using Engine::Engine;
virtual void sync(Depsgraph *depsgraph, virtual void sync(Depsgraph *depsgraph,
bContext *context, bContext *context,
pxr::HdRenderSettingsMap &render_settings) override; pxr::HdRenderSettingsMap &render_settings) override;
@ -25,13 +26,13 @@ class FinalEngine : public Engine {
int height); int height);
void notify_status(float progress, const std::string &title, const std::string &info); void notify_status(float progress, const std::string &title, const std::string &info);
protected: pxr::HdRenderSettingsMap render_settings_;
pxr::HdRenderSettingsMap render_settings;
}; };
class FinalEngineGL : public FinalEngine { class FinalEngineGL : public FinalEngine {
public: public:
using FinalEngine::FinalEngine; using FinalEngine::FinalEngine;
void render(Depsgraph *depsgraph) override; void render(Depsgraph *depsgraph) override;
}; };

View File

@ -3,77 +3,61 @@
#include "DEG_depsgraph_query.h" #include "DEG_depsgraph_query.h"
#include "BLI_timer.h"
#include "camera.h" #include "camera.h"
#include "preview_engine.h" #include "preview_engine.h"
#include "BLI_timer.h"
namespace blender::render::hydra { namespace blender::render::hydra {
const double LIFETIME = 180.0; const double LIFETIME = 180.0;
std::unique_ptr<PreviewEngine> PreviewEngine::instance; std::unique_ptr<PreviewEngine> PreviewEngine::instance_;
PreviewEngine *PreviewEngine::get_instance(RenderEngine *bl_engine,
const std::string &render_delegate_id)
{
if (!instance_) {
instance_ = std::make_unique<PreviewEngine>(bl_engine, render_delegate_id);
}
if (BLI_timer_is_registered((uintptr_t)instance_.get())) {
/* Unregister timer while PreviewEngine is working */
BLI_timer_unregister((uintptr_t)instance_.get());
}
instance_->update(bl_engine, render_delegate_id);
return instance_.get();
}
void PreviewEngine::schedule_free() void PreviewEngine::schedule_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(), BLI_timer_register((uintptr_t)instance_.get(), free_instance, nullptr, nullptr, LIFETIME, true);
free_instance,
nullptr,
nullptr,
LIFETIME,
true);
}
PreviewEngine *PreviewEngine::get_instance(RenderEngine *bl_engine, const std::string &render_delegate_id)
{
if (!instance) {
instance = std::make_unique<PreviewEngine>(bl_engine, render_delegate_id);
}
if (BLI_timer_is_registered((uintptr_t)instance.get())) {
/* Unregister timer while PreviewEngine is working */
BLI_timer_unregister((uintptr_t)instance.get());
}
instance->update(bl_engine, render_delegate_id);
return instance.get();
}
double PreviewEngine::free_instance(uintptr_t uuid, void *user_data)
{
if (!instance->render_task_delegate->is_converged()) {
/* Restart timer if render isn't completed */
return LIFETIME;
}
CLOG_INFO(LOG_EN, 2, "");
instance = nullptr;
return -1;
} }
void PreviewEngine::sync(Depsgraph *depsgraph, void PreviewEngine::sync(Depsgraph *depsgraph,
bContext *context, bContext *context,
pxr::HdRenderSettingsMap &render_settings) pxr::HdRenderSettingsMap &render_settings)
{ {
if (!scene_delegate) { if (!scene_delegate_) {
scene_delegate = std::make_unique<BlenderSceneDelegate>( scene_delegate_ = std::make_unique<BlenderSceneDelegate>(
render_index.get(), render_index_.get(),
pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"), pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"),
BlenderSceneDelegate::EngineType::PREVIEW); BlenderSceneDelegate::EngineType::PREVIEW);
} }
scene_delegate->clear(); scene_delegate_->clear();
scene_delegate->populate(depsgraph, context); scene_delegate_->populate(depsgraph, context);
for (auto const &setting : render_settings) { for (auto const &setting : render_settings) {
render_delegate->SetRenderSetting(setting.first, setting.second); render_delegate_->SetRenderSetting(setting.first, setting.second);
} }
} }
void PreviewEngine::render(Depsgraph *depsgraph) void PreviewEngine::render(Depsgraph *depsgraph)
{ {
Scene *scene = DEG_get_input_scene(depsgraph); const Scene *scene = DEG_get_evaluated_scene(depsgraph);
ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); const ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
std::string layer_name = view_layer->name; std::string layer_name = view_layer->name;
pxr::GfVec2i res(scene->r.xsch, scene->r.ysch); pxr::GfVec2i res(scene->r.xsch, scene->r.ysch);
@ -81,45 +65,58 @@ void PreviewEngine::render(Depsgraph *depsgraph)
pxr::GfCamera camera = pxr::GfCamera camera =
CameraData(scene->camera, res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(pxr::GfVec4f(0, 0, 1, 1)); CameraData(scene->camera, res, pxr::GfVec4f(0, 0, 1, 1)).gf_camera(pxr::GfVec4f(0, 0, 1, 1));
free_camera_delegate->SetCamera(camera); free_camera_delegate_->SetCamera(camera);
render_task_delegate->set_camera_and_viewport(free_camera_delegate->GetCameraId(), render_task_delegate_->set_camera_and_viewport(free_camera_delegate_->GetCameraId(),
pxr::GfVec4d(0, 0, res[0], res[1])); pxr::GfVec4d(0, 0, res[0], res[1]));
render_task_delegate->set_renderer_aov(pxr::HdAovTokens->color); render_task_delegate_->set_renderer_aov(pxr::HdAovTokens->color);
pxr::HdTaskSharedPtrVector tasks; pxr::HdTaskSharedPtrVector tasks;
if (simple_light_task_delegate) { if (simple_light_task_delegate_) {
tasks.push_back(simple_light_task_delegate->get_task()); tasks.push_back(simple_light_task_delegate_->get_task());
} }
tasks.push_back(render_task_delegate->get_task()); tasks.push_back(render_task_delegate_->get_task());
std::vector<float> pixels = std::vector<float>(res[0] * res[1] * 4); // 4 - number of channels std::vector<float> pixels = std::vector<float>(res[0] * res[1] *
4); /* 4 - number of channels. */
{ {
// Release the GIL before calling into hydra, in case any hydra plugins call into python. /* Release the GIL before calling into hydra, in case any hydra plugins call into python. */
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE(); pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
engine->Execute(render_index.get(), &tasks); engine_->Execute(render_index_.get(), &tasks);
} }
while (true) { while (true) {
if (RE_engine_test_break(bl_engine)) { if (RE_engine_test_break(bl_engine_)) {
break; break;
} }
if (render_task_delegate->is_converged()) { if (render_task_delegate_->is_converged()) {
break; break;
} }
render_task_delegate->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data()); render_task_delegate_->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data());
update_render_result(layer_name, res[0], res[1], pixels); update_render_result(layer_name, res[0], res[1], pixels);
} }
render_task_delegate->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data()); render_task_delegate_->get_renderer_aov_data(pxr::HdAovTokens->color, pixels.data());
update_render_result(layer_name, res[0], res[1], pixels); update_render_result(layer_name, res[0], res[1], pixels);
} }
double PreviewEngine::free_instance(uintptr_t uuid, void *user_data)
{
if (!instance_->render_task_delegate_->is_converged()) {
/* Restart timer if render isn't completed */
return LIFETIME;
}
CLOG_INFO(LOG_EN, 2, "");
instance_ = nullptr;
return -1;
}
void PreviewEngine::update(RenderEngine *bl_engine, const std::string &render_delegate_id) void PreviewEngine::update(RenderEngine *bl_engine, const std::string &render_delegate_id)
{ {
this->bl_engine = bl_engine; this->bl_engine_ = bl_engine;
/* TODO: recreate render_delegate when render_delegate_id is changed */ /* TODO: recreate render_delegate when render_delegate_id is changed */
} }
@ -129,13 +126,13 @@ void PreviewEngine::update_render_result(const std::string &layer_name,
std::vector<float> &pixels) std::vector<float> &pixels)
{ {
RenderResult *result = RE_engine_begin_result( RenderResult *result = RE_engine_begin_result(
bl_engine, 0, 0, width, height, layer_name.c_str(), nullptr); bl_engine_, 0, 0, width, height, layer_name.c_str(), nullptr);
RenderLayer *layer = (RenderLayer *)result->layers.first; RenderLayer *layer = (RenderLayer *)result->layers.first;
RenderPass *pass = (RenderPass *)layer->passes.first; RenderPass *pass = (RenderPass *)layer->passes.first;
memcpy(pass->rect, pixels.data(), sizeof(float) * pass->rectx * pass->recty * pass->channels); memcpy(pass->rect, pixels.data(), sizeof(float) * pass->rectx * pass->recty * pass->channels);
RE_engine_end_result(bl_engine, result, false, false, false); RE_engine_end_result(bl_engine_, result, false, false, false);
} }
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -8,28 +8,28 @@
namespace blender::render::hydra { namespace blender::render::hydra {
class PreviewEngine : public FinalEngine { class PreviewEngine : public FinalEngine {
private:
/* Singleton class instance */
static std::unique_ptr<PreviewEngine> instance;
static double free_instance(uintptr_t uuid, void *user_data);
public: public:
static PreviewEngine *get_instance(RenderEngine *bl_engine, const std::string &render_delegate_id); using FinalEngine::FinalEngine;
static PreviewEngine *get_instance(RenderEngine *bl_engine,
const std::string &render_delegate_id);
static void schedule_free(); static void schedule_free();
using FinalEngine::FinalEngine;
void sync(Depsgraph *depsgraph, void sync(Depsgraph *depsgraph,
bContext *context, bContext *context,
pxr::HdRenderSettingsMap &render_settings) override; pxr::HdRenderSettingsMap &render_settings) override;
void render(Depsgraph *depsgraph) override; void render(Depsgraph *depsgraph) override;
private: private:
/* Singleton class instance */
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_id); void update(RenderEngine *bl_engine, const std::string &render_delegate_id);
void update_render_result(const std::string &layer_name, void update_render_result(const std::string &layer_name,
int width, int width,
int height, int height,
std::vector<float> &pixels); std::vector<float> &pixels);
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -236,8 +236,8 @@ static PyMethodDef methods[] = {
{"engine_create", engine_create_func, METH_VARARGS, ""}, {"engine_create", engine_create_func, METH_VARARGS, ""},
{"engine_free", engine_free_func, METH_VARARGS, ""}, {"engine_free", engine_free_func, METH_VARARGS, ""},
{"engine_render", engine_render_func, METH_VARARGS, ""},
{"engine_sync", engine_sync_func, METH_VARARGS, ""}, {"engine_sync", engine_sync_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, ""},
{NULL, NULL, 0, NULL}, {NULL, NULL, 0, NULL},

View File

@ -22,8 +22,8 @@ RenderTaskDelegate::RenderTaskDelegate(pxr::HdRenderIndex *parent_index,
GetRenderIndex().GetChangeTracker().MarkTaskDirty(render_task_id, GetRenderIndex().GetChangeTracker().MarkTaskDirty(render_task_id,
pxr::HdChangeTracker::DirtyRenderTags); pxr::HdChangeTracker::DirtyRenderTags);
task_params.enableLighting = true; task_params_.enableLighting = true;
task_params.alphaThreshold = 0.1f; task_params_.alphaThreshold = 0.1f;
} }
pxr::SdfPath RenderTaskDelegate::get_task_id() const pxr::SdfPath RenderTaskDelegate::get_task_id() const
@ -36,32 +36,6 @@ pxr::SdfPath RenderTaskDelegate::get_aov_id(pxr::TfToken const &aov) const
return GetDelegateID().AppendElementString("aov_" + aov.GetString()); return GetDelegateID().AppendElementString("aov_" + aov.GetString());
} }
pxr::VtValue RenderTaskDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
{
if (key == pxr::HdTokens->params) {
return pxr::VtValue(task_params);
}
if (key == pxr::HdTokens->collection) {
pxr::HdRprimCollection rprim_collection(pxr::HdTokens->geometry,
pxr::HdReprSelector(pxr::HdReprTokens->smoothHull),
false,
pxr::TfToken());
rprim_collection.SetRootPath(pxr::SdfPath::AbsoluteRootPath());
return pxr::VtValue(rprim_collection);
}
return pxr::VtValue();
}
pxr::HdRenderBufferDescriptor RenderTaskDelegate::GetRenderBufferDescriptor(pxr::SdfPath const &id)
{
return buffer_descriptors[id];
}
pxr::TfTokenVector RenderTaskDelegate::GetTaskRenderTags(pxr::SdfPath const &task_id)
{
return {pxr::HdRenderTagTokens->geometry};
}
bool RenderTaskDelegate::is_converged() bool RenderTaskDelegate::is_converged()
{ {
pxr::HdTaskSharedPtr renderTask = GetRenderIndex().GetTask(get_task_id()); pxr::HdTaskSharedPtr renderTask = GetRenderIndex().GetTask(get_task_id());
@ -73,14 +47,14 @@ void RenderTaskDelegate::set_renderer_aov(pxr::TfToken const &aov)
pxr::HdAovDescriptor aov_desc = GetRenderIndex().GetRenderDelegate()->GetDefaultAovDescriptor( pxr::HdAovDescriptor aov_desc = GetRenderIndex().GetRenderDelegate()->GetDefaultAovDescriptor(
aov); aov);
pxr::HdRenderBufferDescriptor desc( pxr::HdRenderBufferDescriptor desc(
pxr::GfVec3i(task_params.viewport[2], task_params.viewport[3], 1), pxr::GfVec3i(task_params_.viewport[2], task_params_.viewport[3], 1),
aov_desc.format, aov_desc.format,
aov_desc.multiSampled); aov_desc.multiSampled);
pxr::SdfPath buffer_id = get_aov_id(aov); pxr::SdfPath buffer_id = get_aov_id(aov);
if (buffer_descriptors.find(buffer_id) == buffer_descriptors.end()) { if (buffer_descriptors_.find(buffer_id) == buffer_descriptors_.end()) {
GetRenderIndex().InsertBprim(pxr::HdPrimTypeTokens->renderBuffer, this, buffer_id); GetRenderIndex().InsertBprim(pxr::HdPrimTypeTokens->renderBuffer, this, buffer_id);
buffer_descriptors[buffer_id] = desc; buffer_descriptors_[buffer_id] = desc;
GetRenderIndex().GetChangeTracker().MarkBprimDirty(buffer_id, GetRenderIndex().GetChangeTracker().MarkBprimDirty(buffer_id,
pxr::HdRenderBuffer::DirtyDescription); pxr::HdRenderBuffer::DirtyDescription);
@ -88,13 +62,13 @@ void RenderTaskDelegate::set_renderer_aov(pxr::TfToken const &aov)
binding.aovName = aov; binding.aovName = aov;
binding.renderBufferId = buffer_id; binding.renderBufferId = buffer_id;
binding.aovSettings = aov_desc.aovSettings; binding.aovSettings = aov_desc.aovSettings;
task_params.aovBindings.push_back(binding); task_params_.aovBindings.push_back(binding);
GetRenderIndex().GetChangeTracker().MarkTaskDirty(get_task_id(), GetRenderIndex().GetChangeTracker().MarkTaskDirty(get_task_id(),
pxr::HdChangeTracker::DirtyParams); pxr::HdChangeTracker::DirtyParams);
} }
else if (buffer_descriptors[buffer_id] != desc) { else if (buffer_descriptors_[buffer_id] != desc) {
buffer_descriptors[buffer_id] = desc; buffer_descriptors_[buffer_id] = desc;
GetRenderIndex().GetChangeTracker().MarkBprimDirty(buffer_id, GetRenderIndex().GetChangeTracker().MarkBprimDirty(buffer_id,
pxr::HdRenderBuffer::DirtyDescription); pxr::HdRenderBuffer::DirtyDescription);
} }
@ -124,12 +98,38 @@ pxr::HdTaskSharedPtr RenderTaskDelegate::get_task()
void RenderTaskDelegate::set_camera_and_viewport(pxr::SdfPath const &camera_id, void RenderTaskDelegate::set_camera_and_viewport(pxr::SdfPath const &camera_id,
pxr::GfVec4d const &viewport) pxr::GfVec4d const &viewport)
{ {
if (task_params.viewport != viewport || task_params.camera != camera_id) { if (task_params_.viewport != viewport || task_params_.camera != camera_id) {
task_params.viewport = viewport; task_params_.viewport = viewport;
task_params.camera = camera_id; task_params_.camera = camera_id;
GetRenderIndex().GetChangeTracker().MarkTaskDirty(get_task_id(), GetRenderIndex().GetChangeTracker().MarkTaskDirty(get_task_id(),
pxr::HdChangeTracker::DirtyParams); pxr::HdChangeTracker::DirtyParams);
} }
} }
pxr::VtValue RenderTaskDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
{
if (key == pxr::HdTokens->params) {
return pxr::VtValue(task_params_);
}
if (key == pxr::HdTokens->collection) {
pxr::HdRprimCollection rprim_collection(pxr::HdTokens->geometry,
pxr::HdReprSelector(pxr::HdReprTokens->smoothHull),
false,
pxr::TfToken());
rprim_collection.SetRootPath(pxr::SdfPath::AbsoluteRootPath());
return pxr::VtValue(rprim_collection);
}
return pxr::VtValue();
}
pxr::HdRenderBufferDescriptor RenderTaskDelegate::GetRenderBufferDescriptor(pxr::SdfPath const &id)
{
return buffer_descriptors_[id];
}
pxr::TfTokenVector RenderTaskDelegate::GetTaskRenderTags(pxr::SdfPath const &task_id)
{
return {pxr::HdRenderTagTokens->geometry};
}
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -16,10 +16,6 @@ class RenderTaskDelegate : public pxr::HdSceneDelegate {
pxr::SdfPath get_task_id() const; pxr::SdfPath get_task_id() const;
pxr::SdfPath get_aov_id(pxr::TfToken const &aov) const; pxr::SdfPath get_aov_id(pxr::TfToken const &aov) const;
pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override;
pxr::HdRenderBufferDescriptor GetRenderBufferDescriptor(pxr::SdfPath const &id) override;
pxr::TfTokenVector GetTaskRenderTags(pxr::SdfPath const &taskId) override;
bool is_converged(); bool is_converged();
void set_renderer_aov(pxr::TfToken const &aovId); void set_renderer_aov(pxr::TfToken const &aovId);
pxr::HdRenderBuffer *get_renderer_aov(pxr::TfToken const &id); pxr::HdRenderBuffer *get_renderer_aov(pxr::TfToken const &id);
@ -28,10 +24,15 @@ class RenderTaskDelegate : public pxr::HdSceneDelegate {
pxr::HdTaskSharedPtr get_task(); pxr::HdTaskSharedPtr get_task();
void set_camera_and_viewport(pxr::SdfPath const &cameraId, pxr::GfVec4d const &viewport); void set_camera_and_viewport(pxr::SdfPath const &cameraId, pxr::GfVec4d const &viewport);
/* Delegate methods */
pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override;
pxr::HdRenderBufferDescriptor GetRenderBufferDescriptor(pxr::SdfPath const &id) override;
pxr::TfTokenVector GetTaskRenderTags(pxr::SdfPath const &taskId) override;
private: private:
pxr::HdxRenderTaskParams task_params; pxr::HdxRenderTaskParams task_params_;
pxr::TfHashMap<pxr::SdfPath, pxr::HdRenderBufferDescriptor, pxr::SdfPath::Hash> pxr::TfHashMap<pxr::SdfPath, pxr::HdRenderBufferDescriptor, pxr::SdfPath::Hash>
buffer_descriptors; buffer_descriptors_;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -16,153 +16,18 @@ CLG_LOGREF_DECLARE_GLOBAL(LOG_BSD, "rhd.bsd");
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) BlenderSceneDelegate::EngineType engine_type)
: HdSceneDelegate(parent_index, delegate_id), : HdSceneDelegate(parent_index, delegate_id), engine_type(engine_type)
engine_type(engine_type),
depsgraph(nullptr),
context(nullptr),
view3d(nullptr)
{ {
} }
bool BlenderSceneDelegate::GetVisible(pxr::SdfPath const &id)
{
if (id == WorldData::prim_id(this)) {
return true;
}
return object_data(id)->visible;
}
pxr::SdfPath BlenderSceneDelegate::GetInstancerId(pxr::SdfPath const &prim_id)
{
CLOG_INFO(LOG_BSD, 3, "%s", prim_id.GetText());
InstancerData *i_data = instancer_data(prim_id.GetParentPath());
if (i_data) {
return i_data->p_id;
}
return pxr::SdfPath();
}
pxr::SdfPathVector BlenderSceneDelegate::GetInstancerPrototypes(pxr::SdfPath const &instancer_id)
{
CLOG_INFO(LOG_BSD, 3, "%s", instancer_id.GetText());
InstancerData *i_data = instancer_data(instancer_id);
return i_data->prototypes();
}
pxr::VtIntArray BlenderSceneDelegate::GetInstanceIndices(pxr::SdfPath const &instancer_id,
pxr::SdfPath const &prototype_id)
{
CLOG_INFO(LOG_BSD, 3, "%s, %s", instancer_id.GetText(), prototype_id.GetText());
InstancerData *i_data = instancer_data(instancer_id);
return i_data->indices(prototype_id);
}
pxr::GfMatrix4d BlenderSceneDelegate::GetInstancerTransform(pxr::SdfPath const &instancer_id)
{
CLOG_INFO(LOG_BSD, 3, "%s", instancer_id.GetText());
InstancerData *i_data = instancer_data(instancer_id);
return i_data->transform();
}
void BlenderSceneDelegate::update_objects(Object *object)
{
if (!ObjectData::supported(object)) {
return;
}
pxr::SdfPath id = ObjectData::prim_id(this, object);
ObjectData *obj_data = object_data(id);
if (obj_data) {
obj_data->update();
return;
}
if (view3d && !BKE_object_is_visible_in_viewport(view3d, object)) {
return;
}
objects[id] = ObjectData::create(this, object);
obj_data = object_data(id);
obj_data->update_visibility(view3d);
}
void BlenderSceneDelegate::update_instancers(Object *object)
{
/* Check object inside instancers */
for (auto &it : instancers) {
it.second->check_update(object);
}
pxr::SdfPath id = InstancerData::prim_id(this, object);
InstancerData *i_data = instancer_data(id);
if (i_data) {
if (object->transflag & OB_DUPLI) {
i_data->update();
}
else {
i_data->remove();
instancers.erase(id);
}
return;
}
if ((object->transflag & OB_DUPLI) == 0) {
return;
}
if (view3d && !BKE_object_is_visible_in_viewport(view3d, object)) {
return;
}
instancers[id] = InstancerData::create(this, object);
i_data = instancer_data(id);
i_data->update_visibility(view3d);
}
ObjectData *BlenderSceneDelegate::object_data(pxr::SdfPath const &id)
{
auto it = objects.find(id);
if (it != objects.end()) {
return it->second.get();
}
InstancerData *i_data = instancer_data(id.GetParentPath());
if (i_data) {
return i_data->object_data(id);
}
return nullptr;
}
MeshData *BlenderSceneDelegate::mesh_data(pxr::SdfPath const &id)
{
return dynamic_cast<MeshData *>(object_data(id));
}
LightData *BlenderSceneDelegate::light_data(pxr::SdfPath const &id)
{
return dynamic_cast<LightData *>(object_data(id));
}
MaterialData *BlenderSceneDelegate::material_data(pxr::SdfPath const &id)
{
auto it = materials.find(id);
if (it == materials.end()) {
return nullptr;
}
return it->second.get();
}
InstancerData *BlenderSceneDelegate::instancer_data(pxr::SdfPath const &id)
{
auto it = instancers.find(id);
if (it != instancers.end()) {
return it->second.get();
}
return nullptr;
}
void BlenderSceneDelegate::populate(Depsgraph *deps, bContext *cont) void BlenderSceneDelegate::populate(Depsgraph *deps, bContext *cont)
{ {
bool is_populated = depsgraph != nullptr; bool is_populated = depsgraph_ != nullptr;
depsgraph = deps; depsgraph_ = deps;
context = cont; context_ = cont;
scene = DEG_get_input_scene(depsgraph); scene_ = DEG_get_input_scene(depsgraph_);
view3d = CTX_wm_view3d(context); view3d_ = CTX_wm_view3d(context_);
if (is_populated) { if (is_populated) {
check_updates(); check_updates();
@ -289,13 +154,13 @@ void BlenderSceneDelegate::check_updates()
bool do_update_visibility = false; bool do_update_visibility = false;
bool do_update_world = false; bool do_update_world = false;
unsigned int scene_recalc = scene->id.recalc; unsigned int scene_recalc = scene_->id->recalc;
if (scene_recalc) { if (scene_recalc) {
/* Checking scene updates */ /* Checking scene updates */
CLOG_INFO(LOG_BSD, CLOG_INFO(LOG_BSD,
2, 2,
"Update: %s [%s]", "Update: %s [%s]",
((ID *)scene)->name, ((ID *)scene_)->name,
std::bitset<32>(scene_recalc).to_string().c_str()); std::bitset<32>(scene_recalc).to_string().c_str());
if (scene_recalc & ID_RECALC_BASE_FLAGS) { if (scene_recalc & ID_RECALC_BASE_FLAGS) {
@ -305,7 +170,7 @@ void BlenderSceneDelegate::check_updates()
do_update_collection = true; do_update_collection = true;
} }
if (scene_recalc & ID_RECALC_AUDIO_VOLUME) { if (scene_recalc & ID_RECALC_AUDIO_VOLUME) {
if ((scene->world && !world_data) || (!scene->world && world_data)) { if ((scene_->world && !world_data_) || (!scene_->world && world_data_)) {
do_update_world = true; do_update_world = true;
} }
} }
@ -313,7 +178,7 @@ void BlenderSceneDelegate::check_updates()
/* Checking other objects updates */ /* Checking other objects 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) {
@ -358,7 +223,21 @@ void BlenderSceneDelegate::check_updates()
} }
} }
void BlenderSceneDelegate::add_new_objects() void BlenderSceneDelegate::clear()
{
for (auto &it : materials_) {
it.second->remove();
}
for (auto &it : objects_) {
it.second->remove();
}
materials_.clear();
objects_.clear();
}
pxr::HdMeshTopology BlenderSceneDelegate::GetMeshTopology(pxr::SdfPath const &id)
{ {
DEGObjectIterSettings settings = {0}; DEGObjectIterSettings settings = {0};
settings.depsgraph = depsgraph; settings.depsgraph = depsgraph;
@ -375,17 +254,51 @@ void BlenderSceneDelegate::add_new_objects()
Object *, Object *,
object) { object) {
if (!ObjectData::supported(object)) { pxr::GfMatrix4d BlenderSceneDelegate::GetTransform(pxr::SdfPath const &id)
continue; {
CLOG_INFO(LOG_BSD, 3, "%s", id.GetText());
ObjectData *obj_data = object_data(id);
if (obj_data) {
return obj_data->transform();
} }
if (id == WorldData::prim_id(this)) {
return world_data_->transform();
}
InstancerData *i_data = instancer_data(id);
if (i_data) {
return i_data->transform();
}
return pxr::GfMatrix4d();
}
pxr::VtValue BlenderSceneDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
{
CLOG_INFO(LOG_BSD, 3, "%s, %s", id.GetText(), key.GetText());
update_objects(object); update_objects(object);
update_instancers(object); update_instancers(object);
} }
ITER_END; ITER_END;
} }
void BlenderSceneDelegate::remove_unused_objects() pxr::VtValue BlenderSceneDelegate::GetLightParamValue(pxr::SdfPath const &id,
pxr::TfToken const &key)
{
LightData *l_data = light_data(id);
if (l_data) {
return l_data->get_data(key);
}
if (id == WorldData::prim_id(this)) {
return world_data_->get_data(key);
}
return pxr::VtValue();
}
pxr::HdPrimvarDescriptorVector BlenderSceneDelegate::GetPrimvarDescriptors(
pxr::SdfPath const &id, pxr::HdInterpolation interpolation)
{ {
/* Get available objects */ /* Get available objects */
std::set<std::string> available_objects; std::set<std::string> available_objects;
@ -434,17 +347,11 @@ void BlenderSceneDelegate::remove_unused_objects()
} }
/* Remove unused materials */ pxr::VtValue BlenderSceneDelegate::GetMaterialResource(pxr::SdfPath const &id)
std::set<pxr::SdfPath> available_materials; {
for (auto &it : objects) { MaterialData *mat_data = material_data(id);
MeshData *m_data = dynamic_cast<MeshData *>(it.second.get()); if (mat_data) {
if (!m_data) { return mat_data->get_material_resource();
continue;
}
pxr::SdfPath mat_id = m_data->material_id();
if (!mat_id.IsEmpty()) {
available_materials.insert(mat_id);
}
} }
for (auto &it : instancers) { for (auto &it : instancers) {
it.second->available_materials(available_materials); it.second->available_materials(available_materials);
@ -459,18 +366,167 @@ void BlenderSceneDelegate::remove_unused_objects()
} }
} }
void BlenderSceneDelegate::update_visibility() bool BlenderSceneDelegate::GetVisible(pxr::SdfPath const &id)
{ {
for (auto &it : objects) { if (id == WorldData::prim_id(this)) {
it.second->update_visibility(view3d); return true;
}
for (auto &it : instancers) {
it.second->update_visibility(view3d);
} }
/* Add objects which were invisible before and not added yet */ return object_data(id)->visible;
}
pxr::SdfPath BlenderSceneDelegate::GetInstancerId(pxr::SdfPath const &prim_id)
{
CLOG_INFO(LOG_BSD, 3, "%s", prim_id.GetText());
InstancerData *i_data = instancer_data(prim_id, true);
if (i_data) {
return i_data->instancer_id;
}
return pxr::SdfPath();
}
pxr::SdfPathVector BlenderSceneDelegate::GetInstancerPrototypes(pxr::SdfPath const &instancer_id)
{
CLOG_INFO(LOG_BSD, 3, "%s", instancer_id.GetText());
pxr::SdfPathVector paths;
paths.push_back(instancer_id.GetParentPath());
return paths;
}
pxr::VtIntArray BlenderSceneDelegate::GetInstanceIndices(pxr::SdfPath const &instancer_id,
pxr::SdfPath const &prototype_id)
{
CLOG_INFO(LOG_BSD, 3, "%s, %s", instancer_id.GetText(), prototype_id.GetText());
InstancerData *i_data = instancer_data(instancer_id);
return i_data->instance_indices();
}
pxr::GfMatrix4d BlenderSceneDelegate::GetInstancerTransform(pxr::SdfPath const &instancer_id)
{
CLOG_INFO(LOG_BSD, 3, "%s", instancer_id.GetText());
InstancerData *i_data = instancer_data(instancer_id);
return i_data->transform();
}
ObjectData *BlenderSceneDelegate::object_data(pxr::SdfPath const &id)
{
auto it = objects_.find(id);
if (it == objects_.end()) {
return nullptr;
}
return it->second.get();
}
MeshData *BlenderSceneDelegate::mesh_data(pxr::SdfPath const &id)
{
return dynamic_cast<MeshData *>(object_data(id));
}
LightData *BlenderSceneDelegate::light_data(pxr::SdfPath const &id)
{
return dynamic_cast<LightData *>(object_data(id));
}
MaterialData *BlenderSceneDelegate::material_data(pxr::SdfPath const &id)
{
auto it = materials_.find(id);
if (it == materials_.end()) {
return nullptr;
}
return it->second.get();
}
InstancerData *BlenderSceneDelegate::instancer_data(pxr::SdfPath const &id, bool base_prim)
{
if (base_prim) {
return dynamic_cast<InstancerData *>(object_data(id));
}
return dynamic_cast<InstancerData *>(object_data(id.GetParentPath()));
}
InstancerData *BlenderSceneDelegate::instancer_data(Object *object)
{
InstancerData *i_data;
for (auto &it : objects_) {
i_data = dynamic_cast<InstancerData *>(it.second.get());
if (i_data && i_data->is_base(object)) {
return i_data;
}
}
return nullptr;
}
void BlenderSceneDelegate::add_update_object(Object *object)
{
if ((object->transflag & OB_DUPLI) && InstancerData::is_supported(object)) {
add_update_instancer(object);
}
InstancerData *i_data = instancer_data(object);
if (i_data) {
i_data->update();
}
pxr::SdfPath id = ObjectData::prim_id(this, object);
ObjectData *obj_data = object_data(id);
if (obj_data) {
obj_data->update();
return;
}
if (view3d_ && !BKE_object_is_visible_in_viewport(view3d_, object)) {
return;
}
objects_[id] = ObjectData::create(this, object);
obj_data = object_data(id);
obj_data->update_visibility(view3d_);
}
void BlenderSceneDelegate::add_update_instancer(Object *object)
{
pxr::SdfPath id = InstancerData::prim_id(this, object);
InstancerData *i_data = instancer_data(id, true);
if (i_data) {
i_data->update();
return;
}
objects_[id] = InstancerData::create(this, object);
i_data = instancer_data(id, true);
i_data->update_visibility(view3d_);
}
void BlenderSceneDelegate::update_world()
{
World *world = scene_->world;
if (!world_data_) {
if (world) {
world_data_ = WorldData::create(this, world, context_);
}
}
else {
if (world) {
world_data_->update(world);
}
else {
world_data_->remove();
world_data_ = nullptr;
}
}
}
void BlenderSceneDelegate::update_collection(bool remove, bool visibility)
{
if (visibility) {
/* Check and update visibility */
for (auto &obj : objects_) {
obj.second->update_visibility(view3d_);
}
}
/* Export of new visible objects which were not exported before */
std::set<pxr::SdfPath> available_objects;
pxr::SdfPath id;
DEGObjectIterSettings settings = {0}; DEGObjectIterSettings settings = {0};
settings.depsgraph = depsgraph; settings.depsgraph = depsgraph_;
settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE | settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE |
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET; DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET;
DEGObjectIterData data = {0}; DEGObjectIterData data = {0};
@ -484,32 +540,57 @@ void BlenderSceneDelegate::update_visibility()
Object *, Object *,
object) { object) {
if (!ObjectData::supported(object)) { CLOG_INFO(LOG_BSD, 2, "Add %s", ((ID *)object)->name);
if (!ObjectData::is_supported(object)) {
continue; continue;
} }
if (!object_data(ObjectData::prim_id(this, object))) { id = ObjectData::prim_id(this, object);
update_objects(object); if (remove) {
available_objects.insert(id);
if ((object->transflag & OB_DUPLI) && InstancerData::is_supported(object)) {
available_objects.insert(InstancerData::prim_id(this, object));
} }
if (!instancer_data(InstancerData::prim_id(this, object))) { }
update_instancers(object);
if (!object_data(id)) {
add_update_object(object);
} }
} }
ITER_END; ITER_END;
}
void BlenderSceneDelegate::clear() if (remove) {
{ /* remove unused objects */
for (auto &it : materials) { for (auto it = objects_.begin(); it != objects_.end(); ++it) {
it.second->remove(); if (available_objects.find(it->first) != available_objects.end()) {
continue;
}
it->second->remove();
objects_.erase(it);
it = objects_.begin();
} }
for (auto &it : objects) { /* remove unused materials */
it.second->remove(); std::set<pxr::SdfPath> available_materials;
for (auto &obj : objects_) {
MeshData *m_data = dynamic_cast<MeshData *>(obj.second.get());
if (!m_data) {
continue;
}
pxr::SdfPath mat_id = m_data->material_id();
if (!mat_id.IsEmpty()) {
available_materials.insert(mat_id);
}
}
for (auto it = materials_.begin(); it != materials_.end(); ++it) {
if (available_materials.find(it->first) != available_materials.end()) {
continue;
}
it->second->remove();
materials_.erase(it);
it = materials_.begin();
}
} }
materials.clear();
objects.clear();
} }
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -27,12 +27,12 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
public: public:
enum class EngineType { VIEWPORT = 1, FINAL, PREVIEW }; enum class EngineType { VIEWPORT = 1, FINAL, PREVIEW };
BlenderSceneDelegate(pxr::HdRenderIndex *render_index, BlenderSceneDelegate(pxr::HdRenderIndex *parent_index,
pxr::SdfPath const &delegate_id, pxr::SdfPath const &delegate_id,
BlenderSceneDelegate::EngineType engine_type); BlenderSceneDelegate::EngineType engine_type);
~BlenderSceneDelegate() override = default; ~BlenderSceneDelegate() override = default;
// delegate methods /* Delegate methods */
pxr::HdMeshTopology GetMeshTopology(pxr::SdfPath const &id) override; pxr::HdMeshTopology GetMeshTopology(pxr::SdfPath const &id) override;
pxr::GfMatrix4d GetTransform(pxr::SdfPath const &id) override; pxr::GfMatrix4d GetTransform(pxr::SdfPath const &id) override;
pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override; pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override;
@ -68,17 +68,15 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
void remove_unused_objects(); void remove_unused_objects();
void update_visibility(); void update_visibility();
Depsgraph *depsgraph_ = nullptr;
bContext *context_ = nullptr;
View3D *view3d_ = nullptr;
Scene *scene_ = nullptr;
private: ObjectDataMap objects_;
Depsgraph *depsgraph; MaterialDataMap materials_;
bContext *context; InstancerDataMap instancers_;
Scene *scene; std::unique_ptr<WorldData> world_data_;
View3D *view3d;
ObjectDataMap objects;
MaterialDataMap materials;
InstancerDataMap instancers;
std::unique_ptr<WorldData> world_data;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -9,7 +9,7 @@
namespace blender::render::hydra { namespace blender::render::hydra {
IdData::IdData(BlenderSceneDelegate *scene_delegate, ID *id) IdData::IdData(BlenderSceneDelegate *scene_delegate, ID *id)
: id(id), scene_delegate(scene_delegate) : scene_delegate_(scene_delegate), id_(id)
{ {
} }

View File

@ -26,11 +26,10 @@ class IdData {
virtual pxr::VtValue get_data(pxr::TfToken const &key) const; virtual pxr::VtValue get_data(pxr::TfToken const &key) const;
template<class T> const T get_data(pxr::TfToken const &key) const; template<class T> const T get_data(pxr::TfToken const &key) const;
ID *id;
pxr::SdfPath p_id;
protected: protected:
BlenderSceneDelegate *scene_delegate; BlenderSceneDelegate *scene_delegate_;
ID *id_;
pxr::SdfPath p_id_;
}; };
template<class T> const T IdData::get_data(pxr::TfToken const &key) const template<class T> const T IdData::get_data(pxr::TfToken const &key) const
@ -39,6 +38,6 @@ template<class T> const T IdData::get_data(pxr::TfToken const &key) const
} }
#define ID_LOG(level, msg, ...) \ #define ID_LOG(level, msg, ...) \
CLOG_INFO(LOG_BSD, level, "%s (%s): " msg, p_id.GetText(), id->name, __VA_ARGS__); CLOG_INFO(LOG_BSD, level, "%s (%s): " msg, p_id_.GetText(), id_->name, __VA_ARGS__);
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -9,7 +9,16 @@
namespace blender::render::hydra { namespace blender::render::hydra {
bool InstancerData::supported(Object *object) InstancerData::InstancerData(BlenderSceneDelegate *scene_delegate, Object *object)
: MeshData(scene_delegate, object), parent_obj_(object)
{
id_ = nullptr;
p_id_ = prim_id(scene_delegate, object);
instancer_id = p_id_.AppendElementString("Instancer");
CLOG_INFO(LOG_BSD, 2, "%s, instancer_id=%s", ((ID *)parent_obj_)->name, instancer_id.GetText());
}
bool InstancerData::is_supported(Object *object)
{ {
switch (object->type) { switch (object->type) {
case OB_MESH: case OB_MESH:
@ -56,6 +65,54 @@ void InstancerData::init()
set_instances(); set_instances();
} }
void InstancerData::insert()
{
ID_LOG(2, "");
scene_delegate->GetRenderIndex().InsertInstancer(scene_delegate, p_id);
for (auto &it : instances) {
it.second.obj_data->insert();
}
}
void InstancerData::remove()
{
CLOG_INFO(LOG_BSD, 2, "%s", p_id.GetText());
for (auto &it : instances) {
it.second.obj_data->remove();
}
scene_delegate->GetRenderIndex().RemoveInstancer(p_id);
}
void InstancerData::update()
{
ID_LOG(2, "");
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
Object *object = (Object *)id;
if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
set_instances();
bits |= pxr::HdChangeTracker::AllDirty;
}
else if (id->recalc & ID_RECALC_TRANSFORM) {
set_instances();
bits |= pxr::HdChangeTracker::DirtyTransform;
}
if (bits != pxr::HdChangeTracker::Clean) {
scene_delegate->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(p_id, bits);
}
}
pxr::VtValue InstancerData::get_data(pxr::TfToken const &key) const
{
ID_LOG(3, "%s", key.GetText());
pxr::VtValue ret;
if (key == pxr::HdInstancerTokens->instanceTransform) {
ret = transforms;
}
return ret;
}
pxr::GfMatrix4d InstancerData::transform() pxr::GfMatrix4d InstancerData::transform()
{ {
return pxr::GfMatrix4d(1.0); return pxr::GfMatrix4d(1.0);
@ -80,16 +137,6 @@ bool InstancerData::update_visibility(View3D *view3d)
return ret; return ret;
} }
pxr::VtValue InstancerData::get_data(pxr::TfToken const &key) const
{
ID_LOG(3, "%s", key.GetText());
pxr::VtValue ret;
if (key == pxr::HdInstancerTokens->instanceTransform) {
ret = transforms;
}
return ret;
}
pxr::HdPrimvarDescriptorVector InstancerData::primvar_descriptors(pxr::HdInterpolation interpolation) pxr::HdPrimvarDescriptorVector InstancerData::primvar_descriptors(pxr::HdInterpolation interpolation)
{ {
pxr::HdPrimvarDescriptorVector primvars; pxr::HdPrimvarDescriptorVector primvars;
@ -196,7 +243,7 @@ void InstancerData::set_instances()
else { else {
inst = &it->second; inst = &it->second;
} }
transforms.push_back(gf_matrix_from_transform(dupli->mat)); transforms_.push_back(gf_matrix_from_transform(dupli->mat));
inst->indices.push_back(index); inst->indices.push_back(index);
ID_LOG(2, "Instance %s %d", inst->obj_data->id->name, index); ID_LOG(2, "Instance %s %d", inst->obj_data->id->name, index);
++index; ++index;
@ -214,44 +261,6 @@ void InstancerData::set_instances()
} }
} }
void InstancerData::insert()
{
ID_LOG(2, "");
scene_delegate->GetRenderIndex().InsertInstancer(scene_delegate, p_id);
for (auto &it : instances) {
it.second.obj_data->insert();
}
}
void InstancerData::remove()
{
CLOG_INFO(LOG_BSD, 2, "%s", p_id.GetText());
for (auto &it : instances) {
it.second.obj_data->remove();
}
scene_delegate->GetRenderIndex().RemoveInstancer(p_id);
}
void InstancerData::update()
{
ID_LOG(2, "");
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
Object *object = (Object *)id;
if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
set_instances();
bits |= pxr::HdChangeTracker::AllDirty;
}
else if (id->recalc & ID_RECALC_TRANSFORM) {
set_instances();
bits |= pxr::HdChangeTracker::DirtyTransform;
}
if (bits != pxr::HdChangeTracker::Clean) {
scene_delegate->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(p_id, bits);
}
}
InstanceMeshData::InstanceMeshData(BlenderSceneDelegate *scene_delegate, InstanceMeshData::InstanceMeshData(BlenderSceneDelegate *scene_delegate,
Object *object, Object *object,
pxr::SdfPath const &p_id) pxr::SdfPath const &p_id)

View File

@ -16,17 +16,18 @@ class InstancerData : public ObjectData {
}; };
public: public:
static bool supported(Object *object); InstancerData(BlenderSceneDelegate *scene_delegate, Object *object);
static bool is_supported(Object *object);
static std::unique_ptr<InstancerData> create(BlenderSceneDelegate *scene_delegate, static std::unique_ptr<InstancerData> create(BlenderSceneDelegate *scene_delegate,
Object *object); Object *object);
static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate, Object *object); static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate, Object *object);
InstancerData(BlenderSceneDelegate *scene_delegate, Object *object);
void init() override; void init() override;
void insert() override; void insert() override;
void remove() override; void remove() override;
void update() override; void update() override;
pxr::VtValue get_data(pxr::TfToken const &key) const override; pxr::VtValue get_data(pxr::TfToken const &key) const override;
pxr::GfMatrix4d transform() override; pxr::GfMatrix4d transform() override;
bool update_visibility(View3D *view3d) override; bool update_visibility(View3D *view3d) override;
@ -38,6 +39,7 @@ class InstancerData : public ObjectData {
void check_update(Object *object); void check_update(Object *object);
void check_remove(std::set<std::string> &available_objects); void check_remove(std::set<std::string> &available_objects);
void available_materials(std::set<pxr::SdfPath> &paths); void available_materials(std::set<pxr::SdfPath> &paths);
bool is_base(Object *object) const;
private: private:
void set_instances(); void set_instances();

View File

@ -24,65 +24,131 @@ void LightData::init()
{ {
ID_LOG(2, ""); ID_LOG(2, "");
Light *light = (Light *)((Object *)id)->data; Light *light = (Light *)((Object *)id_)->data;
data.clear(); data_.clear();
float intensity = light->energy; float intensity = light->energy;
if (scene_delegate->engine_type == BlenderSceneDelegate::EngineType::PREVIEW) { if (scene_delegate_->engine_type == BlenderSceneDelegate::EngineType::PREVIEW) {
intensity *= 0.001; intensity *= 0.001;
} }
data[pxr::HdLightTokens->intensity] = intensity; data_[pxr::HdLightTokens->intensity] = intensity;
data[pxr::HdLightTokens->color] = pxr::GfVec3f(light->r, light->g, light->b); data_[pxr::HdLightTokens->color] = pxr::GfVec3f(light->r, light->g, light->b);
switch (light->type) { switch (light->type) {
case LA_LOCAL: case LA_LOCAL:
data[pxr::HdLightTokens->radius] = light->area_size / 2; data_[pxr::HdLightTokens->radius] = light->area_size / 2;
break; break;
case LA_SUN: case LA_SUN:
data[pxr::HdLightTokens->angle] = light->sun_angle * 180.0 / M_PI; data_[pxr::HdLightTokens->angle] = light->sun_angle * 180.0 / M_PI;
break; break;
case LA_SPOT: case LA_SPOT:
data[pxr::HdLightTokens->shapingConeAngle] = light->spotsize / 2; data_[pxr::HdLightTokens->shapingConeAngle] = light->spotsize / 2;
data[pxr::HdLightTokens->shapingConeSoftness] = light->spotblend; data_[pxr::HdLightTokens->shapingConeSoftness] = light->spotblend;
data[pxr::UsdLuxTokens->treatAsPoint] = true; data_[pxr::UsdLuxTokens->treatAsPoint] = true;
break; break;
case LA_AREA: case LA_AREA:
switch (light->area_shape) { switch (light->area_shape) {
case LA_AREA_SQUARE: case LA_AREA_SQUARE:
data[pxr::HdLightTokens->width] = light->area_size; data_[pxr::HdLightTokens->width] = light->area_size;
data[pxr::HdLightTokens->height] = light->area_size; data_[pxr::HdLightTokens->height] = light->area_size;
break; break;
case LA_AREA_RECT: case LA_AREA_RECT:
data[pxr::HdLightTokens->width] = light->area_size; data_[pxr::HdLightTokens->width] = light->area_size;
data[pxr::HdLightTokens->height] = light->area_sizey; data_[pxr::HdLightTokens->height] = light->area_sizey;
break; break;
case LA_AREA_DISK: case LA_AREA_DISK:
data[pxr::HdLightTokens->radius] = light->area_size / 2; data_[pxr::HdLightTokens->radius] = light->area_size / 2;
break; break;
case LA_AREA_ELLIPSE: case LA_AREA_ELLIPSE:
data[pxr::HdLightTokens->radius] = (light->area_size + light->area_sizey) / 4; data_[pxr::HdLightTokens->radius] = (light->area_size + light->area_sizey) / 4;
break; break;
default: default:
break; break;
} }
data[pxr::HdLightTokens->normalize] = true; data_[pxr::HdLightTokens->normalize] = true;
break; break;
default: default:
break; break;
} }
p_type = prim_type(light); p_type_ = prim_type(light);
/* TODO: temporary value, it should be delivered through Python UI */ /* TODO: temporary value, it should be delivered through Python UI */
data[pxr::HdLightTokens->exposure] = 1.0f; data_[pxr::HdLightTokens->exposure] = 1.0f;
}
void LightData::insert()
{
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
scene_delegate_->GetRenderIndex().InsertSprim(p_type_, scene_delegate_, p_id_);
}
void LightData::remove()
{
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
scene_delegate_->GetRenderIndex().RemoveSprim(p_type_, p_id_);
}
void LightData::update()
{
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
Light *light = (Light *)((Object *)id_)->data;
if (prim_type(light) != p_type_) {
remove();
init();
insert();
return;
}
pxr::HdDirtyBits bits = pxr::HdLight::Clean;
if (id_->recalc & ID_RECALC_GEOMETRY) {
init();
bits = pxr::HdLight::AllDirty;
}
else if (id_->recalc & ID_RECALC_TRANSFORM) {
bits = pxr::HdLight::DirtyTransform;
}
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id_, bits);
}
pxr::VtValue LightData::get_data(pxr::TfToken const &key) const
{
pxr::VtValue ret;
auto it = data_.find(key);
if (it != data_.end()) {
ret = it->second;
}
else {
std::string n = key.GetString();
if (boost::algorithm::contains(n, "object:visibility:")) {
if (boost::algorithm::ends_with(n, "camera") || boost::algorithm::ends_with(n, "shadow")) {
ret = false;
}
else {
ret = true;
}
}
}
return ret;
}
bool LightData::update_visibility(View3D *view3d)
{
bool ret = ObjectData::update_visibility(view3d);
if (ret) {
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id_,
pxr::HdLight::DirtyParams);
}
return ret;
} }
pxr::TfToken LightData::prim_type(Light *light) pxr::TfToken LightData::prim_type(Light *light)
@ -121,70 +187,4 @@ pxr::TfToken LightData::prim_type(Light *light)
return ret; return ret;
} }
pxr::VtValue LightData::get_data(pxr::TfToken const &key) const
{
pxr::VtValue ret;
auto it = data.find(key);
if (it != data.end()) {
ret = it->second;
}
else {
std::string n = key.GetString();
if (boost::algorithm::contains(n, "object:visibility:")) {
if (boost::algorithm::ends_with(n, "camera") || boost::algorithm::ends_with(n, "shadow")) {
ret = false;
}
else {
ret = true;
}
}
}
return ret;
}
bool LightData::update_visibility(View3D *view3d)
{
bool ret = ObjectData::update_visibility(view3d);
if (ret) {
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id,
pxr::HdLight::DirtyParams);
}
return ret;
}
void LightData::insert()
{
ID_LOG(2, "");
scene_delegate->GetRenderIndex().InsertSprim(p_type, scene_delegate, p_id);
}
void LightData::remove()
{
CLOG_INFO(LOG_BSD, 2, "%s", p_id.GetText());
scene_delegate->GetRenderIndex().RemoveSprim(p_type, p_id);
}
void LightData::update()
{
ID_LOG(2, "");
Light *light = (Light *)((Object *)id)->data;
if (prim_type(light) != p_type) {
remove();
init();
insert();
return;
}
pxr::HdDirtyBits bits = pxr::HdLight::Clean;
if (id->recalc & ID_RECALC_GEOMETRY) {
init();
bits = pxr::HdLight::AllDirty;
}
else if (id->recalc & ID_RECALC_TRANSFORM) {
bits = pxr::HdLight::DirtyTransform;
}
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id, bits);
}
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -21,13 +21,15 @@ class LightData : public ObjectData {
void insert() override; void insert() override;
void remove() override; void remove() override;
void update() override; void update() override;
pxr::VtValue get_data(pxr::TfToken const &key) const override; pxr::VtValue get_data(pxr::TfToken const &key) const override;
bool update_visibility(View3D *view3d) override; bool update_visibility(View3D *view3d) override;
private: private:
std::map<pxr::TfToken, pxr::VtValue> data;
pxr::TfToken p_type;
pxr::TfToken prim_type(Light *light); pxr::TfToken prim_type(Light *light);
std::map<pxr::TfToken, pxr::VtValue> data_;
pxr::TfToken p_type_;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -20,6 +20,13 @@
namespace blender::render::hydra { namespace blender::render::hydra {
MaterialData::MaterialData(BlenderSceneDelegate *scene_delegate, Material *material)
: IdData(scene_delegate, (ID *)material)
{
p_id_ = prim_id(scene_delegate, material);
ID_LOG(2, "");
}
std::unique_ptr<MaterialData> MaterialData::create(BlenderSceneDelegate *scene_delegate, std::unique_ptr<MaterialData> MaterialData::create(BlenderSceneDelegate *scene_delegate,
Material *material) Material *material)
{ {
@ -38,18 +45,11 @@ pxr::SdfPath MaterialData::prim_id(BlenderSceneDelegate *scene_delegate, Materia
return scene_delegate->GetDelegateID().AppendElementString(str); return scene_delegate->GetDelegateID().AppendElementString(str);
} }
MaterialData::MaterialData(BlenderSceneDelegate *scene_delegate, Material *material)
: IdData(scene_delegate, (ID *)material)
{
p_id = prim_id(scene_delegate, material);
ID_LOG(2, "");
}
void MaterialData::init() void MaterialData::init()
{ {
ID_LOG(2, ""); ID_LOG(2, "");
material_network_map = pxr::VtValue(); material_network_map_ = pxr::VtValue();
/* Call of python function hydra.export_mtlx() */ /* Call of python function hydra.export_mtlx() */
@ -62,7 +62,7 @@ void MaterialData::init()
func = PyDict_GetItemString(dict, "export_mtlx"); func = PyDict_GetItemString(dict, "export_mtlx");
PointerRNA materialptr; PointerRNA materialptr;
RNA_pointer_create(NULL, &RNA_Material, id, &materialptr); RNA_pointer_create(NULL, &RNA_Material, id_, &materialptr);
PyObject *material = pyrna_struct_CreatePyObject(&materialptr); PyObject *material = pyrna_struct_CreatePyObject(&materialptr);
result = PyObject_CallFunction(func, "O", material); result = PyObject_CallFunction(func, "O", material);
@ -76,67 +76,68 @@ void MaterialData::init()
Py_DECREF(result); Py_DECREF(result);
} }
else { else {
CLOG_ERROR(LOG_BSD, "Export error for %s", id->name); CLOG_ERROR(LOG_BSD, "Export error for %s", id_->name);
PyErr_Print(); PyErr_Print();
} }
Py_DECREF(module); Py_DECREF(module);
PyGILState_Release(gstate); PyGILState_Release(gstate);
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::insert()
{
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
scene_delegate_->GetRenderIndex().InsertSprim(
pxr::HdPrimTypeTokens->material, scene_delegate_, p_id_);
}
void MaterialData::remove()
{
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
scene_delegate_->GetRenderIndex().RemoveSprim(pxr::HdPrimTypeTokens->material, p_id_);
}
void MaterialData::update()
{
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
init();
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id_,
pxr::HdMaterial::AllDirty);
} }
pxr::VtValue MaterialData::get_data(pxr::TfToken const &key) const pxr::VtValue MaterialData::get_data(pxr::TfToken const &key) const
{ {
pxr::VtValue ret; pxr::VtValue ret;
if (key.GetString() == "MaterialXFilename") { if (key.GetString() == "MaterialXFilename") {
if (!mtlx_path.GetResolvedPath().empty()) { if (!mtlx_path_.GetResolvedPath().empty()) {
ret = mtlx_path; ret = mtlx_path_;
} }
ID_LOG(3, "%s", key.GetText()); ID_LOG(3, "%s", key.GetText());
} }
return ret; return ret;
} }
pxr::VtValue MaterialData::material_resource() pxr::VtValue MaterialData::get_material_resource()
{ {
if (material_network_map.IsEmpty()) { if (material_network_map_.IsEmpty()) {
const std::string &path = mtlx_path.GetResolvedPath(); const std::string &path = mtlx_path_.GetResolvedPath();
if (!path.empty()) { if (!path.empty()) {
pxr::HdRenderDelegate *render_delegate = pxr::HdRenderDelegate *render_delegate =
scene_delegate->GetRenderIndex().GetRenderDelegate(); 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;
HdMtlxConvertToMaterialNetworkMap(path, shader_source_types, render_contexts, &network_map); hdmtlx_convert_to_materialnetworkmap(
path, shader_source_types, render_contexts, &network_map);
material_network_map = network_map; material_network_map_ = network_map;
} }
} }
return material_network_map; return material_network_map_;
}
void MaterialData::insert()
{
ID_LOG(2, "");
scene_delegate->GetRenderIndex().InsertSprim(
pxr::HdPrimTypeTokens->material, scene_delegate, p_id);
}
void MaterialData::remove()
{
CLOG_INFO(LOG_BSD, 2, "%s", p_id.GetText());
scene_delegate->GetRenderIndex().RemoveSprim(pxr::HdPrimTypeTokens->material, p_id);
}
void MaterialData::update()
{
ID_LOG(2, "");
init();
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id,
pxr::HdMaterial::AllDirty);
} }
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -19,24 +19,23 @@ class MaterialData : IdData {
friend MeshData; friend MeshData;
public: public:
MaterialData(BlenderSceneDelegate *scene_delegate, Material *material);
static std::unique_ptr<MaterialData> create(BlenderSceneDelegate *scene_delegate, static std::unique_ptr<MaterialData> create(BlenderSceneDelegate *scene_delegate,
Material *material); Material *material);
static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate, Material *material); static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate, Material *material);
MaterialData(BlenderSceneDelegate *scene_delegate, Material *material);
void init() override; void init() override;
void insert() override; void insert() override;
void remove() override; void remove() override;
void update() override; void update() override;
pxr::VtValue get_data(pxr::TfToken const &key) const override;
pxr::VtValue material_resource(); pxr::VtValue get_data(pxr::TfToken const &key) const override;
void export_mtlx(); pxr::VtValue get_material_resource();
private: private:
pxr::SdfAssetPath mtlx_path; pxr::SdfAssetPath mtlx_path_;
pxr::VtValue material_network_map; pxr::VtValue material_network_map_;
}; };
using MaterialDataMap = using MaterialDataMap =

View File

@ -16,25 +16,102 @@
namespace blender::render::hydra { namespace blender::render::hydra {
MeshData::MeshData(BlenderSceneDelegate *scene_delegate, Object *object) MeshData::MeshData(BlenderSceneDelegate *scene_delegate, Object *object)
: ObjectData(scene_delegate, object), mat_data(nullptr) : ObjectData(scene_delegate, object), mat_data_(nullptr)
{ {
ID_LOG(2, ""); ID_LOG(2, "");
} }
void MeshData::init()
{
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
Object *object = (Object *)id_;
if (object->type == OB_MESH && object->mode == OB_MODE_OBJECT &&
BLI_listbase_is_empty(&object->modifiers)) {
write_mesh((Mesh *)object->data);
}
else {
Mesh *mesh = BKE_object_to_mesh(nullptr, object, false);
if (mesh) {
write_mesh(mesh);
}
BKE_object_to_mesh_clear(object);
}
write_material();
}
void MeshData::insert()
{
if (face_vertex_counts_.empty()) {
return;
}
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
scene_delegate_->GetRenderIndex().InsertRprim(
pxr::HdPrimTypeTokens->mesh, scene_delegate_, p_id_);
}
void MeshData::remove()
{
if (!scene_delegate_->GetRenderIndex().HasRprim(p_id_)) {
return;
}
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
scene_delegate_->GetRenderIndex().RemoveRprim(p_id_);
}
void MeshData::update()
{
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
Object *object = (Object *)id_;
if ((id_->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
init();
bits = pxr::HdChangeTracker::AllDirty;
}
else {
if (id_->recalc & ID_RECALC_SHADING) {
write_material();
bits |= pxr::HdChangeTracker::DirtyMaterialId;
}
if (id_->recalc & ID_RECALC_TRANSFORM) {
bits |= pxr::HdChangeTracker::DirtyTransform;
}
}
if (bits == pxr::HdChangeTracker::Clean) {
return;
}
if (!scene_delegate_->GetRenderIndex().HasRprim(p_id_)) {
insert();
return;
}
if (face_vertex_counts_.empty()) {
/* Remove prim without faces */
remove();
return;
}
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(p_id_, bits);
}
pxr::VtValue MeshData::get_data(pxr::TfToken const &key) const pxr::VtValue MeshData::get_data(pxr::TfToken const &key) const
{ {
pxr::VtValue ret; pxr::VtValue ret;
if (key == pxr::HdTokens->points) { if (key == pxr::HdTokens->points) {
ret = vertices; ret = vertices_;
} }
else if (key == pxr::HdTokens->normals) { else if (key == pxr::HdTokens->normals) {
ret = normals; ret = normals_;
} }
else if (key == pxr::HdPrimvarRoleTokens->textureCoordinate) { else if (key == pxr::HdPrimvarRoleTokens->textureCoordinate) {
ret = uvs; ret = uvs_;
} }
else if (key == pxr::HdInstancerTokens->instanceTransform) { else if (key == pxr::HdInstancerTokens->instanceTransform) {
ret = instances; ret = instances_;
} }
return ret; return ret;
} }
@ -43,8 +120,8 @@ bool MeshData::update_visibility(View3D *view3d)
{ {
bool ret = ObjectData::update_visibility(view3d); bool ret = ObjectData::update_visibility(view3d);
if (ret) { if (ret) {
scene_delegate->GetRenderIndex().GetChangeTracker().MarkRprimDirty( scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
p_id, pxr::HdChangeTracker::DirtyVisibility); p_id_, pxr::HdChangeTracker::DirtyVisibility);
} }
return ret; return ret;
} }
@ -53,24 +130,24 @@ pxr::HdMeshTopology MeshData::mesh_topology()
{ {
return pxr::HdMeshTopology(pxr::PxOsdOpenSubdivTokens->none, return pxr::HdMeshTopology(pxr::PxOsdOpenSubdivTokens->none,
pxr::HdTokens->rightHanded, pxr::HdTokens->rightHanded,
face_vertex_counts, face_vertex_counts_,
face_vertex_indices); face_vertex_indices_);
} }
pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(pxr::HdInterpolation interpolation) pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(pxr::HdInterpolation interpolation)
{ {
pxr::HdPrimvarDescriptorVector primvars; pxr::HdPrimvarDescriptorVector primvars;
if (interpolation == pxr::HdInterpolationVertex) { if (interpolation == pxr::HdInterpolationVertex) {
if (!vertices.empty()) { if (!vertices_.empty()) {
primvars.emplace_back(pxr::HdTokens->points, interpolation, pxr::HdPrimvarRoleTokens->point); primvars.emplace_back(pxr::HdTokens->points, interpolation, pxr::HdPrimvarRoleTokens->point);
} }
} }
else if (interpolation == pxr::HdInterpolationFaceVarying) { else if (interpolation == pxr::HdInterpolationFaceVarying) {
if (!normals.empty()) { if (!normals_.empty()) {
primvars.emplace_back( primvars.emplace_back(
pxr::HdTokens->normals, interpolation, pxr::HdPrimvarRoleTokens->normal); pxr::HdTokens->normals, interpolation, pxr::HdPrimvarRoleTokens->normal);
} }
if (!uvs.empty()) { if (!uvs_.empty()) {
primvars.emplace_back(pxr::HdPrimvarRoleTokens->textureCoordinate, primvars.emplace_back(pxr::HdPrimvarRoleTokens->textureCoordinate,
interpolation, interpolation,
pxr::HdPrimvarRoleTokens->textureCoordinate); pxr::HdPrimvarRoleTokens->textureCoordinate);
@ -81,19 +158,19 @@ pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(pxr::HdInterpolatio
pxr::SdfPath MeshData::material_id() pxr::SdfPath MeshData::material_id()
{ {
if (!mat_data) { if (!mat_data_) {
return pxr::SdfPath(); return pxr::SdfPath();
} }
return mat_data->p_id; return mat_data_->p_id_;
} }
void MeshData::set_mesh(Mesh *mesh) void MeshData::write_mesh(Mesh *mesh)
{ {
face_vertex_counts.clear(); face_vertex_counts_.clear();
face_vertex_indices.clear(); face_vertex_indices_.clear();
vertices.clear(); vertices_.clear();
normals.clear(); normals_.clear();
uvs.clear(); uvs_.clear();
BKE_mesh_calc_normals_split(mesh); BKE_mesh_calc_normals_split(mesh);
int tris_len = BKE_mesh_runtime_looptri_len(mesh); int tris_len = BKE_mesh_runtime_looptri_len(mesh);
@ -104,141 +181,74 @@ void MeshData::set_mesh(Mesh *mesh)
blender::Span<MLoopTri> loopTris = mesh->looptris(); blender::Span<MLoopTri> loopTris = mesh->looptris();
/* face_vertex_counts */ /* face_vertex_counts */
face_vertex_counts = pxr::VtIntArray(tris_len, 3); face_vertex_counts_ = pxr::VtIntArray(tris_len, 3);
/* face_vertex_indices */ /* face_vertex_indices */
blender::Span<int> corner_verts = mesh->corner_verts(); blender::Span<int> corner_verts = mesh->corner_verts();
face_vertex_indices.reserve(loopTris.size() * 3); face_vertex_indices_.reserve(loopTris.size() * 3);
for (MLoopTri lt : loopTris) { for (MLoopTri lt : loopTris) {
face_vertex_indices.push_back(corner_verts[lt.tri[0]]); face_vertex_indices_.push_back(corner_verts[lt.tri[0]]);
face_vertex_indices.push_back(corner_verts[lt.tri[1]]); face_vertex_indices_.push_back(corner_verts[lt.tri[1]]);
face_vertex_indices.push_back(corner_verts[lt.tri[2]]); face_vertex_indices_.push_back(corner_verts[lt.tri[2]]);
} }
/* vertices */ /* vertices */
vertices.reserve(mesh->totvert); vertices_.reserve(mesh->totvert);
blender::Span<blender::float3> verts = mesh->vert_positions(); blender::Span<blender::float3> verts = mesh->vert_positions();
for (blender::float3 v : verts) { for (blender::float3 v : verts) {
vertices.push_back(pxr::GfVec3f(v.x, v.y, v.z)); vertices_.push_back(pxr::GfVec3f(v.x, v.y, v.z));
} }
/* normals */ write_normals(mesh);
const float(*lnors)[3] = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL); write_uv_maps(mesh);
if (lnors) {
normals.reserve(loopTris.size() * 3);
for (MLoopTri lt : loopTris) {
normals.push_back(pxr::GfVec3f(lnors[lt.tri[0]]));
normals.push_back(pxr::GfVec3f(lnors[lt.tri[1]]));
normals.push_back(pxr::GfVec3f(lnors[lt.tri[2]]));
}
}
/* uvs*/
const float(*luvs)[2] = (float(*)[2])CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2);
if (luvs) {
uvs.reserve(loopTris.size() * 3);
for (MLoopTri lt : loopTris) {
uvs.push_back(pxr::GfVec2f(luvs[lt.tri[0]]));
uvs.push_back(pxr::GfVec2f(luvs[lt.tri[1]]));
uvs.push_back(pxr::GfVec2f(luvs[lt.tri[2]]));
}
}
} }
void MeshData::set_material() void MeshData::write_material()
{ {
Object *object = (Object *)id; Object *object = (Object *)id_;
Material *mat = nullptr; Material *mat = nullptr;
if (BKE_object_material_count_eval(object) > 0) { if (BKE_object_material_count_eval(object) > 0) {
mat = BKE_object_material_get_eval(object, object->actcol); mat = BKE_object_material_get_eval(object, object->actcol);
} }
if (!mat) { if (!mat) {
mat_data = nullptr; mat_data_ = nullptr;
return; return;
} }
pxr::SdfPath id = MaterialData::prim_id(scene_delegate, mat); pxr::SdfPath id = MaterialData::prim_id(scene_delegate_, mat);
mat_data = scene_delegate->material_data(id); mat_data_ = scene_delegate_->material_data(id);
if (!mat_data) { if (!mat_data_) {
scene_delegate->materials[id] = MaterialData::create(scene_delegate, mat); scene_delegate_->materials_[id] = MaterialData::create(scene_delegate_, mat);
mat_data = scene_delegate->material_data(id); mat_data_ = scene_delegate_->material_data(id);
} }
} }
void MeshData::init() void MeshData::write_uv_maps(Mesh *mesh)
{ {
ID_LOG(2, ""); blender::Span<MLoopTri> loopTris = mesh->looptris();
const float(*luvs)[2] = (float(*)[2])CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2);
Object *object = (Object *)id; if (luvs) {
if (object->type == OB_MESH && object->mode == OB_MODE_OBJECT && uvs_.reserve(loopTris.size() * 3);
BLI_listbase_is_empty(&object->modifiers)) { for (MLoopTri lt : loopTris) {
set_mesh((Mesh *)object->data); uvs_.push_back(pxr::GfVec2f(luvs[lt.tri[0]]));
uvs_.push_back(pxr::GfVec2f(luvs[lt.tri[1]]));
uvs_.push_back(pxr::GfVec2f(luvs[lt.tri[2]]));
} }
else {
Mesh *mesh = BKE_object_to_mesh(nullptr, object, false);
if (mesh) {
set_mesh(mesh);
} }
BKE_object_to_mesh_clear(object);
}
set_material();
} }
void MeshData::insert() void MeshData::write_normals(Mesh *mesh)
{ {
if (face_vertex_counts.empty()) { blender::Span<MLoopTri> loopTris = mesh->looptris();
return; const float(*lnors)[3] = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL);
} if (lnors) {
normals_.reserve(loopTris.size() * 3);
ID_LOG(2, ""); for (MLoopTri lt : loopTris) {
scene_delegate->GetRenderIndex().InsertRprim(pxr::HdPrimTypeTokens->mesh, scene_delegate, p_id); normals_.push_back(pxr::GfVec3f(lnors[lt.tri[0]]));
} normals_.push_back(pxr::GfVec3f(lnors[lt.tri[1]]));
normals_.push_back(pxr::GfVec3f(lnors[lt.tri[2]]));
void MeshData::remove()
{
if (!scene_delegate->GetRenderIndex().HasRprim(p_id)) {
return;
}
CLOG_INFO(LOG_BSD, 2, "%s", p_id.GetText());
scene_delegate->GetRenderIndex().RemoveRprim(p_id);
}
void MeshData::update()
{
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
Object *object = (Object *)id;
if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
init();
bits = pxr::HdChangeTracker::AllDirty;
}
else {
if (id->recalc & ID_RECALC_SHADING) {
set_material();
bits |= pxr::HdChangeTracker::DirtyMaterialId;
}
if (id->recalc & ID_RECALC_TRANSFORM) {
bits |= pxr::HdChangeTracker::DirtyTransform;
} }
} }
if (bits == pxr::HdChangeTracker::Clean) {
return;
}
if (!scene_delegate->GetRenderIndex().HasRprim(p_id)) {
insert();
return;
}
if (face_vertex_counts.empty()) {
/* Remove prim without faces */
remove();
return;
}
ID_LOG(2, "");
scene_delegate->GetRenderIndex().GetChangeTracker().MarkRprimDirty(p_id, bits);
} }
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -21,6 +21,7 @@ class MeshData : public ObjectData {
void insert() override; void insert() override;
void remove() override; void remove() override;
void update() override; void update() override;
pxr::VtValue get_data(pxr::TfToken const &key) const override; pxr::VtValue get_data(pxr::TfToken const &key) const override;
bool update_visibility(View3D *view3d) override; bool update_visibility(View3D *view3d) override;
@ -29,18 +30,19 @@ class MeshData : public ObjectData {
pxr::SdfPath material_id(); pxr::SdfPath material_id();
protected: protected:
void set_mesh(Mesh *mesh); void write_mesh(Mesh *mesh);
void set_material(); void write_material();
void write_uv_maps(Mesh *mesh);
void write_normals(Mesh *mesh);
pxr::VtIntArray face_vertex_counts; pxr::VtIntArray face_vertex_counts_;
pxr::VtIntArray face_vertex_indices; pxr::VtIntArray face_vertex_indices_;
pxr::VtVec3fArray vertices; pxr::VtVec3fArray vertices_;
pxr::VtVec3fArray normals; pxr::VtVec2fArray uvs_;
pxr::VtVec2fArray uvs; pxr::VtVec3fArray normals_;
pxr::VtMatrix4dArray instances_;
pxr::VtMatrix4dArray instances; MaterialData *mat_data_;
MaterialData *mat_data;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -22,7 +22,7 @@
namespace mx = MaterialX; namespace mx = MaterialX;
void HdMtlxConvertToMaterialNetworkMap(std::string const &mtlx_path, void hdmtlx_convert_to_materialnetworkmap(std::string const &mtlx_path,
pxr::TfTokenVector const &shader_source_types, pxr::TfTokenVector const &shader_source_types,
pxr::TfTokenVector const &render_contexts, pxr::TfTokenVector const &render_contexts,
pxr::HdMaterialNetworkMap *out) pxr::HdMaterialNetworkMap *out)

View File

@ -10,7 +10,7 @@
struct pxr::HdMaterialNetworkMap; struct pxr::HdMaterialNetworkMap;
void HdMtlxConvertToMaterialNetworkMap(std::string const &mtlx_path, void hdmtlx_convert_to_materialnetworkmap(std::string const &mtlx_path,
pxr::TfTokenVector const &shader_source_types, pxr::TfTokenVector const &shader_source_types,
pxr::TfTokenVector const &render_contexts, pxr::TfTokenVector const &render_contexts,
pxr::HdMaterialNetworkMap *out); pxr::HdMaterialNetworkMap *out);

View File

@ -11,7 +11,13 @@
namespace blender::render::hydra { namespace blender::render::hydra {
bool ObjectData::supported(Object *object) ObjectData::ObjectData(BlenderSceneDelegate *scene_delegate, Object *object)
: IdData(scene_delegate, (ID *)object), visible(true)
{
p_id_ = prim_id(scene_delegate, object);
}
bool ObjectData::is_supported(Object *object)
{ {
switch (object->type) { switch (object->type) {
case OB_MESH: case OB_MESH:
@ -65,15 +71,9 @@ pxr::SdfPath ObjectData::prim_id(BlenderSceneDelegate *scene_delegate, Object *o
return scene_delegate->GetDelegateID().AppendElementString(str); return scene_delegate->GetDelegateID().AppendElementString(str);
} }
ObjectData::ObjectData(BlenderSceneDelegate *scene_delegate, Object *object)
: IdData(scene_delegate, (ID *)object), visible(true)
{
p_id = prim_id(scene_delegate, object);
}
pxr::GfMatrix4d ObjectData::transform() pxr::GfMatrix4d ObjectData::transform()
{ {
return gf_matrix_from_transform(((Object *)id)->object_to_world); return gf_matrix_from_transform(((Object *)id_)->object_to_world);
} }
bool ObjectData::update_visibility(View3D *view3d) bool ObjectData::update_visibility(View3D *view3d)
@ -83,7 +83,7 @@ bool ObjectData::update_visibility(View3D *view3d)
} }
bool prev_visible = visible; bool prev_visible = visible;
visible = BKE_object_is_visible_in_viewport(view3d, (Object *)id); visible = BKE_object_is_visible_in_viewport(view3d, (Object *)id_);
bool ret = visible != prev_visible; bool ret = visible != prev_visible;
if (ret) { if (ret) {
ID_LOG(2, ""); ID_LOG(2, "");

View File

@ -16,12 +16,12 @@ namespace blender::render::hydra {
class ObjectData : public IdData { class ObjectData : public IdData {
public: public:
static bool supported(Object *object); ObjectData(BlenderSceneDelegate *scene_delegate, Object *object);
static bool is_supported(Object *object);
static std::unique_ptr<ObjectData> create(BlenderSceneDelegate *scene_delegate, Object *object); static std::unique_ptr<ObjectData> create(BlenderSceneDelegate *scene_delegate, Object *object);
static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate, Object *object); static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate, Object *object);
ObjectData(BlenderSceneDelegate *scene_delegate, Object *object);
virtual pxr::GfMatrix4d transform(); virtual pxr::GfMatrix4d transform();
virtual bool update_visibility(View3D *view3d); virtual bool update_visibility(View3D *view3d);

View File

@ -28,6 +28,13 @@
namespace blender::render::hydra { namespace blender::render::hydra {
WorldData::WorldData(BlenderSceneDelegate *scene_delegate, World *world, bContext *context)
: IdData(scene_delegate, (ID *)world), context_(context)
{
p_id_ = prim_id(scene_delegate);
ID_LOG(2, "");
}
std::unique_ptr<WorldData> WorldData::create(BlenderSceneDelegate *scene_delegate, std::unique_ptr<WorldData> WorldData::create(BlenderSceneDelegate *scene_delegate,
World *world, World *world,
bContext *context) bContext *context)
@ -43,21 +50,14 @@ pxr::SdfPath WorldData::prim_id(BlenderSceneDelegate *scene_delegate)
return scene_delegate->GetDelegateID().AppendElementString("World"); return scene_delegate->GetDelegateID().AppendElementString("World");
} }
WorldData::WorldData(BlenderSceneDelegate *scene_delegate, World *world, bContext *context)
: IdData(scene_delegate, (ID *)world), context(context)
{
p_id = prim_id(scene_delegate);
ID_LOG(2, "");
}
void WorldData::init() void WorldData::init()
{ {
ID_LOG(2, ""); ID_LOG(2, "");
World *world = (World *)id; World *world = (World *)id_;
data.clear(); data_.clear();
data[pxr::UsdLuxTokens->orientToStageUpAxis] = true; data_[pxr::UsdLuxTokens->orientToStageUpAxis] = true;
if (world->use_nodes) { if (world->use_nodes) {
/* TODO: Create nodes parsing system */ /* TODO: Create nodes parsing system */
@ -90,9 +90,9 @@ void WorldData::init()
float const *strength = strength_input.default_value_typed<float>(); float const *strength = strength_input.default_value_typed<float>();
float const *color = color_input.default_value_typed<float>(); float const *color = color_input.default_value_typed<float>();
data[pxr::HdLightTokens->intensity] = strength[1]; data_[pxr::HdLightTokens->intensity] = strength[1];
data[pxr::HdLightTokens->exposure] = 1.0f; data_[pxr::HdLightTokens->exposure] = 1.0f;
data[pxr::HdLightTokens->color] = pxr::GfVec3f(color[0], color[1], color[2]); data_[pxr::HdLightTokens->color] = pxr::GfVec3f(color[0], color[1], color[2]);
if (!color_input.directly_linked_links().is_empty()) { if (!color_input.directly_linked_links().is_empty()) {
bNode *color_input_node = color_input.directly_linked_links()[0]->fromnode; bNode *color_input_node = color_input.directly_linked_links()[0]->fromnode;
@ -101,8 +101,8 @@ void WorldData::init()
Image *image = (Image *)color_input_node->id; Image *image = (Image *)color_input_node->id;
if (image) { if (image) {
Main *bmain = CTX_data_main(context); Main *bmain = CTX_data_main(context_);
Scene *scene = CTX_data_scene(context); Scene *scene = CTX_data_scene(context_);
ReportList reports; ReportList reports;
ImageSaveOptions opts; ImageSaveOptions opts;
@ -110,26 +110,53 @@ void WorldData::init()
std::string image_path = cache_image(bmain, scene, image, &tex->iuser, &opts, &reports); std::string image_path = cache_image(bmain, scene, image, &tex->iuser, &opts, &reports);
if (!image_path.empty()) { if (!image_path.empty()) {
data[pxr::HdLightTokens->textureFile] = pxr::SdfAssetPath(image_path, image_path); data_[pxr::HdLightTokens->textureFile] = pxr::SdfAssetPath(image_path, image_path);
} }
} }
} }
} }
} }
else { else {
data[pxr::HdLightTokens->intensity] = 1.0f; data_[pxr::HdLightTokens->intensity] = 1.0f;
data[pxr::HdLightTokens->exposure] = world->exposure; data_[pxr::HdLightTokens->exposure] = world->exposure;
data[pxr::HdLightTokens->color] = pxr::GfVec3f(world->horr, world->horg, world->horb); data_[pxr::HdLightTokens->color] = pxr::GfVec3f(world->horr, world->horg, world->horb);
} }
} }
void WorldData::insert()
{
ID_LOG(2, "");
scene_delegate_->GetRenderIndex().InsertSprim(
pxr::HdPrimTypeTokens->domeLight, scene_delegate_, p_id_);
}
void WorldData::remove()
{
CLOG_INFO(LOG_BSD, 2, "%s", id_->name);
scene_delegate_->GetRenderIndex().RemoveSprim(pxr::HdPrimTypeTokens->domeLight, p_id_);
}
void WorldData::update()
{
ID_LOG(2, "");
init();
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id_,
pxr::HdLight::AllDirty);
}
void WorldData::update(World *world)
{
id_ = (ID *)world;
update();
}
pxr::GfMatrix4d WorldData::transform() pxr::GfMatrix4d WorldData::transform()
{ {
pxr::GfMatrix4d transform = pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -90), pxr::GfMatrix4d transform = pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -90),
pxr::GfVec3d()); pxr::GfVec3d());
/* TODO : do this check via RenderSettings*/ /* TODO : do this check via RenderSettings*/
if (scene_delegate->GetRenderIndex().GetRenderDelegate()->GetRendererDisplayName() == "RPR") { if (scene_delegate_->GetRenderIndex().GetRenderDelegate()->GetRendererDisplayName() == "RPR") {
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),
@ -141,37 +168,11 @@ pxr::GfMatrix4d WorldData::transform()
pxr::VtValue WorldData::get_data(pxr::TfToken const &key) const pxr::VtValue WorldData::get_data(pxr::TfToken const &key) const
{ {
pxr::VtValue ret; pxr::VtValue ret;
auto it = data.find(key); auto it = data_.find(key);
if (it != data.end()) { if (it != data_.end()) {
ret = it->second; ret = it->second;
} }
return ret; return ret;
} }
void WorldData::insert()
{
ID_LOG(2, "");
scene_delegate->GetRenderIndex().InsertSprim(
pxr::HdPrimTypeTokens->domeLight, scene_delegate, p_id);
}
void WorldData::remove()
{
CLOG_INFO(LOG_BSD, 2, "%s", p_id.GetText());
scene_delegate->GetRenderIndex().RemoveSprim(pxr::HdPrimTypeTokens->domeLight, p_id);
}
void WorldData::update()
{
ID_LOG(2, "");
init();
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id, pxr::HdLight::AllDirty);
}
void WorldData::update(World *world)
{
id = (ID *)world;
update();
}
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -20,13 +20,13 @@ namespace blender::render::hydra {
class WorldData : public IdData { class WorldData : public IdData {
public: public:
WorldData(BlenderSceneDelegate *scene_delegate, World *world, bContext *context);
static std::unique_ptr<WorldData> create(BlenderSceneDelegate *scene_delegate, static std::unique_ptr<WorldData> create(BlenderSceneDelegate *scene_delegate,
World *world, World *world,
bContext *context); bContext *context);
static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate); static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate);
WorldData(BlenderSceneDelegate *scene_delegate, World *world, bContext *context);
void init() override; void init() override;
void insert() override; void insert() override;
void remove() override; void remove() override;
@ -34,12 +34,11 @@ class WorldData : public IdData {
void update(World *world); void update(World *world);
pxr::GfMatrix4d transform(); pxr::GfMatrix4d transform();
pxr::VtValue get_data(pxr::TfToken const &key) const override; pxr::VtValue get_data(pxr::TfToken const &key) const override;
private: private:
std::map<pxr::TfToken, pxr::VtValue> data; std::map<pxr::TfToken, pxr::VtValue> data_;
bContext *context; bContext *context_;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -27,13 +27,13 @@ pxr::HdTaskSharedPtr SimpleLightTaskDelegate::get_task()
void SimpleLightTaskDelegate::set_camera_path(pxr::SdfPath const &camera_path) void SimpleLightTaskDelegate::set_camera_path(pxr::SdfPath const &camera_path)
{ {
task_params.cameraPath = camera_path; task_params_.cameraPath = camera_path;
} }
pxr::VtValue SimpleLightTaskDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key) pxr::VtValue SimpleLightTaskDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
{ {
if (key == pxr::HdTokens->params) { if (key == pxr::HdTokens->params) {
return pxr::VtValue(task_params); return pxr::VtValue(task_params_);
} }
return pxr::VtValue(); return pxr::VtValue();
} }

View File

@ -18,10 +18,11 @@ class SimpleLightTaskDelegate : public pxr::HdSceneDelegate {
pxr::HdTaskSharedPtr get_task(); pxr::HdTaskSharedPtr get_task();
void set_camera_path(pxr::SdfPath const &); void set_camera_path(pxr::SdfPath const &);
/* Delegate methods */
pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override; pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override;
private: private:
pxr::HdxSimpleLightTaskParams task_params; pxr::HdxSimpleLightTaskParams task_params_;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -5,15 +5,17 @@
#include <pxr/imaging/glf/drawTarget.h> #include <pxr/imaging/glf/drawTarget.h>
#include <pxr/usd/usdGeom/camera.h> #include <pxr/usd/usdGeom/camera.h>
// clang-format off
#include "DNA_camera_types.h" #include "DNA_camera_types.h"
#include "DNA_screen_types.h" #include "DNA_screen_types.h"
#include "DNA_vec_types.h" /* this include must be before BKE_camera.h due to "rctf" type */ #include "DNA_vec_types.h" /* this include must be before BKE_camera.h due to "rctf" type */
#include "BKE_camera.h" #include "BKE_camera.h"
#include "BLI_math_matrix.h" #include "BLI_math_matrix.h"
#include "DEG_depsgraph_query.h" #include "DEG_depsgraph_query.h"
#include "GPU_matrix.h" #include "GPU_matrix.h"
// clang-format on
#include "camera.h" #include "camera.h"
#include "utils.h" #include "utils.h"
@ -47,7 +49,7 @@ ViewSettings::ViewSettings(bContext *context) : camera_data(context)
Scene *scene = CTX_data_scene(context); Scene *scene = CTX_data_scene(context);
// getting render border /* Getting render border. */
int x1 = 0, y1 = 0; int x1 = 0, y1 = 0;
int x2 = screen_width, y2 = screen_height; int x2 = screen_width, y2 = screen_height;
@ -73,7 +75,7 @@ ViewSettings::ViewSettings(bContext *context) : camera_data(context)
} }
} }
// getting camera view region /* Getting camera view region. */
float x1_f = std::min( float x1_f = std::min(
{screen_points[0][0], screen_points[1][0], screen_points[2][0], screen_points[3][0]}); {screen_points[0][0], screen_points[1][0], screen_points[2][0], screen_points[3][0]});
float x2_f = std::max( float x2_f = std::max(
@ -83,7 +85,7 @@ ViewSettings::ViewSettings(bContext *context) : camera_data(context)
float y2_f = std::max( float y2_f = std::max(
{screen_points[0][1], screen_points[1][1], screen_points[2][1], screen_points[3][1]}); {screen_points[0][1], screen_points[1][1], screen_points[2][1], screen_points[3][1]});
// adjusting region to border /* Adjusting region to border. */
float x = x1_f, y = y1_f; float x = x1_f, y = y1_f;
float dx = x2_f - x1_f, dy = y2_f - y1_f; float dx = x2_f - x1_f, dy = y2_f - y1_f;
@ -92,7 +94,7 @@ ViewSettings::ViewSettings(bContext *context) : camera_data(context)
y1 = y + scene->r.border.ymin * dy; y1 = y + scene->r.border.ymin * dy;
y2 = y + scene->r.border.ymax * dy; y2 = y + scene->r.border.ymax * dy;
// adjusting to region screen resolution /* Adjusting to region screen resolution. */
x1 = std::max(std::min(x1, screen_width), 0); x1 = std::max(std::min(x1, screen_width), 0);
x2 = std::max(std::min(x2, screen_width), 0); x2 = std::max(std::min(x2, screen_width), 0);
y1 = std::max(std::min(y1, screen_height), 0); y1 = std::max(std::min(y1, screen_height), 0);
@ -132,7 +134,7 @@ pxr::GfCamera ViewSettings::gf_camera()
(float)border[3] / screen_height)); (float)border[3] / screen_height));
} }
DrawTexture::DrawTexture() : texture(nullptr), width(0), height(0), channels(4) DrawTexture::DrawTexture() : texture_(nullptr), width_(0), height_(0), channels_(4)
{ {
float coords[8] = {0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0}; float coords[8] = {0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0};
@ -144,92 +146,97 @@ DrawTexture::DrawTexture() : texture(nullptr), width(0), height(0), channels(4)
GPU_vertbuf_attr_fill(vbo, 0, coords); GPU_vertbuf_attr_fill(vbo, 0, coords);
GPU_vertbuf_attr_fill(vbo, 1, coords); GPU_vertbuf_attr_fill(vbo, 1, coords);
batch = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, nullptr, GPU_BATCH_OWNS_VBO); batch_ = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, nullptr, GPU_BATCH_OWNS_VBO);
} }
DrawTexture::~DrawTexture() DrawTexture::~DrawTexture()
{ {
if (texture) { if (texture_) {
free(); free();
} }
GPU_batch_discard(batch); GPU_batch_discard(batch_);
} }
void DrawTexture::set_buffer(pxr::HdRenderBuffer *buffer) void DrawTexture::set_buffer(pxr::HdRenderBuffer *buffer)
{ {
if (!texture) { if (!texture_) {
create(buffer); create(buffer);
return; return;
} }
if (width != buffer->GetWidth() || height != buffer->GetHeight()) { if (width_ != buffer->GetWidth() || height_ != buffer->GetHeight()) {
free(); free();
create(buffer); create(buffer);
return; return;
} }
void *data = buffer->Map(); void *data = buffer->Map();
GPU_texture_update(texture, GPU_DATA_FLOAT, data); GPU_texture_update(texture_, GPU_DATA_FLOAT, data);
buffer->Unmap(); buffer->Unmap();
} }
void DrawTexture::draw(GPUShader *shader, float x, float y)
{
int slot = GPU_shader_get_sampler_binding(shader, "image");
GPU_texture_bind(texture_, slot);
GPU_shader_uniform_1i(shader, "image", slot);
GPU_matrix_push();
GPU_matrix_translate_2f(x, y);
GPU_matrix_scale_2f(width_, height_);
GPU_batch_set_shader(batch_, shader);
GPU_batch_draw(batch_);
GPU_matrix_pop();
}
void DrawTexture::create(pxr::HdRenderBuffer *buffer) void DrawTexture::create(pxr::HdRenderBuffer *buffer)
{ {
width = buffer->GetWidth(); width_ = buffer->GetWidth();
height = buffer->GetHeight(); height_ = buffer->GetHeight();
channels = pxr::HdGetComponentCount(buffer->GetFormat()); channels_ = pxr::HdGetComponentCount(buffer->GetFormat());
void *data = buffer->Map(); void *data = buffer->Map();
texture = GPU_texture_create_2d("texHydraRenderViewport", texture_ = GPU_texture_create_2d("tex_hydra_render_viewport",
width, width_,
height, height_,
1, 1,
GPU_RGBA16F, GPU_RGBA16F,
GPU_TEXTURE_USAGE_GENERAL, GPU_TEXTURE_USAGE_GENERAL,
(float *)data); (float *)data);
buffer->Unmap(); buffer->Unmap();
GPU_texture_filter_mode(texture, true); GPU_texture_filter_mode(texture_, true);
GPU_texture_mipmap_mode(texture, true, true); GPU_texture_mipmap_mode(texture_, true, true);
} }
void DrawTexture::free() void DrawTexture::free()
{ {
GPU_texture_free(texture); GPU_texture_free(texture_);
texture = nullptr; texture_ = nullptr;
}
void DrawTexture::draw(GPUShader *shader, float x, float y)
{
int slot = GPU_shader_get_sampler_binding(shader, "image");
GPU_texture_bind(texture, slot);
GPU_shader_uniform_1i(shader, "image", slot);
GPU_matrix_push();
GPU_matrix_translate_2f(x, y);
GPU_matrix_scale_2f(width, height);
GPU_batch_set_shader(batch, shader);
GPU_batch_draw(batch);
GPU_matrix_pop();
} }
void ViewportEngine::sync(Depsgraph *depsgraph, void ViewportEngine::sync(Depsgraph *depsgraph,
bContext *context, bContext *context,
pxr::HdRenderSettingsMap &render_settings) pxr::HdRenderSettingsMap &render_settings)
{ {
if (!scene_delegate) { if (!scene_delegate_) {
scene_delegate = std::make_unique<BlenderSceneDelegate>( scene_delegate_ = std::make_unique<BlenderSceneDelegate>(
render_index.get(), render_index_.get(),
pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"), pxr::SdfPath::AbsoluteRootPath().AppendElementString("scene"),
BlenderSceneDelegate::EngineType::VIEWPORT); BlenderSceneDelegate::EngineType::VIEWPORT);
} }
scene_delegate->populate(depsgraph, context); scene_delegate_->populate(depsgraph, context);
for (auto const &setting : render_settings) { for (auto const &setting : render_settings) {
render_delegate->SetRenderSetting(setting.first, setting.second); render_delegate_->SetRenderSetting(setting.first, setting.second);
} }
} }
void ViewportEngine::render(Depsgraph *depsgraph)
{
/* Empty function */
}
void ViewportEngine::render(Depsgraph *depsgraph, bContext *context) void ViewportEngine::render(Depsgraph *depsgraph, bContext *context)
{ {
ViewSettings view_settings(context); ViewSettings view_settings(context);
@ -238,41 +245,41 @@ void ViewportEngine::render(Depsgraph *depsgraph, bContext *context)
}; };
pxr::GfCamera gf_camera = view_settings.gf_camera(); pxr::GfCamera gf_camera = view_settings.gf_camera();
free_camera_delegate->SetCamera(gf_camera); free_camera_delegate_->SetCamera(gf_camera);
render_task_delegate->set_camera_and_viewport(free_camera_delegate->GetCameraId(), render_task_delegate_->set_camera_and_viewport(free_camera_delegate_->GetCameraId(),
pxr::GfVec4d(view_settings.border[0], pxr::GfVec4d(view_settings.border[0],
view_settings.border[1], view_settings.border[1],
view_settings.border[2], view_settings.border[2],
view_settings.border[3])); view_settings.border[3]));
if (simple_light_task_delegate) { if (simple_light_task_delegate_) {
simple_light_task_delegate->set_camera_path(free_camera_delegate->GetCameraId()); simple_light_task_delegate_->set_camera_path(free_camera_delegate_->GetCameraId());
} }
if ((bl_engine->type->flag & RE_USE_GPU_CONTEXT) == 0) { if ((bl_engine_->type->flag & RE_USE_GPU_CONTEXT) == 0) {
render_task_delegate->set_renderer_aov(pxr::HdAovTokens->color); render_task_delegate_->set_renderer_aov(pxr::HdAovTokens->color);
} }
if (renderer_percent_done() == 0.0f) { if (renderer_percent_done() == 0.0f) {
time_begin = std::chrono::steady_clock::now(); time_begin_ = std::chrono::steady_clock::now();
} }
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_IMAGE); GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_IMAGE);
GPU_shader_bind(shader); GPU_shader_bind(shader);
pxr::HdTaskSharedPtrVector tasks; pxr::HdTaskSharedPtrVector tasks;
if (simple_light_task_delegate) { if (simple_light_task_delegate_) {
tasks.push_back(simple_light_task_delegate->get_task()); tasks.push_back(simple_light_task_delegate_->get_task());
} }
tasks.push_back(render_task_delegate->get_task()); tasks.push_back(render_task_delegate_->get_task());
{ {
/* Release the GIL before calling into hydra, in case any hydra plugins call into python. */ /* Release the GIL before calling into hydra, in case any hydra plugins call into python. */
pxr::TF_PY_ALLOW_THREADS_IN_SCOPE(); pxr::TF_PY_ALLOW_THREADS_IN_SCOPE();
engine->Execute(render_index.get(), &tasks); engine_->Execute(render_index_.get(), &tasks);
if ((bl_engine->type->flag & RE_USE_GPU_CONTEXT) == 0) { if ((bl_engine_->type->flag & RE_USE_GPU_CONTEXT) == 0) {
draw_texture.set_buffer(render_task_delegate->get_renderer_aov(pxr::HdAovTokens->color)); draw_texture_.set_buffer(render_task_delegate_->get_renderer_aov(pxr::HdAovTokens->color));
draw_texture.draw(shader, view_settings.border[0], view_settings.border[1]); draw_texture_.draw(shader, view_settings.border[0], view_settings.border[1]);
} }
} }
@ -281,29 +288,24 @@ void ViewportEngine::render(Depsgraph *depsgraph, bContext *context)
std::chrono::time_point<std::chrono::steady_clock> time_current = std::chrono::time_point<std::chrono::steady_clock> time_current =
std::chrono::steady_clock::now(); std::chrono::steady_clock::now();
std::chrono::milliseconds elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::milliseconds elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(
time_current - time_begin); time_current - time_begin_);
std::string formatted_time = format_duration(elapsed_time); std::string formatted_time = format_duration(elapsed_time);
if (!render_task_delegate->is_converged()) { if (!render_task_delegate_->is_converged()) {
notify_status("Time: " + formatted_time + notify_status("Time: " + formatted_time +
" | Done: " + std::to_string(int(renderer_percent_done())) + "%", " | Done: " + std::to_string(int(renderer_percent_done())) + "%",
"Render"); "Render");
bl_engine->flag |= RE_ENGINE_DO_DRAW; bl_engine_->flag |= RE_ENGINE_DO_DRAW;
} }
else { else {
notify_status(("Time: " + formatted_time).c_str(), "Rendering Done"); notify_status(("Time: " + formatted_time).c_str(), "Rendering Done");
} }
} }
void ViewportEngine::render(Depsgraph *depsgraph)
{
/* Empty function */
}
void ViewportEngine::notify_status(const std::string &info, const std::string &status) void ViewportEngine::notify_status(const std::string &info, 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());
} }
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -19,6 +19,7 @@ class DrawTexture {
public: public:
DrawTexture(); DrawTexture();
~DrawTexture(); ~DrawTexture();
void set_buffer(pxr::HdRenderBuffer *buffer); void set_buffer(pxr::HdRenderBuffer *buffer);
void draw(GPUShader *shader, float x, float y); void draw(GPUShader *shader, float x, float y);
@ -26,14 +27,15 @@ class DrawTexture {
void create(pxr::HdRenderBuffer *buffer); void create(pxr::HdRenderBuffer *buffer);
void free(); void free();
GPUTexture *texture; GPUTexture *texture_;
GPUBatch *batch; GPUBatch *batch_;
int width, height, channels; int width_, height_, channels_;
}; };
class ViewportEngine : public Engine { class ViewportEngine : public Engine {
public: public:
using Engine::Engine; using Engine::Engine;
void sync(Depsgraph *depsgraph, void sync(Depsgraph *depsgraph,
bContext *context, bContext *context,
pxr::HdRenderSettingsMap &render_settings) override; pxr::HdRenderSettingsMap &render_settings) override;
@ -44,9 +46,9 @@ class ViewportEngine : public Engine {
void notify_status(const std::string &title, const std::string &info); void notify_status(const std::string &title, const std::string &info);
private: private:
std::chrono::time_point<std::chrono::steady_clock> time_begin; std::chrono::time_point<std::chrono::steady_clock> time_begin_;
DrawTexture draw_texture; DrawTexture draw_texture_;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra