[Bf-blender-cvs] [49f7bee879d] soc-2022-many-lights-sampling: Cleanup: group a few types and functions in the light tree to avoid computing some quantities twice
Weizhen Huang
noreply at git.blender.org
Tue Nov 15 20:34:16 CET 2022
Commit: 49f7bee879d8bf5fe64983a3fa2f3ce133c650d9
Author: Weizhen Huang
Date: Tue Nov 15 20:28:28 2022 +0100
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB49f7bee879d8bf5fe64983a3fa2f3ce133c650d9
Cleanup: group a few types and functions in the light tree to avoid
computing some quantities twice
===================================================================
M intern/cycles/kernel/light/tree.h
M intern/cycles/kernel/types.h
M intern/cycles/scene/light.cpp
M intern/cycles/scene/light_tree.cpp
M intern/cycles/scene/light_tree.h
===================================================================
diff --git a/intern/cycles/kernel/light/tree.h b/intern/cycles/kernel/light/tree.h
index 60e991723f5..0f3069af41b 100644
--- a/intern/cycles/kernel/light/tree.h
+++ b/intern/cycles/kernel/light/tree.h
@@ -223,15 +223,15 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
float min_distance, distance;
float max_distance = 0.0f;
float cos_theta_u = 1.0f;
- float3 centroid, point_to_centroid;
+ float3 centroid = make_float3(
+ kemitter->centroid[0], kemitter->centroid[1], kemitter->centroid[2]);
+ float3 point_to_centroid = safe_normalize_len(centroid - P, &distance);
bool bbox_is_visible = has_transmission;
const int prim = kemitter->prim_id;
if (prim < 0) {
const int lamp = -prim - 1;
const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp);
- centroid = make_float3(klight->co[0], klight->co[1], klight->co[2]);
- point_to_centroid = safe_normalize_len(centroid - P, &distance);
if (klight->type == LIGHT_SPOT || klight->type == LIGHT_POINT) {
const float radius = klight->spot.radius;
@@ -268,9 +268,6 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
const int object = kemitter->mesh_light.object_id;
float3 V[3];
triangle_world_space_vertices(kg, object, prim, -1.0f, V);
- /* TODO: store in KernelLightTreeEmitter */
- centroid = (V[0] + V[1] + V[2]) / 3.f;
- point_to_centroid = safe_normalize_len(centroid - P, &distance);
for (int i = 0; i < 3; i++) {
const float3 corner = V[i];
float distance_point_to_corner;
@@ -739,7 +736,7 @@ ccl_device float light_tree_distant_light_importance(KernelGlobals kg,
const float3 light_axis = make_float3(
kdistant->direction[0], kdistant->direction[1], kdistant->direction[2]);
- float theta_i = fast_acosf(dot(N, light_axis));
+ float theta_i = fast_acosf(dot(N, -light_axis));
/* If the light is guaranteed to be behind the surface we're sampling, and the surface is
* opaque, then we can give the light an importance of 0 as it contributes nothing to the
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index 01628cd97fe..2d0fba1074c 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -1366,9 +1366,7 @@ typedef struct KernelLightTreeNode {
static_assert_align(KernelLightTreeNode, 16);
typedef struct KernelLightTreeEmitter {
- /* Bounding box. */
- float bounding_box_min[3];
- float bounding_box_max[3];
+ float centroid[3];
/* Bounding cone. */
float bounding_cone_axis[3];
@@ -1386,18 +1384,21 @@ typedef struct KernelLightTreeEmitter {
int object_id;
} mesh_light;
struct {
- float pad;
+ float pad1;
float size;
} lamp;
};
/* Parent. */
int parent_index;
+
+ /* Padding */
+ float pad3[3];
} KernelLightTreeEmitter;
static_assert_align(KernelLightTreeEmitter, 16);
typedef struct KernelLightTreeDistantEmitter {
- /* Direction from world to light. */
+ /* Direction from light to world. */
float direction[3];
/* Size of light (in radians). */
diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp
index f5e68e479c6..af6623811a5 100644
--- a/intern/cycles/scene/light.cpp
+++ b/intern/cycles/scene/light.cpp
@@ -294,9 +294,8 @@ void LightManager::device_update_distribution(Device *device,
foreach (Light *light, scene->lights) {
if (light->is_enabled) {
if (light_tree_enabled) {
- LightTreePrimitive light_prim;
- light_prim.prim_id = ~device_light_index; /* -prim_id - 1 is a light source index. */
- light_prim.lamp_id = scene_light_index;
+ /* -prim_id - 1 is a light source index. */
+ LightTreePrimitive light_prim(scene, ~device_light_index, scene_light_index);
/* Distant lights get added to a separate vector. */
if (light->light_type == LIGHT_DISTANT || light->light_type == LIGHT_BACKGROUND) {
@@ -345,12 +344,8 @@ void LightManager::device_update_distribution(Device *device,
scene->default_surface;
if (shader->get_use_mis() && shader->has_surface_emission) {
- /* to-do: for the light tree implementation, we eventually want to include emissive
- * triangles. Right now, point lights are the main concern. */
if (light_tree_enabled) {
- LightTreePrimitive light_prim;
- light_prim.prim_id = i;
- light_prim.object_id = object_id;
+ LightTreePrimitive light_prim(scene, i, object_id);
light_prims.push_back(light_prim);
}
@@ -409,21 +404,17 @@ void LightManager::device_update_distribution(Device *device,
for (int i = 0; i < node.num_lights; i++) {
int emitter_index = i + node.first_prim_index;
LightTreePrimitive &prim = light_prims[emitter_index];
- BoundBox bbox = prim.calculate_bbox(scene);
- OrientationBounds bcone = prim.calculate_bcone(scene);
- float energy = prim.calculate_energy(scene);
- light_tree_emitters[emitter_index].energy = energy;
+ light_tree_emitters[emitter_index].energy = prim.energy;
for (int i = 0; i < 3; i++) {
- light_tree_emitters[emitter_index].bounding_box_min[i] = bbox.min[i];
- light_tree_emitters[emitter_index].bounding_box_max[i] = bbox.max[i];
- light_tree_emitters[emitter_index].bounding_cone_axis[i] = bcone.axis[i];
+ light_tree_emitters[emitter_index].centroid[i] = prim.centroid[i];
+ light_tree_emitters[emitter_index].bounding_cone_axis[i] = prim.bcone.axis[i];
}
- light_tree_emitters[emitter_index].theta_o = bcone.theta_o;
- light_tree_emitters[emitter_index].theta_e = bcone.theta_e;
+ light_tree_emitters[emitter_index].theta_o = prim.bcone.theta_o;
+ light_tree_emitters[emitter_index].theta_e = prim.bcone.theta_e;
- if (prim.prim_id >= 0) {
+ if (prim.is_triangle()) {
light_tree_emitters[emitter_index].mesh_light.object_id = prim.object_id;
int shader_flag = 0;
@@ -453,10 +444,9 @@ void LightManager::device_update_distribution(Device *device,
triangle_array[prim.prim_id + object_lookup_offsets[prim.object_id]] = emitter_index;
}
else {
- Light *lamp = scene->lights[prim.lamp_id];
+ Light *lamp = scene->lights[prim.object_id];
light_tree_emitters[emitter_index].prim_id = prim.prim_id;
light_tree_emitters[emitter_index].lamp.size = lamp->size;
- light_tree_emitters[emitter_index].lamp.pad = 1.0f;
light_array[~prim.prim_id] = emitter_index;
}
@@ -478,43 +468,19 @@ void LightManager::device_update_distribution(Device *device,
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];
- OrientationBounds light_bounds;
/* Lights in this group are either a background or distant light. */
light_tree_distant_group[index].prim_id = ~prim.prim_id;
- float energy = 0.0f;
- if (light->light_type == LIGHT_BACKGROUND) {
- /* 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;
- light_bounds.axis[1] = 0.0f;
- light_bounds.axis[2] = 1.0f;
-
- /* to-do: this may depend on portal lights as well. */
- light_bounds.theta_o = M_PI_F;
- }
- else {
- energy = prim.calculate_energy(scene);
-
- for (int i = 0; i < 3; i++) {
- light_bounds.axis[i] = -light->dir[i];
- }
- light_bounds.theta_o = tanf(light->angle * 0.5f);
- }
-
- distant_light_bounds = merge(distant_light_bounds, light_bounds);
+ distant_light_bounds = merge(distant_light_bounds, prim.bcone);
for (int i = 0; i < 3; i++) {
- light_tree_distant_group[index].direction[i] = light_bounds.axis[i];
+ light_tree_distant_group[index].direction[i] = prim.bcone.axis[i];
}
- light_tree_distant_group[index].bounding_radius = light_bounds.theta_o;
- light_tree_distant_group[index].energy = energy;
+ light_tree_distant_group[index].bounding_radius = prim.bcone.theta_o;
+ light_tree_distant_group[index].energy = prim.energy;
light_array[~prim.prim_id] = index;
- light_tree_distant_group[num_distant_lights].energy += energy;
+ light_tree_distant_group[num_distant_lights].energy += prim.energy;
}
/* The net OrientationBounds contain bounding information about all the distant lights. */
diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp
index 7fbaf9fb572..c9891fe6544 100644
--- a/intern/cycles/scene/light_tree.cpp
+++ b/intern/cycles/scene/light_tree.cpp
@@ -23,7 +23,7 @@ OrientationBounds merge(const OrientationBounds &cone_a, const OrientationBounds
if (is_zero(cone_a.axis)) {
return cone_b;
}
- else if (is_zero(cone_b.axis)) {
+ if (is_zero(cone_b.axis)) {
return cone_a;
}
@@ -43,61 +43,87 @@ OrientationBounds merge(const OrientationBounds &cone_a, const OrientationBounds
if (a->theta_o >= fminf(M_PI_F, theta_d + b->theta_o)) {
return OrientationBounds({a->axis, a->theta_o, theta_e});
}
- else {
- /* Compute new theta_o that contains both a and b. */
- float theta_o = (theta_d + a->theta_o + b->theta_o) * 0.5f;
- if (theta_o >= M_PI_F) {
- return OrientationBounds({a->axis, M_PI_F, theta_e});
- }
+ /* Compute new theta_o that contains both a and b. */
+ float theta_o = (theta_d + a->theta_o + b->theta_o) * 0.5f;
+
+ if (theta_o >= M_PI_F) {
+ return OrientationBounds({a->axis, M_PI_F, theta_e});
+ }
+
+ /* Rotate new axis to be between a and b. */
+ float theta_r = theta_o - a->theta_o;
+ float3 new_axis = rotate_around_axis(a->axis, cross(a->axis, b->axis), theta_r);
+ new_axis =
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list