Blender V4.3
blender/light.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "scene/light.h"
6
8#include "blender/sync.h"
9#include "blender/util.h"
10
11#include "util/hash.h"
12
14
15void BlenderSync::sync_light(BL::Object &b_parent,
16 int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
17 BObjectInfo &b_ob_info,
18 int random_id,
19 Transform &tfm,
20 bool *use_portal)
21{
22 /* test if we need to sync */
23 ObjectKey key(b_parent, persistent_id, b_ob_info.real_object, false);
24 BL::Light b_light(b_ob_info.object_data);
25
26 Light *light = light_map.find(key);
27
28 /* Check if the transform was modified, in case a linked collection is moved we do not get a
29 * specific depsgraph update (#88515). This also mimics the behavior for Objects. */
30 const bool tfm_updated = (light && light->get_tfm() != tfm);
31
32 /* Update if either object or light data changed. */
33 if (!light_map.add_or_update(&light, b_ob_info.real_object, b_parent, key) && !tfm_updated) {
34 Shader *shader;
35 if (!shader_map.add_or_update(&shader, b_light)) {
36 if (light->get_is_portal()) {
37 *use_portal = true;
38 }
39 return;
40 }
41 }
42
43 light->name = b_light.name().c_str();
44
45 /* type */
46 switch (b_light.type()) {
47 case BL::Light::type_POINT: {
48 BL::PointLight b_point_light(b_light);
49 light->set_size(b_point_light.shadow_soft_size());
50 light->set_light_type(LIGHT_POINT);
51 light->set_is_sphere(!b_point_light.use_soft_falloff());
52 break;
53 }
54 case BL::Light::type_SPOT: {
55 BL::SpotLight b_spot_light(b_light);
56 light->set_size(b_spot_light.shadow_soft_size());
57 light->set_light_type(LIGHT_SPOT);
58 light->set_spot_angle(b_spot_light.spot_size());
59 light->set_spot_smooth(b_spot_light.spot_blend());
60 light->set_is_sphere(!b_spot_light.use_soft_falloff());
61 break;
62 }
63 /* Hemi were removed from 2.8 */
64 // case BL::Light::type_HEMI: {
65 // light->type = LIGHT_DISTANT;
66 // light->size = 0.0f;
67 // break;
68 // }
69 case BL::Light::type_SUN: {
70 BL::SunLight b_sun_light(b_light);
71 light->set_angle(b_sun_light.angle());
72 light->set_light_type(LIGHT_DISTANT);
73 break;
74 }
75 case BL::Light::type_AREA: {
76 BL::AreaLight b_area_light(b_light);
77 light->set_size(1.0f);
78 light->set_sizeu(b_area_light.size());
79 light->set_spread(b_area_light.spread());
80 switch (b_area_light.shape()) {
81 case BL::AreaLight::shape_SQUARE:
82 light->set_sizev(light->get_sizeu());
83 light->set_ellipse(false);
84 break;
85 case BL::AreaLight::shape_RECTANGLE:
86 light->set_sizev(b_area_light.size_y());
87 light->set_ellipse(false);
88 break;
89 case BL::AreaLight::shape_DISK:
90 light->set_sizev(light->get_sizeu());
91 light->set_ellipse(true);
92 break;
93 case BL::AreaLight::shape_ELLIPSE:
94 light->set_sizev(b_area_light.size_y());
95 light->set_ellipse(true);
96 break;
97 }
98 light->set_light_type(LIGHT_AREA);
99 break;
100 }
101 }
102
103 /* strength */
104 float3 strength = get_float3(b_light.color()) * BL::PointLight(b_light).energy();
105 light->set_strength(strength);
106
107 /* location and (inverted!) direction */
108 light->set_tfm(tfm);
109
110 /* shader */
111 array<Node *> used_shaders;
112 find_shader(b_light, used_shaders, scene->default_light);
113 light->set_shader(static_cast<Shader *>(used_shaders[0]));
114
115 /* shadow */
116 PointerRNA clight = RNA_pointer_get(&b_light.ptr, "cycles");
117 light->set_cast_shadow(b_light.use_shadow());
118 light->set_use_mis(get_boolean(clight, "use_multiple_importance_sampling"));
119
120 /* caustics light */
121 light->set_use_caustics(get_boolean(clight, "is_caustics_light"));
122
123 light->set_max_bounces(get_int(clight, "max_bounces"));
124
125 if (b_ob_info.real_object != b_ob_info.iter_object) {
126 light->set_random_id(random_id);
127 }
128 else {
129 light->set_random_id(hash_uint2(hash_string(b_ob_info.real_object.name().c_str()), 0));
130 }
131
132 if (light->get_light_type() == LIGHT_AREA) {
133 light->set_is_portal(get_boolean(clight, "is_portal"));
134 }
135 else {
136 light->set_is_portal(false);
137 }
138
139 if (light->get_is_portal()) {
140 *use_portal = true;
141 }
142
143 /* visibility */
144 uint visibility = object_ray_visibility(b_ob_info.real_object);
145 light->set_use_camera((visibility & PATH_RAY_CAMERA) != 0);
146 light->set_use_diffuse((visibility & PATH_RAY_DIFFUSE) != 0);
147 light->set_use_glossy((visibility & PATH_RAY_GLOSSY) != 0);
148 light->set_use_transmission((visibility & PATH_RAY_TRANSMIT) != 0);
149 light->set_use_scatter((visibility & PATH_RAY_VOLUME_SCATTER) != 0);
150 light->set_is_shadow_catcher(b_ob_info.real_object.is_shadow_catcher());
151
152 /* Light group and linking. */
153 string lightgroup = b_ob_info.real_object.lightgroup();
154 if (lightgroup.empty()) {
155 lightgroup = b_parent.lightgroup();
156 }
157 light->set_lightgroup(ustring(lightgroup));
158 light->set_light_set_membership(
160 light->set_shadow_set_membership(
162
163 /* tag */
164 light->tag_update(scene);
165}
166
167void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal)
168{
169 BL::World b_world = view_layer.world_override ? view_layer.world_override : b_scene.world();
170
171 if (b_world) {
172 PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
173
174 enum SamplingMethod { SAMPLING_NONE = 0, SAMPLING_AUTOMATIC, SAMPLING_MANUAL, SAMPLING_NUM };
175 int sampling_method = get_enum(cworld, "sampling_method", SAMPLING_NUM, SAMPLING_AUTOMATIC);
176 bool sample_as_light = (sampling_method != SAMPLING_NONE);
177
178 if (sample_as_light || use_portal) {
179 /* test if we need to sync */
180 Light *light;
181 ObjectKey key(b_world, 0, b_world, false);
182
183 if (light_map.add_or_update(&light, b_world, b_world, key) || world_recalc ||
184 b_world.ptr.data != world_map)
185 {
186 light->set_light_type(LIGHT_BACKGROUND);
187 if (sampling_method == SAMPLING_MANUAL) {
188 light->set_map_resolution(get_int(cworld, "sample_map_resolution"));
189 }
190 else {
191 light->set_map_resolution(0);
192 }
193 light->set_shader(scene->default_background);
194 light->set_use_mis(sample_as_light);
195 light->set_max_bounces(get_int(cworld, "max_bounces"));
196
197 /* force enable light again when world is resynced */
198 light->set_is_enabled(true);
199
200 /* caustic light */
201 light->set_use_caustics(get_boolean(cworld, "is_caustics_light"));
202
203 light->tag_update(scene);
204 light_map.set_recalc(b_world);
205 }
206 }
207 }
208
209 world_map = b_world.ptr.data;
210 world_recalc = false;
211 viewport_parameters = BlenderViewportParameters(b_v3d, use_developer_ui);
212}
213
unsigned int uint
constexpr PointerRNA PointerRNA_NULL
Definition RNA_types.hh:45
bool add_or_update(T **r_data, const BL::ID &id)
Definition id_map.h:103
void set_recalc(const BL::ID &id)
Definition id_map.h:54
T * find(const BL::ID &id)
Definition id_map.h:39
static uint object_ray_visibility(BL::Object &b_ob)
static bool get_boolean(PointerRNA &ptr, const char *name)
static int get_int(PointerRNA &ptr, const char *name)
static float3 get_float3(const BL::Array< float, 2 > &array)
static int get_enum(PointerRNA &ptr, const char *name, int num_values=-1, int default_value=-1)
#define CCL_NAMESPACE_END
static uint hash_string(const char *str)
Definition hash.h:532
ccl_device_inline uint hash_uint2(uint kx, uint ky)
Definition hash.h:89
@ OBJECT_PERSISTENT_ID_SIZE
Definition id_map.h:214
@ PATH_RAY_TRANSMIT
@ PATH_RAY_VOLUME_SCATTER
@ PATH_RAY_GLOSSY
@ PATH_RAY_DIFFUSE
@ PATH_RAY_CAMERA
@ LIGHT_AREA
@ LIGHT_DISTANT
@ LIGHT_SPOT
@ LIGHT_BACKGROUND
@ LIGHT_POINT
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
BL::Object real_object
BL::Object iter_object
ustring name
Definition graph/node.h:177