Commit: 8ad56a0749e0bab4ad0664cdf97798ba30be9af8 Author: Jeffrey Liu Date: Thu Jul 21 16:44:00 2022 -0400 Branches: soc-2022-many-lights-sampling https://developer.blender.org/rB8ad56a0749e0bab4ad0664cdf97798ba30be9af8
Fix: light tree fails with instanced objects This fixes the issue with instanced objects. The issue was related to the fact that instanced objects were overwriting the same areas of the lookup table for the triangle to light tree array. =================================================================== M intern/cycles/kernel/data_arrays.h M intern/cycles/kernel/integrator/shade_surface.h M intern/cycles/scene/light.cpp M intern/cycles/scene/light_tree.cpp M intern/cycles/scene/light_tree.h M intern/cycles/scene/object.cpp M intern/cycles/scene/scene.cpp M intern/cycles/scene/scene.h =================================================================== diff --git a/intern/cycles/kernel/data_arrays.h b/intern/cycles/kernel/data_arrays.h index a22200c58eb..28fcfb4a2cf 100644 --- a/intern/cycles/kernel/data_arrays.h +++ b/intern/cycles/kernel/data_arrays.h @@ -65,6 +65,7 @@ KERNEL_DATA_ARRAY(KernelLightTreeNode, light_tree_nodes) KERNEL_DATA_ARRAY(KernelLightTreeEmitter, light_tree_emitters) KERNEL_DATA_ARRAY(KernelLightTreeDistantEmitter, light_tree_distant_group) KERNEL_DATA_ARRAY(uint, light_to_tree) +KERNEL_DATA_ARRAY(uint, object_lookup_offset) KERNEL_DATA_ARRAY(uint, triangle_to_tree) /* particles */ diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h index 7d403a84c1b..56fbad6711a 100644 --- a/intern/cycles/kernel/integrator/shade_surface.h +++ b/intern/cycles/kernel/integrator/shade_surface.h @@ -87,7 +87,9 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg, float3 ray_P = INTEGRATOR_STATE(state, ray, P); const float3 ray_D = INTEGRATOR_STATE(state, ray, D); const float3 N = INTEGRATOR_STATE(state, path, mis_origin_n); - pdf *= light_tree_pdf(kg, ray_P, N, sd->prim); + uint lookup_offset = kernel_data_fetch(object_lookup_offset, sd->object); + uint prim_offset = kernel_data_fetch(object_prim_offset, sd->object); + pdf *= light_tree_pdf(kg, ray_P, N, sd->prim - prim_offset + lookup_offset); } float mis_weight = light_sample_mis_weight_forward(kg, bsdf_pdf, pdf); L *= mis_weight; diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp index 3a193df9f17..8371bf71671 100644 --- a/intern/cycles/scene/light.cpp +++ b/intern/cycles/scene/light.cpp @@ -313,6 +313,7 @@ void LightManager::device_update_distribution(Device *device, bool light_tree_enabled = scene->integrator->get_use_light_tree(); vector<LightTreePrimitive> light_prims; vector<LightTreePrimitive> distant_lights; + vector<uint> object_lookup_offsets(scene->objects.size()); /* When we keep track of the light index, only contributing lights will be added to the device. * Therefore, we want to keep track of the light's index on the device. @@ -353,16 +354,19 @@ void LightManager::device_update_distribution(Device *device, if (progress.get_cancel()) return; - /* Count emissive triangles. */ - Mesh *mesh = static_cast<Mesh *>(object->get_geometry()); - size_t mesh_num_triangles = mesh->num_triangles(); - total_triangles += mesh_num_triangles; - if (!object_usable_as_light(object)) { object_id++; continue; } + if (light_tree_enabled) { + object_lookup_offsets[object_id] = total_triangles; + } + + /* Count emissive triangles. */ + Mesh *mesh = static_cast<Mesh *>(object->get_geometry()); + size_t mesh_num_triangles = mesh->num_triangles(); + for (size_t i = 0; i < mesh_num_triangles; i++) { int shader_index = mesh->get_shader()[i]; Shader *shader = (shader_index < mesh->get_used_shaders().size()) ? @@ -374,7 +378,7 @@ void LightManager::device_update_distribution(Device *device, * triangles. Right now, point lights are the main concern. */ if (light_tree_enabled) { LightTreePrimitive light_prim; - light_prim.prim_id = i + mesh->prim_offset; + light_prim.prim_id = i; light_prim.object_id = object_id; light_prims.push_back(light_prim); } @@ -383,6 +387,7 @@ void LightManager::device_update_distribution(Device *device, } } + total_triangles += mesh_num_triangles; object_id++; } @@ -398,8 +403,13 @@ void LightManager::device_update_distribution(Device *device, /* We want to create separate arrays corresponding to triangles and lights, * which will be used to index back into the light tree for PDF calculations. */ uint *light_array = dscene->light_to_tree.alloc(num_lights); + uint *object_offsets = dscene->object_lookup_offset.alloc(object_lookup_offsets.size()); uint *triangle_array = dscene->triangle_to_tree.alloc(total_triangles); + for (int i = 0; i < object_lookup_offsets.size(); i++) { + object_offsets[i] = object_lookup_offsets[i]; + } + /* 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()); @@ -445,13 +455,12 @@ void LightManager::device_update_distribution(Device *device, 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].prim_id = prim.prim_id; - if (prim.prim_id >= 0) { light_tree_emitters[emitter_index].mesh_light.object_id = prim.object_id; int shader_flag = 0; Object *object = scene->objects[prim.object_id]; + Mesh *mesh = static_cast<Mesh *>(object->get_geometry()); if (!(object->get_visibility() & PATH_RAY_CAMERA)) { shader_flag |= SHADER_EXCLUDE_CAMERA; } @@ -471,11 +480,13 @@ void LightManager::device_update_distribution(Device *device, shader_flag |= SHADER_EXCLUDE_SHADOW_CATCHER; } + light_tree_emitters[emitter_index].prim_id = prim.prim_id + mesh->prim_offset; light_tree_emitters[emitter_index].mesh_light.shader_flag = shader_flag; - triangle_array[prim.prim_id] = emitter_index; + triangle_array[prim.prim_id + object_lookup_offsets[prim.object_id]] = emitter_index; } else { Light *lamp = scene->lights[prim.lamp_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; @@ -557,6 +568,7 @@ void LightManager::device_update_distribution(Device *device, dscene->light_tree_emitters.copy_to_device(); dscene->light_tree_distant_group.copy_to_device(); dscene->light_to_tree.copy_to_device(); + dscene->object_lookup_offset.copy_to_device(); dscene->triangle_to_tree.copy_to_device(); } @@ -764,6 +776,7 @@ void LightManager::device_update_distribution(Device *device, dscene->light_tree_emitters.free(); dscene->light_tree_distant_group.free(); dscene->light_to_tree.free(); + dscene->object_lookup_offset.free(); dscene->triangle_to_tree.free(); } dscene->light_distribution.free(); diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp index 2c3c8cb880f..2db19912f50 100644 --- a/intern/cycles/scene/light_tree.cpp +++ b/intern/cycles/scene/light_tree.cpp @@ -73,7 +73,7 @@ BoundBox LightTreePrimitive::calculate_bbox(Scene *scene) const if (prim_id >= 0) { 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); + Mesh::Triangle triangle = mesh->get_triangle(prim_id); float3 p[3] = {mesh->get_verts()[triangle.v[0]], mesh->get_verts()[triangle.v[1]], @@ -133,7 +133,7 @@ OrientationBounds LightTreePrimitive::calculate_bcone(Scene *scene) const if (prim_id >= 0) { 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); + Mesh::Triangle triangle = mesh->get_triangle(prim_id); float3 p[3] = {mesh->get_verts()[triangle.v[0]], mesh->get_verts()[triangle.v[1]], @@ -196,8 +196,8 @@ float LightTreePrimitive::calculate_energy(Scene *scene) const if (prim_id >= 0) { 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); - Shader *shader = static_cast<Shader*>(mesh->get_used_shaders()[mesh->get_shader()[prim_id - mesh->prim_offset]]); + Mesh::Triangle triangle = mesh->get_triangle(prim_id); + 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. */ if (!shader->is_constant_emission(&strength)) { diff --git a/intern/cycles/scene/light_tree.h b/intern/cycles/scene/light_tree.h index 0a768d32b2f..ff333a0d3b0 100644 --- a/intern/cycles/scene/light_tree.h +++ b/intern/cycles/scene/light_tree.h @@ -67,7 +67,7 @@ struct LightTreePrimitiveInfo { /* Light Tree Primitive * Struct that indexes into the scene's triangle and light arrays. */ struct LightTreePrimitive { - /* prim_id >= 0 is an index into the global triangle index, + /* prim_id >= 0 is an index into an object's local triangle index, * otherwise -prim_id-1 is an index into device lights array. * */ int prim_id; diff --git a/intern/cycles/scene/object.cpp b/intern/cycles/scene/object.cpp index 2126b23d82e..b3848c58501 100644 --- a/intern/cycles/scene/object.cpp +++ b/intern/cycles/scene/object.cpp @@ -558,10 +558,12 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s void ObjectManager::device_update_prim_offsets(Device *device, DeviceScene *dscene, Scene *scene) { - BVHLayoutMask layout_mask = device->get_bvh_layout_mask(); - if (layout_mask != BVH_LAYOUT_METAL && layout_mask != BVH_LAYOUT_MULTI_METAL && - layout_mask != BVH_LAYOUT_MULTI_METAL_EMBREE) { - return; + if (!scene->integrator->get_use_light_tree()) { + BVHLayoutMask layout_mask = device->get_bvh_layout_mask(); + if (layout_mask != BVH_LAYOUT_METAL && layout_mask != BVH_LAYOUT_MULTI_METAL && + layout_mask != BVH_LAYOUT_MULTI_METAL_EMBREE) { + return; + } } /* On MetalRT, primitive / curve segment offsets can't be baked at BVH build time. Intersection diff --git a/intern/cycles/scene/scene.cpp b/intern/cycles/scene/scene @@ 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