Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorWeizhen Huang <itsnotrj@gmail.com>2022-11-02 18:06:12 +0300
committerWeizhen Huang <itsnotrj@gmail.com>2022-11-02 19:27:31 +0300
commitbde57b3a858c27a93ece6d1b02252132f34241e8 (patch)
treeb2b436ccda6128be84cf1dfc4ad379e0c9021cdb /intern
parent0aa151f8349b7024faaf69bfc4501a3fbcb38cbb (diff)
Adjust energy scaling for different light types
Differential Revision: https://developer.blender.org/D16368
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/kernel/light/tree.h3
-rw-r--r--intern/cycles/scene/light.cpp93
-rw-r--r--intern/cycles/scene/light.h1
-rw-r--r--intern/cycles/scene/light_tree.cpp7
4 files changed, 37 insertions, 67 deletions
diff --git a/intern/cycles/kernel/light/tree.h b/intern/cycles/kernel/light/tree.h
index 9198aa82262..4e9a560c10c 100644
--- a/intern/cycles/kernel/light/tree.h
+++ b/intern/cycles/kernel/light/tree.h
@@ -945,8 +945,7 @@ ccl_device bool light_tree_sample(KernelGlobals kg,
ccl_private LightSample *ls)
{
const bool has_transmission = (shader_flags & SD_BSDF_HAS_TRANSMISSION);
- /* to-do: with weighted reservoir sampling, we can also try picking a sample from the distant
- * light group and compare it to the sample from the light tree. */
+ /* TODO: add distant lights to light tree (as one child node of the root node) */
float distant_light_importance = light_tree_distant_light_importance(
kg, N, has_transmission, kernel_data.integrator.num_distant_lights);
float light_tree_importance = 0.0f;
diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp
index f7f3689d514..20650759c29 100644
--- a/intern/cycles/scene/light.cpp
+++ b/intern/cycles/scene/light.cpp
@@ -80,32 +80,6 @@ static void shade_background_pixels(Device *device,
});
}
-static float average_background_energy(
- Device *device, DeviceScene *dscene, Progress &progress, Scene *scene, Light *light)
-{
- if (light->get_light_type() != LIGHT_BACKGROUND) {
- assert(false);
- }
-
- /* get the resolution from the light's size (we stuff it in there) */
- int2 res = make_int2(light->get_map_resolution(), light->get_map_resolution() / 2);
- /* If it's still unknown, just use the default. */
- if (res.x == 0 || res.y == 0) {
- res = make_int2(1024, 512);
- VLOG_INFO << "Setting World MIS resolution to default\n";
- }
-
- vector<float3> pixels;
- shade_background_pixels(device, dscene, res.x, res.y, pixels, progress);
-
- float total_energy = 0.0f;
- for (int i = 0; i < pixels.size(); i++) {
- total_energy += scene->shader_manager->linear_rgb_to_gray(pixels[i]);
- }
-
- return total_energy / pixels.size();
-}
-
/* Light */
NODE_DEFINE(Light)
@@ -136,6 +110,7 @@ NODE_DEFINE(Light)
SOCKET_FLOAT(spread, "Spread", M_PI_F);
SOCKET_INT(map_resolution, "Map Resolution", 0);
+ SOCKET_FLOAT(average_radiance, "Average Radiance", 0.0f);
SOCKET_FLOAT(spot_angle, "Spot Angle", M_PI_4_F);
SOCKET_FLOAT(spot_smooth, "Spot Smooth", 0.0f);
@@ -304,8 +279,6 @@ void LightManager::device_update_distribution(Device *device,
size_t num_triangles = 0;
size_t total_triangles = 0;
- bool background_mis = false;
-
/* We want to add both lights and emissive triangles to this vector for light tree construction.
*/
bool light_tree_enabled = scene->integrator->get_use_light_tree();
@@ -512,7 +485,7 @@ void LightManager::device_update_distribution(Device *device,
/* We use OrientationBounds here to */
OrientationBounds distant_light_bounds = OrientationBounds::empty;
- float max_distant_light_energy = 0.0f;
+ light_tree_distant_group[num_distant_lights].energy = 0.f;
for (int index = 0; index < num_distant_lights; index++) {
LightTreePrimitive prim = distant_lights[index];
Light *light = scene->lights[prim.lamp_id];
@@ -521,9 +494,10 @@ void LightManager::device_update_distribution(Device *device,
/* Lights in this group are either a background or distant light. */
light_tree_distant_group[index].prim_id = ~prim.prim_id;
- float strength = 0.0f;
+ float energy = 0.0f;
if (light->light_type == LIGHT_BACKGROUND) {
- strength = average_background_energy(device, dscene, progress, scene, light);
+ /* integrate over cosine-weighted hemisphere */
+ energy = light->get_average_radiance() * M_PI_F;
/* We can set an arbitrary direction for the background light. */
light_bounds.axis[0] = 0.0f;
@@ -534,7 +508,8 @@ void LightManager::device_update_distribution(Device *device,
light_bounds.theta_o = M_PI_F;
}
else {
- strength = prim.calculate_energy(scene);
+ energy = prim.calculate_energy(scene);
+
for (int i = 0; i < 3; i++) {
light_bounds.axis[i] = -light->dir[i];
}
@@ -546,21 +521,14 @@ void LightManager::device_update_distribution(Device *device,
light_tree_distant_group[index].direction[i] = light_bounds.axis[i];
}
light_tree_distant_group[index].bounding_radius = light_bounds.theta_o;
- /* We multiply the strength of distance lights by 4pi so it more closely matches the
- * energy output of other light types.
- * TODO: validate if this is correct*/
- float energy = strength * M_4PI_F;
light_tree_distant_group[index].energy = energy;
light_array[~prim.prim_id] = index;
- if (energy > max_distant_light_energy) {
- max_distant_light_energy = energy;
- }
+ light_tree_distant_group[num_distant_lights].energy += energy;
}
/* The net OrientationBounds contain bounding information about all the distant lights. */
light_tree_distant_group[num_distant_lights].prim_id = -1;
- light_tree_distant_group[num_distant_lights].energy = max_distant_light_energy;
for (int i = 0; i < 3; i++) {
light_tree_distant_group[num_distant_lights].direction[i] = distant_light_bounds.axis[i];
}
@@ -679,7 +647,6 @@ void LightManager::device_update_distribution(Device *device,
}
else if (light->light_type == LIGHT_BACKGROUND) {
num_background_lights++;
- background_mis |= light->use_mis;
}
light_index++;
@@ -753,17 +720,7 @@ void LightManager::device_update_distribution(Device *device,
/* Portals */
if (num_portals > 0) {
kbackground->portal_offset = light_index;
- kbackground->num_portals = num_portals;
- kbackground->portal_weight = 1.0f;
- }
- else {
- kbackground->num_portals = 0;
- kbackground->portal_offset = 0;
- kbackground->portal_weight = 0.0f;
}
-
- /* Map */
- kbackground->map_weight = background_mis ? 1.0f : 0.0f;
}
else {
if (light_tree_enabled) {
@@ -782,12 +739,6 @@ void LightManager::device_update_distribution(Device *device,
kintegrator->distribution_pdf_lights = 0.0f;
kintegrator->use_lamp_mis = false;
- kbackground->num_portals = 0;
- kbackground->portal_offset = 0;
- kbackground->portal_weight = 0.0f;
- kbackground->sun_weight = 0.0f;
- kbackground->map_weight = 0.0f;
-
kfilm->pass_shadow_scale = 1.0f;
}
}
@@ -840,20 +791,30 @@ void LightManager::device_update_background(Device *device,
KernelBackground *kbackground = &dscene->data.background;
Light *background_light = NULL;
+ bool background_mis = false;
+ size_t num_portals = 0;
+
/* find background light */
foreach (Light *light, scene->lights) {
- if (light->light_type == LIGHT_BACKGROUND) {
+ if (light->light_type == LIGHT_BACKGROUND && light->is_enabled) {
background_light = light;
- break;
+ background_mis |= light->use_mis;
+ }
+ if (light->is_portal) {
+ num_portals++;
}
}
+ kbackground->num_portals = num_portals;
+ kbackground->portal_offset = 0;
+ kbackground->portal_weight = num_portals > 0 ? 1.0f : 0.0f;
+ kbackground->map_weight = background_mis ? 1.0f : 0.0f;
+ kbackground->sun_weight = 0.0f;
+
/* no background light found, signal renderer to skip sampling */
if (!background_light || !background_light->is_enabled) {
kbackground->map_res_x = 0;
kbackground->map_res_y = 0;
- kbackground->map_weight = 0.0f;
- kbackground->sun_weight = 0.0f;
kbackground->use_mis = (kbackground->portal_weight > 0.0f);
return;
}
@@ -974,6 +935,8 @@ void LightManager::device_update_background(Device *device,
float cdf_total = marg_cdf[res.y - 1].y + marg_cdf[res.y - 1].x / res.y;
marg_cdf[res.y].x = cdf_total;
+ background_light->set_average_radiance(cdf_total * M_PI_2_F);
+
if (cdf_total > 0.0f)
for (int i = 1; i < res.y; i++)
marg_cdf[i].y /= cdf_total;
@@ -1263,16 +1226,16 @@ void LightManager::device_update(Device *device,
if (progress.get_cancel())
return;
- device_update_distribution(device, dscene, scene, progress);
- if (progress.get_cancel())
- return;
-
if (need_update_background) {
device_update_background(device, dscene, scene, progress);
if (progress.get_cancel())
return;
}
+ device_update_distribution(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
+
device_update_ies(dscene);
if (progress.get_cancel())
return;
diff --git a/intern/cycles/scene/light.h b/intern/cycles/scene/light.h
index 4db4de10ec6..b747e793e8e 100644
--- a/intern/cycles/scene/light.h
+++ b/intern/cycles/scene/light.h
@@ -51,6 +51,7 @@ class Light : public Node {
NODE_SOCKET_API(Transform, tfm)
NODE_SOCKET_API(int, map_resolution)
+ NODE_SOCKET_API(float, average_radiance)
NODE_SOCKET_API(float, spot_angle)
NODE_SOCKET_API(float, spot_smooth)
diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp
index 775b4c0bc73..7fbaf9fb572 100644
--- a/intern/cycles/scene/light_tree.cpp
+++ b/intern/cycles/scene/light_tree.cpp
@@ -220,6 +220,13 @@ float LightTreePrimitive::calculate_energy(Scene *scene) const
else {
Light *lamp = scene->lights[lamp_id];
strength = lamp->get_strength();
+ LightType type = lamp->get_light_type();
+ if (type == LIGHT_AREA) {
+ strength *= 0.25f; /* eval_fac scaling in `area.h` */
+ }
+ else if (type == LIGHT_SPOT || type == LIGHT_POINT) {
+ strength *= 0.25f * M_1_PI_F; /* eval_fac scaling in `spot.h` and `point.h` */
+ }
}
return fabsf(scene->shader_manager->linear_rgb_to_gray(strength));