Commit: 2e17c3f3a10bb2f6a62b1e8d5d236c437f7ae4e8 Author: Erik Englesson Date: Thu May 31 08:25:44 2018 +0200 Branches: gsoc-2018-many-light-sampling https://developer.blender.org/rB2e17c3f3a10bb2f6a62b1e8d5d236c437f7ae4e8
Added simple construction and sampling code for light BVH The light BVH is created on the host out of all emissive triangles and all lights in the scene. The nodes of the light BVH is then copied to the device where it is used when sampling lights. When a light is asked for it traverses the light BVH randomly to find a single light. This is still very much in development. =================================================================== M CMakeLists.txt M intern/cycles/kernel/kernel_light.h M intern/cycles/kernel/kernel_textures.h M intern/cycles/render/CMakeLists.txt M intern/cycles/render/light.cpp M intern/cycles/render/light.h A intern/cycles/render/light_tree.cpp A intern/cycles/render/light_tree.h M intern/cycles/render/scene.cpp M intern/cycles/render/scene.h =================================================================== diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ffe87da673..0b9cfd551a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -212,6 +212,7 @@ option(WITH_BUILDINFO "Include extra build details (only disable for develop if(${CMAKE_VERSION} VERSION_LESS 2.8.8) # add_library OBJECT arg unsupported set(WITH_BUILDINFO OFF) +set(WITH_BUILDINFO OFF) endif() set(BUILDINFO_OVERRIDE_DATE "" CACHE STRING "Use instead of the current date for reproducable builds (empty string disables this option)") set(BUILDINFO_OVERRIDE_TIME "" CACHE STRING "Use instead of the current time for reproducable builds (empty string disables this option)") @@ -407,7 +408,7 @@ mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH) unset(PLATFORM_DEFAULT) option(WITH_CYCLES_LOGGING "Build Cycles with logging support" ON) option(WITH_CYCLES_DEBUG "Build Cycles with extra debug capabilities" OFF) -option(WITH_CYCLES_NATIVE_ONLY "Build Cycles with native kernel only (which fits current CPU, use for development only)" OFF) +option(WITH_CYCLES_NATIVE_ONLY "Build Cycles with native kernel only (which fits current CPU, use for development only)" ON) mark_as_advanced(WITH_CYCLES_CUBIN_COMPILER) mark_as_advanced(WITH_CYCLES_LOGGING) mark_as_advanced(WITH_CYCLES_DEBUG) diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index ec7203d36eb..e540cdf9523 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -503,7 +503,7 @@ ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 if(cos_pi <= 0.0f) return 0.0f; - + return t*t/cos_pi; } @@ -1078,6 +1078,88 @@ ccl_device bool light_select_reached_max_bounces(KernelGlobals *kg, int index, i return (bounce > kernel_tex_fetch(__lights, index).max_bounces); } +ccl_device float calc_node_importance(KernelGlobals *kg, float3 P, int node_offset) +{ + float4 node0 = kernel_tex_fetch(__light_tree_nodes, node_offset + 0); + float4 node1 = kernel_tex_fetch(__light_tree_nodes, node_offset + 1); + float4 node2 = kernel_tex_fetch(__light_tree_nodes, node_offset + 2); + float4 node3 = kernel_tex_fetch(__light_tree_nodes, node_offset + 3); + + float energy = node0[0]; // TODO: This energy is not set correctly on host + float3 bboxMin = make_float3( node1[0], node1[1], node1[2]); + float3 bboxMax = make_float3( node1[3], node2[0], node2[1]); + float theta_o = node2[2]; + float theta_e = node2[3]; + float3 axis = make_float3(node3[0], node3[1], node3[2]); + float3 centroid = 0.5f*(bboxMax + bboxMin); + + float3 centroidToP = P-centroid; + float theta = acosf(dot(axis,normalize(centroidToP))); + float theta_u = 0; // TODO: Figure out how to calculate this one + float d2 = len_squared(centroidToP); + + return energy * cosf(clamp(theta - theta_o - theta_u, 0.0, theta_e))/d2; +} + +ccl_device void update_parent_node(KernelGlobals *kg, int node_offset, + int *childOffset, int *distribution_id, + int *nemitters) +{ + float4 node = kernel_tex_fetch(__light_tree_nodes, node_offset); + (*childOffset) = __float_as_int(node[1]); + (*distribution_id) = __float_as_int(node[2]); + (*nemitters) = __float_as_int(node[3]); +} + +ccl_device int sample_light_bvh(KernelGlobals *kg, float3 P, float randu) +{ + int index = -1; + + /* read in first part of root node of light BVH */ + int secondChildOffset, distribution_id, nemitters; + update_parent_node(kg, 0, &secondChildOffset, &distribution_id, &nemitters); + + int offset = 0; + do{ + + /* Found a leaf - Choose which light to use */ + if(nemitters > 0){ // Found a leaf + if(nemitters == 1){ + index = distribution_id; + } else { // Leaf with several lights. Pick one randomly. + light_distribution_sample(kg, &randu); // TODO: Rescale random number in a better way + int light = min((int)(randu* (float)nemitters), nemitters-1); + index = distribution_id +light; + } + break; + } else { // Interior node, pick left or right randomly + + /* calculate probability of going down left node */ + int child_offsetL = offset + 4; + int child_offsetR = 4*secondChildOffset; + float I_L = calc_node_importance(kg, P, child_offsetL); + float I_R = calc_node_importance(kg, P, child_offsetR); + float P_L = I_L / ( I_L + I_R); + + /* choose which node to go down */ + light_distribution_sample(kg, &randu); // TODO: Rescale random number in a better way + if(randu <= P_L){ // Going down left node + offset = child_offsetL; + } else { // Going down right node + offset = child_offsetR; + } + + /* update parent node info for next iteration */ + update_parent_node(kg, offset, &secondChildOffset, + &distribution_id, &nemitters); + } + + + } while(1); + + return index; +} + ccl_device_noinline bool light_sample(KernelGlobals *kg, float randu, float randv, @@ -1087,7 +1169,8 @@ ccl_device_noinline bool light_sample(KernelGlobals *kg, LightSample *ls) { /* sample index */ - int index = light_distribution_sample(kg, &randu); + //int index = light_distribution_sample(kg, &randu); + int index = sample_light_bvh(kg, P, randu); /* fetch light data */ const ccl_global KernelLightDistribution *kdistribution = &kernel_tex_fetch(__light_distribution, index); diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index a7b8c492ee9..ddd96842352 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -64,6 +64,7 @@ KERNEL_TEX(KernelLightDistribution, __light_distribution) KERNEL_TEX(KernelLight, __lights) KERNEL_TEX(float2, __light_background_marginal_cdf) KERNEL_TEX(float2, __light_background_conditional_cdf) +KERNEL_TEX(float4, __light_tree_nodes) /* particles */ KERNEL_TEX(KernelParticle, __particles) diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index b7248354abd..ed689fd187a 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -20,6 +20,7 @@ set(SRC image.cpp integrator.cpp light.cpp + light_tree.cpp mesh.cpp mesh_displace.cpp mesh_subdivision.cpp diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index cbcd2564e6e..aab63d9c72d 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -19,6 +19,7 @@ #include "render/integrator.h" #include "render/film.h" #include "render/light.h" +#include "render/light_tree.h" #include "render/mesh.h" #include "render/object.h" #include "render/scene.h" @@ -376,7 +377,6 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce foreach(Light *light, scene->lights) { if(!light->is_enabled) continue; - distribution[offset].totarea = totarea; distribution[offset].prim = ~light_index; distribution[offset].lamp.pad = 1.0f; @@ -479,6 +479,302 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce } } +/* TODO: Refactor the code here with the code in device_update_distribution */ +void LightManager::device_update_tree_distribution(Device *, DeviceScene *dscene, Scene *scene, Progress& progress) +{ + progress.set_status("Updating Lights", "Computing tree distribution"); + + /* count */ + size_t num_lights = 0; + size_t num_portals = 0; + size_t num_background_lights = 0; + size_t num_triangles = 0; + + bool background_mis = false; + + /* primitives array used for light BVH */ + vector<Primitive> emissivePrims; // Cannot reserve here..? + + int light_index = 0; + foreach(Light *light, scene->lights) { + if(light->is_enabled) { + num_lights++; + emissivePrims.push_back(Primitive(~light_index,-1)); + light_index++; + } + if(light->is_portal) { + num_portals++; + } + } + + int object_id = 0; + foreach(Object *object, scene->objects) { + if(progress.get_cancel()) return; + + if(!object_usable_as_light(object)) { + object_id++; + continue; + } + /* Count emissive triangles. */ + Mesh *mesh = object->mesh; + size_t mesh_num_triangles = mesh->num_triangles(); + for(size_t i = 0; i < mesh_num_triangles; i++) { + int shader_index = mesh->shader[i]; + Shader *shader = (shader_index < mesh->used_shaders.size()) + ? mesh->used_shaders[shader_index] + : scene->default_surface; + + if(shader->use_mis && shader->has_surface_emission) { + emissivePrims.push_back(Primitive(i + mesh->tri_offset, object_id)); + num_triangles++; + } + } + + object_id++; + } + + size_t num_distribution = num_triangles + num_lights; + VLOG(1) << "Total " << num_distribution << " of light distribution primitives."; + + + /* create light BVH */ + LightTree lightBVH(emissivePrims, scene->objects, scene->lights, 1); + emissivePrims.clear(); + if(progress.get_cancel()) return; + + /* create nodes */ + const vector<CompactNode>& nodesVec = lightBVH.getNodes(); + float4 *nodes = dscene->light_tree_nodes.alloc(nodesVec.size()*LIGHT_BVH_NODE_SIZE); + + /* - Convert each compact node into 4xfloat4 + * 4 for energy, secondChildoffset, prim_id, nemitters + * 4 for bbox.min + bbox.max[0] + * 4 for bbox.max[1-2], theta_o, theta_e + * 4 for axis + 1 pad + */ + size_t offset = 0; + foreach (CompactNode node, nodesVec){ + nodes[offset].x = node.energy; + nodes[offset].y = __int_as_float(node.secondChildOffset); + nodes[off @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs