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. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs