diff --git a/source/blender/render/hydra/preview_engine.cc b/source/blender/render/hydra/preview_engine.cc index 651154cbf4a2..70ee57a12a11 100644 --- a/source/blender/render/hydra/preview_engine.cc +++ b/source/blender/render/hydra/preview_engine.cc @@ -39,7 +39,9 @@ void PreviewEngine::update_render_result(std::vector &pixels) RenderLayer *layer = (RenderLayer *)result->layers.first; RenderPass *pass = (RenderPass *)layer->passes.first; - memcpy(pass->buffer.data, pixels.data(), sizeof(float) * pass->rectx * pass->recty * pass->channels); + memcpy(pass->buffer.data, + pixels.data(), + sizeof(float) * pass->rectx * pass->recty * pass->channels); RE_engine_end_result(bl_engine_, result, false, false, false); } diff --git a/source/blender/render/hydra/scene_delegate/blender_scene_delegate.cc b/source/blender/render/hydra/scene_delegate/blender_scene_delegate.cc index 4326fc6bf008..01754c4814a1 100644 --- a/source/blender/render/hydra/scene_delegate/blender_scene_delegate.cc +++ b/source/blender/render/hydra/scene_delegate/blender_scene_delegate.cc @@ -14,6 +14,19 @@ namespace blender::render::hydra { CLG_LOGREF_DECLARE_GLOBAL(LOG_RENDER_HYDRA_SCENE, "render.hydra.scene"); +bool BlenderSceneDelegate::ShadingSettings::operator==(const ShadingSettings &other) +{ + bool ret = use_scene_lights == other.use_scene_lights && + use_scene_world == other.use_scene_world; + if (ret && !use_scene_world) { + /* compare studiolight settings when studiolight is using */ + ret = studiolight_name == other.studiolight_name && + studiolight_rotation == other.studiolight_rotation && + studiolight_intensity == other.studiolight_intensity; + } + return ret; +} + BlenderSceneDelegate::BlenderSceneDelegate(pxr::HdRenderIndex *parent_index, pxr::SdfPath const &delegate_id, Engine *engine) @@ -205,6 +218,8 @@ void BlenderSceneDelegate::populate(Depsgraph *deps, bContext *cont) check_updates(); } else { + set_light_shading_settings(); + set_world_shading_settings(); add_new_objects(); update_world(); } @@ -338,7 +353,9 @@ void BlenderSceneDelegate::update_objects(Object *object) if (!ObjectData::is_supported(object)) { return; } - + if (!shading_settings.use_scene_lights && object->type == OB_LAMP) { + return; + } pxr::SdfPath id = object_prim_id(object); ObjectData *obj_data = object_data(id); if (obj_data) { @@ -397,17 +414,16 @@ void BlenderSceneDelegate::update_instancers(Object *object) void BlenderSceneDelegate::update_world() { - World *world = scene->world; if (!world_data_) { - if (world) { - world_data_ = std::make_unique(this, world, world_prim_id()); + if (!shading_settings.use_scene_world || (shading_settings.use_scene_world && scene->world)) { + world_data_ = std::make_unique(this, world_prim_id()); world_data_->init(); world_data_->insert(); } } else { - if (world) { - world_data_->update(world); + if (!shading_settings.use_scene_world || (shading_settings.use_scene_world && scene->world)) { + world_data_->update(); } else { world_data_->remove(); @@ -422,6 +438,19 @@ void BlenderSceneDelegate::check_updates() bool do_update_visibility = false; bool do_update_world = false; + if (set_world_shading_settings()) { + do_update_world = true; + } + + if (set_light_shading_settings()) { + if (shading_settings.use_scene_lights) { + add_new_objects(); + } + else { + do_update_collection = true; + } + } + DEGIDIterData data = {0}; data.graph = depsgraph; data.only_updated = true; @@ -455,7 +484,7 @@ void BlenderSceneDelegate::check_updates() } break; case ID_WO: { - if (id->recalc & ID_RECALC_SHADING) { + if (shading_settings.use_scene_world && id->recalc & ID_RECALC_SHADING) { do_update_world = true; } } break; @@ -518,6 +547,9 @@ void BlenderSceneDelegate::add_new_objects() "Visibility: %s [%s]", object->id.name, std::bitset<3>(BKE_object_visibility(object, deg_mode)).to_string().c_str()); + if (object_data(object_prim_id(object))) { + continue; + } update_objects(object); update_instancers(object); } @@ -544,10 +576,13 @@ void BlenderSceneDelegate::remove_unused_objects() Object *, object) { + available_objects.add(instancer_prim_id(object).GetName()); if (ObjectData::is_supported(object)) { + if (!shading_settings.use_scene_lights && object->type == OB_LAMP) { + continue; + } available_objects.add(object_prim_id(object).GetName()); } - available_objects.add(instancer_prim_id(object).GetName()); } ITER_END; @@ -639,4 +674,27 @@ void BlenderSceneDelegate::update_visibility() ITER_END; } +bool BlenderSceneDelegate::set_light_shading_settings() +{ + if (!view3d) { + return false; + } + ShadingSettings prev_settings(shading_settings); + shading_settings.use_scene_lights = V3D_USES_SCENE_LIGHTS(view3d); + return !(shading_settings == prev_settings); +} + +bool BlenderSceneDelegate::set_world_shading_settings() +{ + if (!view3d) { + return false; + } + ShadingSettings prev_settings(shading_settings); + shading_settings.use_scene_world = V3D_USES_SCENE_WORLD(view3d); + shading_settings.studiolight_name = view3d->shading.lookdev_light; + shading_settings.studiolight_rotation = view3d->shading.studiolight_rot_z; + shading_settings.studiolight_intensity = view3d->shading.studiolight_intensity; + return !(shading_settings == prev_settings); +} + } // namespace blender::render::hydra diff --git a/source/blender/render/hydra/scene_delegate/blender_scene_delegate.h b/source/blender/render/hydra/scene_delegate/blender_scene_delegate.h index c7b1468408e4..93119206e783 100644 --- a/source/blender/render/hydra/scene_delegate/blender_scene_delegate.h +++ b/source/blender/render/hydra/scene_delegate/blender_scene_delegate.h @@ -7,11 +7,11 @@ #include #include "BKE_context.h" +#include "BLI_map.hh" #include "DEG_depsgraph.h" #include "CLG_log.h" -#include "BLI_map.hh" #include "curves.h" #include "instancer.h" #include "light.h" @@ -37,6 +37,16 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate { Map render_tokens; }; + struct ShadingSettings { + bool use_scene_lights = true; + bool use_scene_world = true; + std::string studiolight_name; + float studiolight_rotation; + float studiolight_intensity; + + bool operator==(const ShadingSettings &other); + }; + BlenderSceneDelegate(pxr::HdRenderIndex *parent_index, pxr::SdfPath const &delegate_id, Engine *engine); @@ -71,6 +81,7 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate { Scene *scene = nullptr; Engine *engine; Settings settings; + ShadingSettings shading_settings; private: pxr::SdfPath prim_id(ID *id, const char *prefix) const; @@ -93,6 +104,8 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate { void add_new_objects(); void remove_unused_objects(); void update_visibility(); + bool set_light_shading_settings(); + bool set_world_shading_settings(); ObjectDataMap objects_; MaterialDataMap materials_; diff --git a/source/blender/render/hydra/scene_delegate/image.cc b/source/blender/render/hydra/scene_delegate/image.cc index c82731eb788f..340fb34cf424 100644 --- a/source/blender/render/hydra/scene_delegate/image.cc +++ b/source/blender/render/hydra/scene_delegate/image.cc @@ -76,8 +76,9 @@ std::string cache_or_get_image_file(Image *image, bContext *context, ImageUser * } else { Main *main = CTX_data_main(context); - file_path.reserve(FILE_MAX); - BKE_image_user_file_path_ex(main, iuser, image, file_path.data(), false, true); + char str[FILE_MAX]; + BKE_image_user_file_path_ex(main, iuser, image, str, false, true); + file_path = str; if (!pxr::HioImageRegistry::GetInstance().IsSupportedImageFile(file_path)) { file_path = cache_image_file(image, context, iuser, true); diff --git a/source/blender/render/hydra/scene_delegate/instancer.cc b/source/blender/render/hydra/scene_delegate/instancer.cc index 3db5626e89e5..ffbc87004dba 100644 --- a/source/blender/render/hydra/scene_delegate/instancer.cc +++ b/source/blender/render/hydra/scene_delegate/instancer.cc @@ -353,6 +353,9 @@ void InstancerData::write_instances() scene_delegate_->depsgraph, scene_delegate_->scene, (Object *)id); LISTBASE_FOREACH (DupliObject *, dupli, lb) { Object *ob = dupli->ob; + if (!scene_delegate_->shading_settings.use_scene_lights && ob->type == OB_LAMP) { + continue; + } if (!is_supported(ob) || !is_instance_visible(ob)) { continue; } diff --git a/source/blender/render/hydra/scene_delegate/world.cc b/source/blender/render/hydra/scene_delegate/world.cc index 601be80c0ebc..d9d6f0460545 100644 --- a/source/blender/render/hydra/scene_delegate/world.cc +++ b/source/blender/render/hydra/scene_delegate/world.cc @@ -16,6 +16,8 @@ #include "BKE_node.h" #include "BKE_node_runtime.hh" +#include "BKE_studiolight.h" +#include "BLI_math_rotation.h" #include "BLI_path_util.h" #include "NOD_shader.h" @@ -26,93 +28,122 @@ /* TODO : add custom tftoken "transparency"? */ +/* NOTE: opacity and blur aren't supported by USD */ + namespace blender::render::hydra { -WorldData::WorldData(BlenderSceneDelegate *scene_delegate, - World *world, - pxr::SdfPath const &prim_id) - : IdData(scene_delegate, (ID *)world, prim_id) +WorldData::WorldData(BlenderSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id) + : IdData(scene_delegate, nullptr, prim_id) { } void WorldData::init() { - ID_LOG(1, ""); - write_transform(); - World *world = (World *)id; data_.clear(); - data_[pxr::UsdLuxTokens->orientToStageUpAxis] = true; - if (world->use_nodes) { - /* TODO: Create nodes parsing system */ + float intensity = 1.0f; + float exposure = 1.0f; + pxr::GfVec3f color(1.0f, 1.0f, 1.0f); + pxr::SdfAssetPath texture_file; - bNode *output_node = ntreeShaderOutputNode(world->nodetree, SHD_OUTPUT_ALL); - blender::Span input_sockets = output_node->input_sockets(); - bNodeSocket *input_socket = nullptr; + if (scene_delegate_->shading_settings.use_scene_world) { + World *world = scene_delegate_->scene->world; + CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 1, "%s: %s", prim_id.GetText(), world->id.name); - for (auto socket : input_sockets) { - if (STREQ(socket->name, "Surface")) { - input_socket = socket; - break; + exposure = world->exposure; + if (world->use_nodes) { + /* TODO: Create nodes parsing system */ + + bNode *output_node = ntreeShaderOutputNode(world->nodetree, SHD_OUTPUT_ALL); + blender::Span input_sockets = output_node->input_sockets(); + bNodeSocket *input_socket = nullptr; + + for (auto socket : input_sockets) { + if (STREQ(socket->name, "Surface")) { + input_socket = socket; + break; + } + } + if (!input_socket) { + return; + } + bNodeLink const *link = input_socket->directly_linked_links()[0]; + if (input_socket->directly_linked_links().is_empty()) { + return; } - } - if (!input_socket) { - return; - } - bNodeLink const *link = input_socket->directly_linked_links()[0]; - if (input_socket->directly_linked_links().is_empty()) { - return; - } - bNode *input_node = link->fromnode; - if (input_node->type != SH_NODE_BACKGROUND) { - return; - } + bNode *input_node = link->fromnode; + if (input_node->type != SH_NODE_BACKGROUND) { + return; + } - bNodeSocket color_input = input_node->input_by_identifier("Color"); - bNodeSocket strength_input = input_node->input_by_identifier("Strength"); + bNodeSocket color_input = input_node->input_by_identifier("Color"); + bNodeSocket strength_input = input_node->input_by_identifier("Strength"); - float const *strength = strength_input.default_value_typed(); - float const *color = color_input.default_value_typed(); - data_[pxr::HdLightTokens->intensity] = strength[1]; - data_[pxr::HdLightTokens->exposure] = 1.0f; - data_[pxr::HdLightTokens->color] = pxr::GfVec3f(color[0], color[1], color[2]); + float const *strength = strength_input.default_value_typed(); + float const *input_color = color_input.default_value_typed(); + intensity = strength[1]; + color = pxr::GfVec3f(input_color[0], input_color[1], input_color[2]); - if (!color_input.directly_linked_links().is_empty()) { - bNode *color_input_node = color_input.directly_linked_links()[0]->fromnode; - if (color_input_node->type == SH_NODE_TEX_IMAGE) { - NodeTexImage *tex = static_cast(color_input_node->storage); - Image *image = (Image *)color_input_node->id; - if (image) { - std::string image_path = cache_or_get_image_file( - image, scene_delegate_->context, &tex->iuser); - if (!image_path.empty()) { - data_[pxr::HdLightTokens->textureFile] = pxr::SdfAssetPath(image_path, image_path); + if (!color_input.directly_linked_links().is_empty()) { + bNode *color_input_node = color_input.directly_linked_links()[0]->fromnode; + if (color_input_node->type == SH_NODE_TEX_IMAGE) { + NodeTexImage *tex = static_cast(color_input_node->storage); + Image *image = (Image *)color_input_node->id; + if (image) { + std::string image_path = cache_or_get_image_file( + image, scene_delegate_->context, &tex->iuser); + if (!image_path.empty()) { + texture_file = pxr::SdfAssetPath(image_path, image_path); + } } } } } + else { + intensity = 1.0f; + color = pxr::GfVec3f(world->horr, world->horg, world->horb); + } + + if (texture_file.GetAssetPath().empty()) { + float fill_color[4] = {color[0], color[1], color[2], 1.0f}; + std::string image_path = cache_image_color(fill_color); + texture_file = pxr::SdfAssetPath(image_path, image_path); + } } else { - data_[pxr::HdLightTokens->intensity] = 1.0f; - data_[pxr::HdLightTokens->exposure] = world->exposure; - data_[pxr::HdLightTokens->color] = pxr::GfVec3f(world->horr, world->horg, world->horb); + CLOG_INFO(LOG_RENDER_HYDRA_SCENE, + 1, + "%s: studiolight: %s", + prim_id.GetText(), + scene_delegate_->shading_settings.studiolight_name.c_str()); + + StudioLight *sl = BKE_studiolight_find( + scene_delegate_->shading_settings.studiolight_name.c_str(), + STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE); + if (sl != NULL && sl->flag & STUDIOLIGHT_TYPE_WORLD) { + texture_file = pxr::SdfAssetPath(sl->filepath, sl->filepath); + transform *= pxr::GfMatrix4d( + pxr::GfRotation(pxr::GfVec3d(0.0, 0.0, -1.0), + RAD2DEGF(scene_delegate_->shading_settings.studiolight_rotation)), + pxr::GfVec3d()); + /* coefficient to follow Cycles result */ + intensity = scene_delegate_->shading_settings.studiolight_intensity / 2; + } } - if (data_.find(pxr::HdLightTokens->textureFile) == data_.end()) { - pxr::GfVec3f c = data_[pxr::HdLightTokens->color].Get(); - float color[4] = {c[0], c[1], c[2], 1.0f}; - std::string image_path = cache_image_color(color); - data_[pxr::HdLightTokens->textureFile] = pxr::SdfAssetPath(image_path, image_path); - } + data_[pxr::HdLightTokens->intensity] = intensity; + data_[pxr::HdLightTokens->exposure] = exposure; + data_[pxr::HdLightTokens->color] = color; + data_[pxr::HdLightTokens->textureFile] = texture_file; } void WorldData::insert() { - ID_LOG(1, ""); + CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 1, "%s", prim_id.GetText()); scene_delegate_->GetRenderIndex().InsertSprim( pxr::HdPrimTypeTokens->domeLight, scene_delegate_, prim_id); } @@ -125,23 +156,17 @@ void WorldData::remove() void WorldData::update() { - ID_LOG(1, ""); + CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 1, "%s", prim_id.GetText()); init(); scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(prim_id, pxr::HdLight::AllDirty); } -void WorldData::update(World *world) -{ - id = (ID *)world; - update(); -} - pxr::VtValue WorldData::get_data(pxr::TfToken const &key) const { auto it = data_.find(key); if (it != data_.end()) { - ID_LOG(3, "%s", key.GetText()); + CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s: %s", prim_id.GetText(), key.GetText()); return pxr::VtValue(it->second); } return pxr::VtValue(); diff --git a/source/blender/render/hydra/scene_delegate/world.h b/source/blender/render/hydra/scene_delegate/world.h index 2eb62555c555..c6183ab0c1c7 100644 --- a/source/blender/render/hydra/scene_delegate/world.h +++ b/source/blender/render/hydra/scene_delegate/world.h @@ -20,7 +20,7 @@ namespace blender::render::hydra { class WorldData : public IdData { public: - WorldData(BlenderSceneDelegate *scene_delegate, World *world, pxr::SdfPath const &prim_id); + WorldData(BlenderSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id); void init() override; void insert() override;