[Bf-blender-cvs] [d32f60b85e4] soc-2022-many-lights-sampling: begin implementation of cycles light tree
Jebbly
noreply at git.blender.org
Fri Jun 10 16:32:58 CEST 2022
Commit: d32f60b85e4c296622350bf6d8814f4f8ed1127f
Author: Jebbly
Date: Wed Apr 13 17:50:17 2022 -0500
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rBd32f60b85e4c296622350bf6d8814f4f8ed1127f
begin implementation of cycles light tree
===================================================================
M intern/cycles/blender/addon/presets.py
M intern/cycles/blender/addon/properties.py
M intern/cycles/blender/addon/ui.py
M intern/cycles/blender/sync.cpp
M intern/cycles/scene/CMakeLists.txt
M intern/cycles/scene/integrator.cpp
M intern/cycles/scene/integrator.h
M intern/cycles/scene/light.cpp
A intern/cycles/scene/light_tree.cpp
A intern/cycles/scene/light_tree.h
M intern/cycles/scene/scene.cpp
M intern/cycles/scene/scene.h
===================================================================
diff --git a/intern/cycles/blender/addon/presets.py b/intern/cycles/blender/addon/presets.py
index cc6d574da99..82c3091a619 100644
--- a/intern/cycles/blender/addon/presets.py
+++ b/intern/cycles/blender/addon/presets.py
@@ -49,6 +49,8 @@ class AddPresetSampling(AddPresetBase, Operator):
"cycles.samples",
"cycles.adaptive_threshold",
"cycles.adaptive_min_samples",
+ "cycles.use_light_tree",
+ "cycles.splitting_threshold",
"cycles.time_limit",
"cycles.use_denoising",
"cycles.denoiser",
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index b444a806f8d..a391be0bca2 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -471,6 +471,19 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default='MULTIPLE_IMPORTANCE_SAMPLING',
)
+ use_light_tree: BoolProperty(
+ name="Light Tree",
+ description="Samples many lights more efficiently",
+ default=False,
+ )
+
+ splitting_threshold: FloatProperty(
+ name="Splitting",
+ description="Amount of lights to sample at a time, from one light at 0.0, to adaptively more lights as needed, to all lights at 1.0",
+ min=0.0, max=1.0,
+ default=0.85,
+ )
+
min_light_bounces: IntProperty(
name="Min Light Bounces",
description="Minimum number of light bounces. Setting this higher reduces noise in the first bounces, "
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 88be546746d..0194664c222 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -310,6 +310,34 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
layout.row().prop(cscene, "use_layer_samples")
break
+class CYCLES_RENDER_PT_sampling_light_tree(CyclesButtonsPanel, Panel):
+ bl_label = "Many Lights Sampling"
+ bl_parent_id = "CYCLES_RENDER_PT_sampling"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.scene.cycles.feature_set == 'EXPERIMENTAL')
+
+ def draw_header(self, context):
+ layout = self.layout
+ scene = context.scene
+ cscene = scene.cycles
+
+ layout.prop(cscene, "use_light_tree", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ scene = context.scene
+ cscene = scene.cycles
+
+ layout.active = cscene.use_light_tree
+ col = layout.column(align=True)
+ col.prop(cscene, "splitting_threshold", text="Split Threshold")
+
class CYCLES_RENDER_PT_subdivision(CyclesButtonsPanel, Panel):
bl_label = "Subdivision"
@@ -2269,6 +2297,7 @@ classes = (
CYCLES_RENDER_PT_sampling_render,
CYCLES_RENDER_PT_sampling_render_denoise,
CYCLES_RENDER_PT_sampling_advanced,
+ CYCLES_RENDER_PT_sampling_light_tree,
CYCLES_RENDER_PT_light_paths,
CYCLES_RENDER_PT_light_paths_max_bounces,
CYCLES_RENDER_PT_light_paths_clamping,
diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp
index 1028c940772..e008443531f 100644
--- a/intern/cycles/blender/sync.cpp
+++ b/intern/cycles/blender/sync.cpp
@@ -340,6 +340,8 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
integrator->set_motion_blur(view_layer.use_motion_blur);
}
+ integrator->set_use_light_tree(get_boolean(cscene, "use_light_tree"));
+ integrator->set_splitting_threshold(get_float(cscene, "splitting_threshold"));
integrator->set_light_sampling_threshold(get_float(cscene, "light_sampling_threshold"));
SamplingPattern sampling_pattern = (SamplingPattern)get_enum(
diff --git a/intern/cycles/scene/CMakeLists.txt b/intern/cycles/scene/CMakeLists.txt
index 4904bf247ba..32e9fd09b82 100644
--- a/intern/cycles/scene/CMakeLists.txt
+++ b/intern/cycles/scene/CMakeLists.txt
@@ -25,6 +25,7 @@ set(SRC
integrator.cpp
jitter.cpp
light.cpp
+ light_tree.cpp
mesh.cpp
mesh_displace.cpp
mesh_subdivision.cpp
@@ -64,6 +65,7 @@ set(SRC_HEADERS
image_vdb.h
integrator.h
light.h
+ light_tree.h
jitter.h
mesh.h
object.h
diff --git a/intern/cycles/scene/integrator.cpp b/intern/cycles/scene/integrator.cpp
index fda6ecc8d14..7df74614d93 100644
--- a/intern/cycles/scene/integrator.cpp
+++ b/intern/cycles/scene/integrator.cpp
@@ -84,7 +84,9 @@ NODE_DEFINE(Integrator)
SOCKET_FLOAT(adaptive_threshold, "Adaptive Threshold", 0.01f);
SOCKET_INT(adaptive_min_samples, "Adaptive Min Samples", 0);
- SOCKET_FLOAT(light_sampling_threshold, "Light Sampling Threshold", 0.01f);
+ SOCKET_FLOAT(light_sampling_threshold, "Light Sampling Threshold", 0.05f);
+ SOCKET_BOOLEAN(use_light_tree, "Use light tree to optimize many light sampling", false);
+ SOCKET_FLOAT(splitting_threshold, "Splitting threshold (NEED EDITING)", 0.85f);
static NodeEnum sampling_pattern_enum;
sampling_pattern_enum.insert("sobol", SAMPLING_PATTERN_SOBOL);
diff --git a/intern/cycles/scene/integrator.h b/intern/cycles/scene/integrator.h
index d54a44b6177..1d9604d58f1 100644
--- a/intern/cycles/scene/integrator.h
+++ b/intern/cycles/scene/integrator.h
@@ -68,6 +68,8 @@ class Integrator : public Node {
NODE_SOCKET_API(int, start_sample)
NODE_SOCKET_API(float, light_sampling_threshold)
+ NODE_SOCKET_API(bool, use_light_tree)
+ NODE_SOCKET_API(float, splitting_threshold)
NODE_SOCKET_API(bool, use_adaptive_sampling)
NODE_SOCKET_API(int, adaptive_min_samples)
diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp
index 5e311d3051f..402fca968ac 100644
--- a/intern/cycles/scene/light.cpp
+++ b/intern/cycles/scene/light.cpp
@@ -24,6 +24,8 @@
#include "util/progress.h"
#include "util/task.h"
+#include <iostream>
+
CCL_NAMESPACE_BEGIN
static void shade_background_pixels(Device *device,
@@ -389,6 +391,7 @@ void LightManager::device_update_distribution(Device *,
}
float trianglearea = totarea;
+ std::cout << "TOTAL AREA: " << trianglearea << std::endl;
/* point lights */
bool use_lamp_mis = false;
int light_index = 0;
diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp
new file mode 100644
index 00000000000..c0baa35ab74
--- /dev/null
+++ b/intern/cycles/scene/light_tree.cpp
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
+
+#include "scene/light_tree.h"
+
+CCL_NAMESPACE_BEGIN
+
+float OrientationBounds::calculate_measure() const
+{
+ float theta_w = fminf(M_PI_F, theta_o + theta_e);
+ float cos_theta_o = cosf(theta_o);
+ float sin_theta_o = sinf(theta_o);
+
+ return M_2PI_F * (1 - cos_theta_o) +
+ M_PI_2_F * (2 * theta_w * sin_theta_o - cosf(theta_o - 2 * theta_w) -
+ 2 * theta_o * sin_theta_o + cos_theta_o);
+}
+
+OrientationBounds merge(const OrientationBounds& cone_a,
+ const OrientationBounds& cone_b)
+{
+ /* Set cone a to always have the greater theta_o. */
+ const OrientationBounds *a = &cone_a;
+ const OrientationBounds *b = &cone_b;
+ if (cone_b.theta_o > cone_a.theta_o) {
+ a = &cone_b;
+ b = &cone_a;
+ }
+
+ float theta_d = safe_acosf(dot(a->axis, b->axis));
+ float theta_e = fmaxf(a->theta_e, b->theta_e);
+
+ /* Return axis and theta_o of a if it already contains b. */
+ 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) / 2;
+
+ if (theta_o > M_PI_F) {
+ return OrientationBounds({a->axis, M_PI_F, theta_e});
+ }
+
+ /* TODO: test if vectors can just be averaged. */
+ /* 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 = normalize(new_axis);
+
+ return OrientationBounds({new_axis, theta_o, theta_e});
+ }
+}
+
+void LightTreeBuildNode::init_leaf(
+ uint offset, uint n, const BoundBox &b, const OrientationBounds &c, float e, float e_var)
+{
+ bbox = b;
+ bcone = c;
+ energy = e;
+ energy_variance = e_var;
+ first_prim_index = offset;
+ num_lights = n;
+
+ children[0] = children[1] = nullptr;
+ is_leaf = true;
+}
+
+void LightTreeBuildNode::init_interior(LightTreeBuildNode *c0, LightTreeBuildNode *c1)
+{
+ bbox = merge(c0->bbox, c1->bbox);
+ bcone = merge(c0->bcone, c1->bcone);
+ energy = c0->energy + c1->energy;
+ energy_variance = c0->energy_variance + c1->energy_variance;
+ first_prim_index = 0;
+ num_lights = 0;
+
+ children[0] = c0;
+ children[1] = c1;
+ is_leaf = false;
+}
+
+LightTree::LightTree(const vector<LightTreePrimitive> &prims, Scene *scene, uint max_lights_in_leaf)
+{
+ prims_ = prims;
+ scene_ = scene;
+ max_lights_in_leaf_ = max_lights_in_leaf;
+
+ vector<LightTreePrimitiveInfo> build_data(prims.size());
+ for (int i = 0; i < prims.size(); i++) {
+ LightTreePrimitiveInfo prim_info;
+ prim_info.bbox = calculate_bbox(prims[i]);
+ prim_info.bcone = calculate_bcone(prims[i]);
+ prim_info.energy = calculate_energy(prims[i]);
+ prim_info.centroid = prim_info.bbox.center();
+ prim_info.prim_num = i;
+ build_data.push_back(prim_info);
+ }
+
+ int total_nodes = 0;
+ vector<LightTreePrimitive> ordered_prims;
+ LightTreeBuildNode *root;
+ root = recursive_build(build_data, 0, prims.size(), total_nodes, ordered_prims);
+ prims_ = ordered_prims;
+}
+
+LightTreeBuildNode *LightTree::recursive_build(vector<LightTreePrimitiveInfo> &primitive_info,
+ int start,
+ int end,
+ int &total_nodes,
+ vector<LightTreePrimitive> &ordered_prims)
+{
+ LightTreeBuildNode *node = new LightTreeBuildNode();
+ total_nodes++;
+ BoundBox node
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list