[Bf-blender-cvs] [b323b40af64] soc-2022-many-lights-sampling: Cycles: support emissive triangles in light tree
Jeffrey Liu
noreply at git.blender.org
Tue Jun 21 06:15:21 CEST 2022
Commit: b323b40af648c2a46bf1193c16ecc35916f26dba
Author: Jeffrey Liu
Date: Tue Jun 21 00:05:55 2022 -0400
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rBb323b40af648c2a46bf1193c16ecc35916f26dba
Cycles: support emissive triangles in light tree
===================================================================
M intern/cycles/kernel/light/light_tree.h
M intern/cycles/kernel/textures.h
M intern/cycles/kernel/types.h
M intern/cycles/scene/light.cpp
M intern/cycles/scene/light_tree.cpp
M intern/cycles/scene/scene.cpp
M intern/cycles/scene/scene.h
===================================================================
diff --git a/intern/cycles/kernel/light/light_tree.h b/intern/cycles/kernel/light/light_tree.h
index 1c9684e006c..ebc6d8280a2 100644
--- a/intern/cycles/kernel/light/light_tree.h
+++ b/intern/cycles/kernel/light/light_tree.h
@@ -77,29 +77,22 @@ ccl_device float light_tree_emitter_importance(KernelGlobals kg,
const float3 N,
int emitter_index)
{
- ccl_global const KernelLightDistribution *kdistribution = &kernel_tex_fetch(__light_distribution,
- emitter_index);
- const int prim = kdistribution->prim;
+ ccl_global const KernelLightTreeEmitter *kemitter = &kernel_tex_fetch(__light_tree_emitters,
+ emitter_index);
- if (prim >= 0) {
- /* to-do: handle case for mesh lights. */
- }
-
- /* If we're not at a mesh light, then we should be at a point, spot, or area light. */
- const int lamp = -prim - 1;
- const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp);
- const float radius = klight->spot.radius;
- const float3 bbox_min = make_float3(
- klight->co[0] - radius, klight->co[1] - radius, klight->co[2] - radius);
- const float3 bbox_max = make_float3(
- klight->co[0] + radius, klight->co[1] + radius, klight->co[2] + radius);
- const float3 bcone_axis = make_float3(
- klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
- const float3 rgb_strength = make_float3(
- klight->strength[0], klight->strength[1], klight->strength[2]);
+ /* Convert the data from the struct into float3 for calculations. */
+ const float3 bbox_min = make_float3(kemitter->bounding_box_min[0],
+ kemitter->bounding_box_min[1],
+ kemitter->bounding_box_min[2]);
+ const float3 bbox_max = make_float3(kemitter->bounding_box_max[0],
+ kemitter->bounding_box_max[1],
+ kemitter->bounding_box_max[2]);
+ const float3 bcone_axis = make_float3(kemitter->bounding_cone_axis[0],
+ kemitter->bounding_cone_axis[1],
+ kemitter->bounding_cone_axis[2]);
return light_tree_node_importance(
- P, N, bbox_min, bbox_max, bcone_axis, M_PI_F, M_PI_2_F, linear_rgb_to_gray(kg, rgb_strength));
+ P, N, bbox_min, bbox_max, bcone_axis, kemitter->theta_o, kemitter->theta_e, kemitter->energy);
}
ccl_device float light_tree_cluster_importance(KernelGlobals kg,
@@ -193,10 +186,36 @@ ccl_device bool light_tree_sample(KernelGlobals kg,
emitter_cdf += emitter_pdf;
if (tree_u < emitter_cdf) {
*pdf_factor *= emitter_pdf;
- if (UNLIKELY(light_select_reached_max_bounces(kg, prim_index, bounce))) {
+ ccl_global const KernelLightDistribution *kdistribution = &kernel_tex_fetch(__light_distribution,
+ prim_index);
+
+ /* to-do: this is the same code as light_distribution_sample, except the index is determined differently.
+ * Would it be better to refactor this into a separate function? */
+ const int prim = kdistribution->prim;
+
+ if (prim >= 0) {
+ /* Mesh light. */
+ const int object = kdistribution->mesh_light.object_id;
+
+ /* Exclude synthetic meshes from shadow catcher pass. */
+ if ((path_flag & PATH_RAY_SHADOW_CATCHER_PASS) &&
+ !(kernel_tex_fetch(__object_flag, object) & SD_OBJECT_SHADOW_CATCHER)) {
+ return false;
+ }
+
+ const int shader_flag = kdistribution->mesh_light.shader_flag;
+ triangle_light_sample<in_volume_segment>(kg, prim, object, randu, randv, time, ls, P);
+ ls->shader |= shader_flag;
+ return (ls->pdf > 0.0f);
+ }
+
+ const int lamp = -prim - 1;
+
+ if (UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) {
return false;
}
- return light_sample<in_volume_segment>(kg, prim_index, randu, randv, P, path_flag, ls);
+
+ return light_sample<in_volume_segment>(kg, lamp, randu, randv, P, path_flag, ls);
}
}
diff --git a/intern/cycles/kernel/textures.h b/intern/cycles/kernel/textures.h
index 58f0a312d9a..b08409be7c7 100644
--- a/intern/cycles/kernel/textures.h
+++ b/intern/cycles/kernel/textures.h
@@ -62,6 +62,7 @@ KERNEL_TEX(float2, __light_background_conditional_cdf)
/* light tree */
KERNEL_TEX(KernelLightTreeNode, __light_tree_nodes)
+KERNEL_TEX(KernelLightTreeEmitter, __light_tree_emitters)
/* particles */
KERNEL_TEX(KernelParticle, __particles)
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index 069c179fc73..5a5e1bcc220 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -1526,6 +1526,27 @@ typedef struct KernelLightTreeNode {
} KernelLightTreeNode;
static_assert_align(KernelLightTreeNode, 16);
+typedef struct KernelLightTreeEmitter {
+ /* Bounding box. */
+ float bounding_box_min[3];
+ float bounding_box_max[3];
+
+ /* Bounding cone. */
+ float bounding_cone_axis[3];
+ float theta_o;
+ float theta_e;
+
+ /* Energy. */
+ float energy;
+
+ /* If this is positive, this is a triangle. Otherwise, it's a light source. */
+ int prim_id;
+
+ /* Padding. */
+ int pad1, pad2, pad3;
+} KernelLightTreeEmitter;
+static_assert_align(KernelLightTreeEmitter, 16);
+
typedef struct KernelParticle {
int index;
float age;
diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp
index e9407554cbe..7d07b3797ab 100644
--- a/intern/cycles/scene/light.cpp
+++ b/intern/cycles/scene/light.cpp
@@ -350,6 +350,7 @@ void LightManager::device_update_distribution(Device *,
LightTree light_tree(light_prims, scene, 8);
light_prims = light_tree.get_prims();
+ /* First initialize the light tree's nodes. */
const vector<PackedLightTreeNode> &linearized_bvh = light_tree.get_nodes();
KernelLightTreeNode *light_tree_nodes = dscene->light_tree_nodes.alloc(linearized_bvh.size());
for (int index = 0; index < linearized_bvh.size(); index++) {
@@ -374,8 +375,28 @@ void LightManager::device_update_distribution(Device *,
light_tree_nodes[index].child_index = node.second_child_index;
}
}
-
dscene->light_tree_nodes.copy_to_device();
+
+ /* The light tree emitters store extra information about their bounds. */
+ KernelLightTreeEmitter *light_tree_emitters = dscene->light_tree_emitters.alloc(num_distribution);
+ for (int index = 0; index < num_distribution; index++) {
+ LightTreePrimitive &prim = light_prims[index];
+ BoundBox bbox = prim.calculate_bbox(scene);
+ OrientationBounds bcone = prim.calculate_bcone(scene);
+ float energy = prim.calculate_energy(scene);
+
+ light_tree_emitters[index].energy = energy;
+ for (int i = 0; i < 3; i++) {
+ light_tree_emitters[index].bounding_box_min[i] = bbox.min[i];
+ light_tree_emitters[index].bounding_box_max[i] = bbox.max[i];
+ light_tree_emitters[index].bounding_cone_axis[i] = bcone.axis[i];
+ }
+ light_tree_emitters[index].theta_o = bcone.theta_o;
+ light_tree_emitters[index].theta_e = bcone.theta_e;
+
+ light_tree_emitters[index].prim_id = prim.prim_id;
+ }
+ dscene->light_tree_emitters.copy_to_device();
}
/* triangles */
@@ -1099,6 +1120,7 @@ void LightManager::device_free(Device *, DeviceScene *dscene, const bool free_ba
{
/* to-do: check if the light tree member variables need to be wrapped in a conditional too*/
dscene->light_tree_nodes.free();
+ dscene->light_tree_emitters.free();
dscene->light_distribution.free();
dscene->lights.free();
if (free_background) {
diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp
index 22930586d43..252f15ab997 100644
--- a/intern/cycles/scene/light_tree.cpp
+++ b/intern/cycles/scene/light_tree.cpp
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
+#include "scene/mesh.h"
+#include "scene/object.h"
#include "scene/light_tree.h"
CCL_NAMESPACE_BEGIN
@@ -62,7 +64,27 @@ BoundBox LightTreePrimitive::calculate_bbox(Scene *scene) const
BoundBox bbox = BoundBox::empty;
if (prim_id >= 0) {
- /* to-do: handle mesh lights in the future. */
+ Object *object = scene->objects[object_id];
+ Mesh *mesh = static_cast<Mesh*>(object->get_geometry());
+ Mesh::Triangle triangle = mesh->get_triangle(prim_id - mesh->prim_offset);
+
+ float3 p[3] = {mesh->get_verts()[triangle.v[0]],
+ mesh->get_verts()[triangle.v[1]],
+ mesh->get_verts()[triangle.v[2]]};
+
+ /* 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++) {
+ p[i] = transform_point(&tfm, p[i]);
+ }
+ }
+
+ for (int i = 0; i < 3; i++) {
+ bbox.grow(p[i]);
+ }
}
else {
Light *lamp = scene->lights[lamp_id];
@@ -102,7 +124,29 @@ OrientationBounds LightTreePrimitive::calculate_bcone(Scene *scene) const
OrientationBounds bcone = OrientationBounds::empty;
if (prim_id >= 0) {
- /* to-do: handle mesh lights in the future. */
+ Object *object = scene->objects[object_id];
+ Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
+ Mesh::Triangle triangle = mesh->get_triangle(prim_id - mesh->prim_offset);
+
+ float3 p[3] = {mesh->get_verts()[triangle.v[0]],
+ mesh->get_verts()[triangle.v[1]],
+ mesh->get_verts()[triangle.v[2]]};
+
+ /* 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(
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list