Commit: 84fec21522616b93d7b4f7ee7563d9502fb79a32
Author: Erik Englesson
Date:   Sat Jul 28 16:34:44 2018 +0200
Branches: gsoc-2018-many-light-sampling
https://developer.blender.org/rB84fec21522616b93d7b4f7ee7563d9502fb79a32

Cycles: Light tree instancing and energy fixes

Instancing for mesh lights now works with the light tree.
The conversion from emission to luminance is now using
linear_rgb_to_gray() instead.

===================================================================

M       intern/cycles/kernel/kernel_emission.h
M       intern/cycles/kernel/kernel_light.h
M       intern/cycles/render/light.cpp
M       intern/cycles/render/light_tree.cpp
M       intern/cycles/render/light_tree.h
M       intern/cycles/util/util_color.h

===================================================================

diff --git a/intern/cycles/kernel/kernel_emission.h 
b/intern/cycles/kernel/kernel_emission.h
index 9d8e38dc458..a06250a515a 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -212,7 +212,7 @@ ccl_device_noinline float3 
indirect_primitive_emission(KernelGlobals *kg, Shader
                /* multiple importance sampling, get triangle light pdf,
                 * and compute weight with respect to BSDF pdf */
                float pdf = triangle_light_pdf(kg, sd, t);
-               pdf *= light_distribution_pdf(kg, P, N, sd->prim, 
is_volume_boundary);
+               pdf *= light_distribution_pdf(kg, P, N, sd->prim, sd->object, 
is_volume_boundary);
                float mis_weight = power_heuristic(bsdf_pdf, pdf);
 
                return L*mis_weight;
@@ -281,7 +281,7 @@ ccl_device_noinline bool 
indirect_lamp_emission(KernelGlobals *kg,
                         * and compute weight with respect to BSDF pdf */
 
                        /* multiply with light picking probablity to pdf */
-                       ls.pdf *= light_distribution_pdf(kg, ray->P, N, 
~ls.lamp, is_inside_volume);
+                       ls.pdf *= light_distribution_pdf(kg, ray->P, N, 
~ls.lamp, -1, is_inside_volume);
                        float mis_weight = power_heuristic(state->ray_pdf, 
ls.pdf);
                        L *= mis_weight;
                }
@@ -346,7 +346,7 @@ ccl_device_noinline float3 
indirect_background(KernelGlobals *kg,
                 * direction, and compute weight with respect to BSDF pdf */
                float pdf = background_light_pdf(kg, ray->P, ray->D);
                int background_index = 
kernel_data.integrator.background_light_index;
-               pdf *= light_distribution_pdf(kg, ray->P, N, ~background_index, 
is_on_volume_boundary);
+               pdf *= light_distribution_pdf(kg, ray->P, N, ~background_index, 
-1, is_on_volume_boundary);
                float mis_weight = power_heuristic(state->ray_pdf, pdf);
 
                return L*mis_weight;
diff --git a/intern/cycles/kernel/kernel_light.h 
b/intern/cycles/kernel/kernel_light.h
index 5a2facaa454..976dd68b5ae 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -1300,11 +1300,17 @@ ccl_device void light_bvh_sample(KernelGlobals *kg, 
float3 P, float3 N,
 
 /* converts from an emissive triangle index to the corresponding
  * light distribution index. */
-ccl_device int triangle_to_distribution(KernelGlobals *kg, int triangle_id)
+ccl_device int triangle_to_distribution(KernelGlobals *kg, int triangle_id,
+                                        int object_id)
 {
        /* binary search to find triangle_id which then gives distribution_id */
        /* equivalent to implementation of std::lower_bound */
        /* todo: of complexity log(N) now. could be made constant with a hash 
table? */
+       /* __triangle_to_distribution is an array of uints of the format below:
+        * [triangle_id0, object_id0, distribution_id0, triangle_id1,... ]
+        * where e.g. [triangle_id0,object_id0] corresponds to distribution id
+        * distribution_id0
+        */
        int first = 0;
        int last = kernel_data.integrator.num_triangle_lights;
        int count = last - first;
@@ -1312,7 +1318,7 @@ ccl_device int triangle_to_distribution(KernelGlobals 
*kg, int triangle_id)
        while (count > 0) {
                step = count / 2;
                middle = first + step;
-               int triangle = kernel_tex_fetch(__triangle_to_distribution, 
middle*2);
+               int triangle = kernel_tex_fetch(__triangle_to_distribution, 
middle*3);
                if (triangle < triangle_id) {
                        first = middle + 1;
                        count -= step + 1;
@@ -1321,9 +1327,18 @@ ccl_device int triangle_to_distribution(KernelGlobals 
*kg, int triangle_id)
                        count = step;
        }
 
+       /* If instancing then we can have several triangles with the same 
triangle_id
+        * so loop over object_id too. */
+       /* todo: do a binary search here too if many instances */
+       while(true){
+               int object = kernel_tex_fetch(__triangle_to_distribution, 
first*3+1);
+               if(object == object_id) break;
+               ++first;
+       }
+
        kernel_assert(kernel_tex_fetch(__triangle_to_distribution, first*2) == 
triangle_id);
 
-       return kernel_tex_fetch(__triangle_to_distribution, first*2+1);
+       return kernel_tex_fetch(__triangle_to_distribution, first*3+2);
 }
 
 /* computes the probability of picking a light in the given node_id */
@@ -1399,12 +1414,13 @@ ccl_device float light_bvh_pdf(KernelGlobals *kg, 
float3 P, float3 N,
 
 /* computes the the probability of picking the given light out of all lights */
 ccl_device float light_distribution_pdf(KernelGlobals *kg, float3 P, float3 N,
-                                        int prim_id, bool is_inside_volume)
+                                        int prim_id, int object_id,
+                                        bool is_inside_volume)
 {
        /* convert from triangle/lamp to light distribution */
        int distribution_id;
        if(prim_id >= 0){ // Triangle_id = prim_id
-               distribution_id = triangle_to_distribution(kg, prim_id);
+               distribution_id = triangle_to_distribution(kg, prim_id, 
object_id);
        } else { // Lamp
                int lamp_id = -prim_id-1;
                distribution_id = kernel_tex_fetch(__lamp_to_distribution, 
lamp_id);
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 69c0dbcd15e..0384a30759a 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -263,7 +263,7 @@ float LightManager::distant_lights_energy(const Scene 
*scene,
                bool is_constant_emission = 
lamp->shader->is_constant_emission(&emission);
                if(!is_constant_emission) continue; // TODO: Properly handle 
this case
 
-               luminance += rgb_to_luminance(emission);
+               luminance += 
scene->shader_manager->linear_rgb_to_gray(emission);
        }
 
 
@@ -304,7 +304,7 @@ float LightManager::background_light_energy(Device *device,
                shade_background_pixels(device, dscene, res.x, res.y, pixels, 
progress);
                num_pixels += pixels.size();
                for(int i = 0; i < pixels.size(); ++i){
-                       average_luminance += rgb_to_luminance(pixels[i]);
+                       average_luminance += 
scene->shader_manager->linear_rgb_to_gray(pixels[i]);
                }
 
                break;
@@ -404,7 +404,7 @@ void LightManager::device_update_distribution(Device 
*device, DeviceScene *dscen
 
                /* create light BVH */
                double time_start = time_dt();
-               LightTree lightBVH(emissivePrims, scene->objects, 
scene->lights, 64);
+               LightTree lightBVH(emissivePrims, scene->objects, 
scene->lights, scene, 64);
                VLOG(1) << "Light BVH build time: " << time_dt() - time_start;
 
                /* the light BVH reorders the primitives so update 
emissivePrims */
@@ -570,22 +570,23 @@ void LightManager::device_update_distribution(Device 
*device, DeviceScene *dscen
        }
 
        /* find mapping between triangle_id to distribution_id, used for MIS */
-       vector< std::pair<uint,uint> > tri_to_distr;
+       vector< std::tuple<uint,uint, uint> > tri_to_distr;
        tri_to_distr.reserve(num_triangles);
        for(int i = 0; i < emissivePrims.size(); ++i){
                const Primitive& prim = emissivePrims[i];
                if(prim.prim_id < 0) continue; // Skip lamps
-               tri_to_distr.push_back(std::make_pair( prim.prim_id, i ));
+               tri_to_distr.push_back(std::make_tuple(prim.prim_id, 
prim.object_id, i));
        }
 
        std::sort(tri_to_distr.begin(), tri_to_distr.end());
 
        assert(num_triangles == tri_to_distr.size());
        uint *triangle_to_distribution =
-               dscene->triangle_to_distribution.alloc(num_triangles*2);
+               dscene->triangle_to_distribution.alloc(num_triangles*3);
        for(int i = 0; i < tri_to_distr.size(); ++i){
-               triangle_to_distribution[2*i  ] = tri_to_distr[i].first;
-               triangle_to_distribution[2*i+1] = tri_to_distr[i].second;
+               triangle_to_distribution[3*i  ] = std::get<0>(tri_to_distr[i]);
+               triangle_to_distribution[3*i+1] = std::get<1>(tri_to_distr[i]);
+               triangle_to_distribution[3*i+2] = std::get<2>(tri_to_distr[i]);
        }
 
        /* create light distribution in same order as the emissivePrims */
diff --git a/intern/cycles/render/light_tree.cpp 
b/intern/cycles/render/light_tree.cpp
index ad53b84f360..21bbc543044 100644
--- a/intern/cycles/render/light_tree.cpp
+++ b/intern/cycles/render/light_tree.cpp
@@ -31,8 +31,10 @@ CCL_NAMESPACE_BEGIN
 LightTree::LightTree(const vector<Primitive>& prims_,
                      const vector<Object*>& objects_,
                      const vector<Light*>& lights_,
+                     Scene* scene_,
                      const unsigned int maxPrimsInNode_)
-    :  objects(objects_), lights(lights_), maxPrimsInNode(maxPrimsInNode_)
+    :  objects(objects_), lights(lights_), maxPrimsInNode(maxPrimsInNode_),
+      scene(scene_)
 {
 
        if (prims_.empty()) return;
@@ -66,6 +68,7 @@ LightTree::LightTree(const vector<Primitive>& prims_,
                BoundBox bbox     = get_bbox(primitives[i]);
                Orientation bcone = get_bcone(primitives[i]);
                float energy      = get_energy(primitives[i]);
+
                buildData.push_back(BVHPrimitiveInfo(i, bbox, bcone, energy));
        }
 
@@ -143,8 +146,21 @@ BoundBox LightTree::get_bbox(const Primitive& prim)
                const Mesh* mesh = object->mesh;
                const int triangle_id = prim.prim_id - mesh->tri_offset;
                const Mesh::Triangle triangle = mesh->get_triangle(triangle_id);
-               const float3 *vpos = &mesh->verts[0];
-               triangle.bounds_grow(vpos, bbox);
+
+               float3 p0 = mesh->verts[triangle.v[0]];
+               float3 p1 = mesh->verts[triangle.v[1]];
+               float3 p2 = mesh->verts[triangle.v[2]];
+
+               if(!mesh->transform_applied) {
+                       const Transform& tfm = object->tfm;
+                       p0 = transform_point(&tfm, p0);
+                       p1 = transform_point(&tfm, p1);
+                       p2 = transform_point(&tfm, p2);
+               }
+
+               bbox.grow(p0);
+               bbox.grow(p1);
+               bbox.grow(p2);
        } else {
                /* extract bounding box from lamp based on light type */
                Light* lamp = lights[prim.lamp_id];
@@ -183,8 +199,26 @@ Orientation LightTree::get_bcone(const Primitive& prim){
                const Mesh* mesh = object->mesh;
                const int triangle_id = prim.prim_id - mesh->tri_offset;
                const Mesh::Triangle triangle = mesh->get_triangle(triangle_id);
-               const float3 *vpos = &mesh->verts[0];
-               bcone.axis = triangle.compute_normal(vpos);
+
+               float3 p0 = mesh->verts[triangle.v[0]];
+               float3 p1 = mesh->verts[triangle.v[1]];
+               float3 p2 = mesh->verts[triangle.v[2]];
+
+               if(!mesh->transform_applied) {
+                       const Transform& tfm = object->tfm;
+                       p0 = transform_point(&tfm, p0);
+                       p1 = transform_point(&tfm, p1);
+                       p2 = transform_point(&tfm, p2);
+               }
+
+               float3 normal = make_float3(1.0f, 0.0f, 0.0f);
+               const float3 norm = cross(p1 - p0, p2 - p0);
+               const float normlen = len(norm);
+               if(normlen != 0.0f) {
+                       normal = norm / norm

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to