/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation * * SPDX-License-Identifier: Apache-2.0 */ #pragma once #include "bvh/params.h" #include "scene/devicescene.h" #include "scene/film.h" #include "scene/image.h" #include "scene/scene_attributes.h" #include "scene/shader.h" #include "util/param.h" #include "util/string.h" #include "util/thread.h" #include "util/unique_ptr.h" #include "util/unique_ptr_vector.h" CCL_NAMESPACE_BEGIN class AttributeRequestSet; class Background; class BVH; class Camera; class Device; class DeviceInfo; class Film; class Integrator; class SceneAttributes; class PointLight; class SpotLight; class AreaLight; class SunLight; class BackgroundLight; class Light; class LightManager; class LookupTables; class Geometry; class GeometryManager; class Object; class ObjectManager; class OSLManager; class ParticleSystemManager; class ParticleSystem; class PointCloud; class Procedural; class ProceduralManager; class CurveSystemManager; class Shader; class ShaderManager; class Progress; class BakeManager; class BakeData; class RenderStats; class SceneUpdateStats; class Volume; class VolumeManager; /* Scene Parameters */ class SceneParams { public: ShadingSystem shadingsystem; /* Requested BVH layout. * * If it's not supported by the device, the widest one from supported ones * will be used, but BVH wider than this one will never be used. */ BVHLayout bvh_layout; BVHType bvh_type; bool use_bvh_spatial_split; bool use_bvh_compact_structure; bool use_bvh_unaligned_nodes; int num_bvh_time_steps; int hair_subdivisions; CurveShapeType hair_shape; float texture_resolution; int texture_limit; /* Use tx files if they exist. */ bool use_texture_cache = true; /* Auto generate tx files. */ bool auto_texture_cache = false; /* Relative (to the image file) or absolute directory for auto generating tx files. */ std::string texture_cache_path; bool background; SceneParams() { shadingsystem = SHADINGSYSTEM_SVM; bvh_layout = BVH_LAYOUT_AUTO; bvh_type = BVH_TYPE_DYNAMIC; use_bvh_spatial_split = false; use_bvh_compact_structure = true; use_bvh_unaligned_nodes = true; num_bvh_time_steps = 0; hair_subdivisions = 3; hair_shape = CURVE_RIBBON; texture_resolution = 1.0f; texture_limit = 0; background = true; } bool modified(const SceneParams ¶ms) const { return !( shadingsystem == params.shadingsystem && bvh_layout == params.bvh_layout && bvh_type == params.bvh_type && use_bvh_spatial_split == params.use_bvh_spatial_split && use_bvh_compact_structure == params.use_bvh_compact_structure && use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes && num_bvh_time_steps == params.num_bvh_time_steps && hair_subdivisions == params.hair_subdivisions && hair_shape == params.hair_shape && texture_resolution == params.texture_resolution && texture_limit == params.texture_limit && use_texture_cache == params.use_texture_cache && auto_texture_cache == params.auto_texture_cache && texture_cache_path == params.texture_cache_path); } int curve_subdivisions() { /* Matching the tessellation rate limit in Embree. */ return clamp(1 << hair_subdivisions, 1, 16); } }; /* Scene */ class Scene : public NodeOwner { public: /* Optional name. Is used for logging and reporting. */ string name; /* Maps from Light group names to their pass ID. */ map lightgroups; /* data */ unique_ptr bvh; unique_ptr lookup_tables; Camera *camera; Camera *dicing_camera; Film *film; Background *background; Integrator *integrator; SceneAttributes *scene_attribute; /* data lists */ unique_ptr_vector backgrounds; unique_ptr_vector films; unique_ptr_vector integrators; unique_ptr_vector scene_attributes; unique_ptr_vector cameras; unique_ptr_vector shaders; unique_ptr_vector passes; unique_ptr_vector particle_systems; unique_ptr_vector geometry; unique_ptr_vector objects; unique_ptr_vector procedurals; /* data managers */ unique_ptr image_manager; unique_ptr light_manager; unique_ptr osl_manager; unique_ptr shader_manager; unique_ptr geometry_manager; unique_ptr object_manager; unique_ptr particle_system_manager; unique_ptr bake_manager; unique_ptr procedural_manager; unique_ptr volume_manager; /* default shaders */ Shader *default_surface; Shader *default_volume; Shader *default_light; Shader *default_background; Shader *default_empty; /* device */ Device *device; DeviceScene dscene; /* parameters */ SceneParams params; /* mutex must be locked manually by callers */ thread_mutex mutex; bool scene_updated_while_loading_kernels = false; /* scene update statistics */ unique_ptr update_stats; Scene(const SceneParams ¶ms, Device *device); ~Scene() override; void device_update(Device *device, Progress &progress); bool need_global_attribute(AttributeStandard std) const; void need_global_attributes(AttributeRequestSet &attributes); enum MotionType { MOTION_NONE = 0, MOTION_PASS, MOTION_BLUR, MOTION_PASS_INTERACTIVE }; MotionType need_motion() const; float motion_shutter_time(); bool need_update(); bool need_reset(const bool check_camera = true); void reset(); void device_free(); void collect_statistics(RenderStats *stats); void enable_update_stats(); bool update(Progress &progress); bool update_camera_resolution(Progress &progress, int width, int height); bool has_shadow_catcher(); void tag_shadow_catcher_modified(); bool has_volume(); bool has_volume_modified() const; void tag_has_volume_modified(); /* Check if we use multiple importance sampling for any light in the scene. */ bool use_light_mis() const; /* This function is used to create a node of a specified type instead of * calling 'new', and sets the scene as the owner of the node. * The function has overloads that will also add the created node to the right * node array (e.g. Scene::geometry for Geometry nodes) and tag the appropriate * manager for an update. */ template T *create_node(Args &&.../*args*/) = delete; /* This function is used to delete a node from the scene instead of calling 'delete' * and manually removing the node from the data array. It also tags the * appropriate manager for an update, if any, and checks that the scene is indeed * the owner of the node. Calling this function on a node not owned by the scene * will likely cause a crash which we want in order to detect such cases. */ template void delete_node(T *node) = delete; /* Remove all nodes in the set from the appropriate data arrays, and tag the * specific managers for an update. This assumes that the scene owns the nodes. */ template void delete_nodes(const set &nodes) { delete_nodes(nodes, this); } /* Same as above, but specify the actual owner of all the nodes in the set. */ template void delete_nodes(const set &nodes, const NodeOwner *owner); template T *create_light_node(); protected: /* Check if some heavy data worth logging was updated. * Mainly used to suppress extra annoying logging. */ bool need_data_update(); void free_memory(bool final); bool kernels_loaded; uint loaded_kernel_features; void update_kernel_features(); bool has_shadow_catcher_ = false; bool shadow_catcher_modified_ = true; bool has_volume_modified_ = true; /* Maximum number of closure during session lifetime. */ int max_closure_global; /* Get maximum number of closures to be used in kernel. */ int get_max_closure_count(); /* Get size of a volume stack needed to render this scene. */ int get_volume_stack_size() const; bool load_kernels(Progress &progress); }; template<> PointLight *Scene::create_node(); template<> SpotLight *Scene::create_node(); template<> AreaLight *Scene::create_node(); template<> SunLight *Scene::create_node(); template<> BackgroundLight *Scene::create_node(); template<> Mesh *Scene::create_node(); template<> Object *Scene::create_node(); template<> Hair *Scene::create_node(); template<> Volume *Scene::create_node(); template<> PointCloud *Scene::create_node(); template<> ParticleSystem *Scene::create_node(); template<> Shader *Scene::create_node(); template<> Pass *Scene::create_node(); template<> Camera *Scene::create_node(); template<> Background *Scene::create_node(); template<> Film *Scene::create_node(); template<> Integrator *Scene::create_node(); template<> SceneAttributes *Scene::create_node(); template<> void Scene::delete_node(Light *node); template<> void Scene::delete_node(Mesh *node); template<> void Scene::delete_node(Volume *node); template<> void Scene::delete_node(PointCloud *node); template<> void Scene::delete_node(Hair *node); template<> void Scene::delete_node(Geometry *node); template<> void Scene::delete_node(Object *node); template<> void Scene::delete_node(ParticleSystem *node); template<> void Scene::delete_node(Shader *node); template<> void Scene::delete_node(Procedural *node); template<> void Scene::delete_node(Pass *node); template<> void Scene::delete_nodes(const set &nodes, const NodeOwner *owner); template<> void Scene::delete_nodes(const set &nodes, const NodeOwner *owner); template<> void Scene::delete_nodes(const set &nodes, const NodeOwner *owner); template<> void Scene::delete_nodes(const set &nodes, const NodeOwner *owner); template<> void Scene::delete_nodes(const set &nodes, const NodeOwner *owner); template<> void Scene::delete_nodes(const set &nodes, const NodeOwner *owner); CCL_NAMESPACE_END