[Bf-blender-cvs] [9a89fca8b13] soc-2022-many-lights-sampling: Refactor: reduce the size of `LightTreePrimitive`
Weizhen Huang
noreply at git.blender.org
Mon Nov 21 11:49:05 CET 2022
Commit: 9a89fca8b13f02925693d92f874b6f874ba9a21b
Author: Weizhen Huang
Date: Mon Nov 21 11:45:58 2022 +0100
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB9a89fca8b13f02925693d92f874b6f874ba9a21b
Refactor: reduce the size of `LightTreePrimitive`
===================================================================
M intern/cycles/scene/light_tree.cpp
M intern/cycles/scene/light_tree.h
===================================================================
diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp
index 2973f21ba9a..fca8345150f 100644
--- a/intern/cycles/scene/light_tree.cpp
+++ b/intern/cycles/scene/light_tree.cpp
@@ -62,95 +62,37 @@ OrientationBounds merge(const OrientationBounds &cone_a, const OrientationBounds
LightTreePrimitive::LightTreePrimitive(Scene *scene, int prim_id, int object_id)
: prim_id(prim_id), object_id(object_id)
{
- if (is_triangle()) {
- calculate_triangle_vertices(scene);
- }
- calculate_centroid(scene);
- calculate_bbox(scene);
- calculate_bcone(scene);
- calculate_energy(scene);
-}
-
-void LightTreePrimitive::calculate_triangle_vertices(Scene *scene)
-{
- assert(is_triangle());
- Object *object = scene->objects[object_id];
- Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
- Mesh::Triangle triangle = mesh->get_triangle(prim_id);
-
- for (int i = 0; i < 3; i++) {
- vertices[i] = mesh->get_verts()[triangle.v[i]];
- }
-
- /* instanced mesh lights have not applied their transform at this point.
- * in this case, these points have to be transformed to get the proper
- * spatial bound. */
- if (!mesh->transform_applied) {
- const Transform &tfm = object->get_tfm();
- for (int i = 0; i < 3; i++) {
- vertices[i] = transform_point(&tfm, vertices[i]);
- }
- }
-}
-
-void LightTreePrimitive::calculate_centroid(Scene *scene)
-{
- if (is_triangle()) {
- /* NOTE: the original implementation used the bounding box centroid, but primitive centroid
- * seems to work fine */
- centroid = (vertices[0] + vertices[1] + vertices[2]) / 3.0f;
- }
- else {
- centroid = scene->lights[object_id]->get_co();
- }
-}
-
-void LightTreePrimitive::calculate_bbox(Scene *scene)
-{
+ bcone = OrientationBounds::empty;
bbox = BoundBox::empty;
if (is_triangle()) {
- for (int i = 0; i < 3; i++) {
- bbox.grow(vertices[i]);
- }
- }
- else {
- Light *lamp = scene->lights[object_id];
- LightType type = lamp->get_light_type();
- const float size = lamp->get_size();
+ float3 vertices[3];
+ Object *object = scene->objects[object_id];
+ Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
+ Mesh::Triangle triangle = mesh->get_triangle(prim_id);
+ Shader *shader = static_cast<Shader *>(mesh->get_used_shaders()[mesh->get_shader()[prim_id]]);
- if (type == LIGHT_POINT || type == LIGHT_SPOT) {
- /* Point and spot lights can emit light from any point within its radius. */
- const float3 radius = make_float3(size);
- bbox.grow(centroid - radius);
- bbox.grow(centroid + radius);
+ for (int i = 0; i < 3; i++) {
+ vertices[i] = mesh->get_verts()[triangle.v[i]];
}
- else if (type == LIGHT_AREA) {
- /* For an area light, sizeu and sizev determine the 2 dimensions of the area light,
- * while axisu and axisv determine the orientation of the 2 dimensions.
- * We want to add all 4 corners to our bounding box. */
- const float3 half_extentu = 0.5 * lamp->get_sizeu() * lamp->get_axisu() * size;
- const float3 half_extentv = 0.5 * lamp->get_sizev() * lamp->get_axisv() * size;
- bbox.grow(centroid + half_extentu + half_extentv);
- bbox.grow(centroid + half_extentu - half_extentv);
- bbox.grow(centroid - half_extentu + half_extentv);
- bbox.grow(centroid - half_extentu - half_extentv);
- }
- else {
- /* No bounding box for distant lights */
+ /* instanced mesh lights have not applied their transform at this point.
+ * in this case, these points have to be transformed to get the proper
+ * spatial bound. */
+ if (!mesh->transform_applied) {
+ const Transform &tfm = object->get_tfm();
+ for (int i = 0; i < 3; i++) {
+ vertices[i] = transform_point(&tfm, vertices[i]);
+ }
}
- }
-}
-void LightTreePrimitive::calculate_bcone(Scene *scene)
-{
- bcone = OrientationBounds::empty;
+ /* TODO: need a better way to handle this when textures are used. */
+ float area = triangle_area(vertices[0], vertices[1], vertices[2]);
+ energy = area * scene->shader_manager->linear_rgb_to_gray(shader->emission_estimate);
- if (is_triangle()) {
- Object *object = scene->objects[object_id];
- Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
- Shader *shader = static_cast<Shader *>(mesh->get_used_shaders()[mesh->get_shader()[prim_id]]);
+ /* NOTE: the original implementation used the bounding box centroid, but primitive centroid
+ * seems to work fine */
+ centroid = (vertices[0] + vertices[1] + vertices[2]) / 3.0f;
if (shader->emission_sampling == EMISSION_SAMPLING_FRONT) {
/* Front only. */
@@ -167,30 +109,58 @@ void LightTreePrimitive::calculate_bcone(Scene *scene)
bcone.axis = safe_normalize(vertices[0] - vertices[1]);
bcone.theta_o = M_PI_2_F;
}
-
bcone.theta_e = M_PI_2_F;
+
+ for (int i = 0; i < 3; i++) {
+ bbox.grow(vertices[i]);
+ }
}
else {
Light *lamp = scene->lights[object_id];
LightType type = lamp->get_light_type();
+ const float size = lamp->get_size();
+ float3 strength = lamp->get_strength();
+ centroid = scene->lights[object_id]->get_co();
bcone.axis = normalize(lamp->get_dir());
- if (type == LIGHT_POINT) {
+ if (type == LIGHT_AREA) {
+ bcone.theta_o = 0;
+ bcone.theta_e = lamp->get_spread() * 0.5f;
+
+ /* For an area light, sizeu and sizev determine the 2 dimensions of the area light,
+ * while axisu and axisv determine the orientation of the 2 dimensions.
+ * We want to add all 4 corners to our bounding box. */
+ const float3 half_extentu = 0.5 * lamp->get_sizeu() * lamp->get_axisu() * size;
+ const float3 half_extentv = 0.5 * lamp->get_sizev() * lamp->get_axisv() * size;
+ bbox.grow(centroid + half_extentu + half_extentv);
+ bbox.grow(centroid + half_extentu - half_extentv);
+ bbox.grow(centroid - half_extentu + half_extentv);
+ bbox.grow(centroid - half_extentu - half_extentv);
+
+ strength *= 0.25f; /* eval_fac scaling in `area.h` */
+ }
+ else if (type == LIGHT_POINT) {
bcone.theta_o = M_PI_F;
bcone.theta_e = M_PI_2_F;
+
+ /* Point and spot lights can emit light from any point within its radius. */
+ const float3 radius = make_float3(size);
+ bbox.grow(centroid - radius);
+ bbox.grow(centroid + radius);
+
+ strength *= 0.25f * M_1_PI_F; /* eval_fac scaling in `spot.h` and `point.h` */
}
else if (type == LIGHT_SPOT) {
bcone.theta_o = 0;
bcone.theta_e = lamp->get_spot_angle() * 0.5f;
- }
- else if (type == LIGHT_AREA) {
- bcone.theta_o = 0;
- bcone.theta_e = lamp->get_spread() * 0.5f;
- }
- else if (type == LIGHT_DISTANT) {
- bcone.theta_o = tanf(0.5f * lamp->get_angle());
- bcone.theta_e = 0;
+
+ /* Point and spot lights can emit light from any point within its radius. */
+ const float3 radius = make_float3(size);
+ bbox.grow(centroid - radius);
+ bbox.grow(centroid + radius);
+
+ strength *= 0.25f * M_1_PI_F; /* eval_fac scaling in `spot.h` and `point.h` */
}
else if (type == LIGHT_BACKGROUND) {
/* Set an arbitrary direction for the background light. */
@@ -198,36 +168,14 @@ void LightTreePrimitive::calculate_bcone(Scene *scene)
/* TODO: this may depend on portal lights as well. */
bcone.theta_o = M_PI_F;
bcone.theta_e = 0;
- }
- }
-}
-
-void LightTreePrimitive::calculate_energy(Scene *scene)
-{
- if (is_triangle()) {
- Object *object = scene->objects[object_id];
- Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
- Shader *shader = static_cast<Shader *>(mesh->get_used_shaders()[mesh->get_shader()[prim_id]]);
-
- /* to-do: need a better way to handle this when textures are used. */
- float area = triangle_area(vertices[0], vertices[1], vertices[2]);
- energy = area * scene->shader_manager->linear_rgb_to_gray(shader->emission_estimate);
- }
- else {
- Light *lamp = scene->lights[object_id];
- LightType type = lamp->get_light_type();
- float3 strength = lamp->get_strength();
- 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` */
- }
- else if (type == LIGHT_BACKGROUND) {
/* integrate over cosine-weighted hemisphere */
strength *= lamp->get_average_radiance() * M_PI_F;
}
+ else if (type == LIGHT_DISTANT) {
+ bcone.theta_o = tanf(0.5f * lamp->get_angle());
+ bcone.theta_e = 0;
+ }
if (lamp->get_shader()) {
strength *= lamp->get_shader()->emission_estimate;
@@ -342,7 +290,8 @@ LightTreeBuildNode *LightTree::recursive_build(int start,
* If the best split cost is no better than making a leaf node, make a leaf instead.*/
float min_cost = min_split_saoh(
centroid_bounds, start, end, node_bbox, node_bcone, min_dim, min_bucket);
- should_split = num_prims > max_lights_in_leaf_ || min_cost < energy_total;
+ should_split = (num_prims > max_lights_in_leaf_ || min_cost < energy_total) &&
+ energy_total > 1e-3f;
}
if (should_split) {
int middle;
diff --git a/intern/cycles/scene/light_tree.h b/intern/cycles/scene/light_tree.h
index b1268755644..c1f56ceab81 100644
--- a/intern/cycles/scene/light_tree.h
+++ b/intern/cycles/scene/light_tree.h
@@ -61,23 +61,15 @@ struct LightTreePrimitive {
int prim_id;
int object_id;
- /* Only used for emissive triangles */
- float3 vertices[3];
-
+ int prim_num;
+ float energy;
float3 centroid;
- BoundBox bbox;
OrientationBounds bcone;
- float energy;
- int prim_num;
+ BoundBox bbox;
LightTreePrimitive(Scene *scene, int prim_id, int object_id);
- void calculate_triangle_vertices(Scene *scene);
- void calculate_centroid(Scene *scene);
- void calculate_bbox(Scene *scene);
- void calculate_bcone(Scene *scene);
- void calculate_energy(Scene *scene);
- bool is_triangle() const
+ inline bool is_triangle() const
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list