Merge branch 'master' into blender2.8
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>
Thu, 8 Feb 2018 18:00:20 +0000 (03:00 +0900)
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>
Thu, 8 Feb 2018 18:00:20 +0000 (03:00 +0900)
Conflicts:
intern/cycles/blender/addon/ui.py

16 files changed:
intern/cycles/blender/addon/ui.py
intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_path_branched.h
intern/cycles/kernel/kernel_path_state.h
intern/cycles/kernel/kernel_path_subsurface.h
intern/cycles/kernel/kernel_subsurface.h
intern/cycles/kernel/osl/osl_bssrdf.cpp
intern/cycles/kernel/osl/osl_closures.cpp
intern/cycles/kernel/osl/osl_closures.h
intern/cycles/kernel/shaders/node_principled_bsdf.osl
intern/cycles/kernel/shaders/node_subsurface_scattering.osl
intern/cycles/kernel/shaders/stdosl.h
intern/cycles/kernel/split/kernel_split_data_types.h
intern/cycles/kernel/split/kernel_subsurface_scatter.h
source/blender/bmesh/tools/bmesh_bevel.c
tests/python/CMakeLists.txt

index 13bb00949824509464932dadbdd606d3570de94c..d5f72654c723ccbc7476a3a24f935f90c9a23534 100644 (file)
@@ -442,8 +442,10 @@ class CYCLES_RENDER_PT_layer_options(CyclesButtonsPanel, Panel):
 
     def draw(self, context):
         layout = self.layout
+        with_freestyle = bpy.app.build_options.freestyle
 
         scene = context.scene
+        rd = scene.render
         view_layer = scene.view_layers.active
 
         col = layout.column()
@@ -451,6 +453,10 @@ class CYCLES_RENDER_PT_layer_options(CyclesButtonsPanel, Panel):
         col.prop(view_layer, "use_ao", "Use AO")
         col.prop(view_layer, "use_solid", "Use Surfaces")
         col.prop(view_layer, "use_strand", "Use Hair")
+        if with_freestyle:
+            row = col.row()
+            row.prop(view_layer, "use_freestyle", "Use Freestyle")
+            row.active = rd.use_freestyle
 
 
 class CYCLES_RENDER_PT_layer_passes(CyclesButtonsPanel, Panel):
index 1e98bca66ad5ae6a48ee6c82c3d977d5020d9732..afca4575331c93c2cd7f67d9db5c77c05c3cc2fa 100644 (file)
@@ -504,7 +504,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
                                subsurface_scatter_step(kg,
                                                        sd,
                                                        state,
-                                                       state->flag,
                                                        sc,
                                                        &lcg_state,
                                                        bssrdf_u, bssrdf_v,
index fe2a7d179a447c8f8e7df853394e05bfdc11c90d..5f917d509ec90805f46672c7c58529406c224e89 100644 (file)
@@ -340,9 +340,13 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
                /* do subsurface scatter step with copy of shader data, this will
                 * replace the BSSRDF with a diffuse BSDF closure */
                for(int j = 0; j < num_samples; j++) {
+                       PathState hit_state = *state;
+                       path_state_branch(&hit_state, j, num_samples);
+                       hit_state.rng_hash = bssrdf_rng_hash;
+
                        LocalIntersection ss_isect;
                        float bssrdf_u, bssrdf_v;
-                       path_branched_rng_2D(kg, bssrdf_rng_hash, state, j, num_samples, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
+                       path_state_rng_2D(kg, &hit_state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
                        int num_hits = subsurface_scatter_multi_intersect(kg,
                                                                          &ss_isect,
                                                                          sd,
@@ -350,6 +354,9 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
                                                                          &lcg_state,
                                                                          bssrdf_u, bssrdf_v,
                                                                          true);
+
+                       hit_state.rng_offset += PRNG_BOUNCE_NUM;
+
 #ifdef __VOLUME__
                        Ray volume_ray = *ray;
                        bool need_update_volume_stack =
@@ -364,14 +371,8 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
                                                               &ss_isect,
                                                               hit,
                                                               &bssrdf_sd,
-                                                              state,
-                                                              state->flag,
-                                                              sc,
-                                                              true);
-
-                               PathState hit_state = *state;
-
-                               path_state_branch(&hit_state, j, num_samples);
+                                                              &hit_state,
+                                                              sc);
 
 #ifdef __VOLUME__
                                if(need_update_volume_stack) {
@@ -380,6 +381,10 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
                                        volume_ray.D = normalize_len(P - volume_ray.P,
                                                                     &volume_ray.t);
 
+                                       for(int k = 0; k < VOLUME_STACK_SIZE; k++) {
+                                               hit_state.volume_stack[k] = state->volume_stack[k];
+                                       }
+
                                        kernel_volume_stack_update_for_subsurface(
                                            kg,
                                            emission_sd,
@@ -392,7 +397,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
                                /* direct light */
                                if(kernel_data.integrator.use_direct_light) {
                                        int all = (kernel_data.integrator.sample_all_lights_direct) ||
-                                                 (state->flag & PATH_RAY_SHADOW_CATCHER);
+                                                 (hit_state.flag & PATH_RAY_SHADOW_CATCHER);
                                        kernel_branched_path_surface_connect_light(
                                                kg,
                                                &bssrdf_sd,
index 2ae866bb051996b6b9c1ccb946793e48e606bc5e..a16c20cbee6a7b9e3fb10fa6d380f7ca132d7e8f 100644 (file)
@@ -231,8 +231,6 @@ ccl_device_inline void path_state_branch(ccl_addr_space PathState *state,
                                          int branch,
                                          int num_branches)
 {
-       state->rng_offset += PRNG_BOUNCE_NUM;
-
        if(num_branches > 1) {
                /* Path is splitting into a branch, adjust so that each branch
                 * still gets a unique sample from the same sequence. */
index c29b41e42222e8311f6461772824a0a0b197d4ce..a48bde6443e7796377aa4550c7342018f94adf3a 100644 (file)
@@ -71,9 +71,7 @@ bool kernel_path_subsurface_scatter(
                                                       hit,
                                                       sd,
                                                       state,
-                                                      state->flag,
-                                                      sc,
-                                                      false);
+                                                      sc);
 
                        kernel_path_surface_connect_light(kg, sd, emission_sd, *throughput, state, L);
 
index 582a20704d34d4e893c122a248d12716a5dbf347..f4759b26191e25b3c5b396439be9fded9528d769 100644 (file)
@@ -135,7 +135,6 @@ ccl_device float3 subsurface_color_pow(float3 color, float exponent)
 ccl_device void subsurface_color_bump_blur(KernelGlobals *kg,
                                            ShaderData *sd,
                                            ccl_addr_space PathState *state,
-                                           int state_flag,
                                            float3 *eval,
                                            float3 *N)
 {
@@ -148,7 +147,7 @@ ccl_device void subsurface_color_bump_blur(KernelGlobals *kg,
 
        if(bump || texture_blur > 0.0f) {
                /* average color and normal at incoming point */
-               shader_eval_surface(kg, sd, state, state_flag, kernel_data.integrator.max_closures);
+               shader_eval_surface(kg, sd, state, state->flag, kernel_data.integrator.max_closures);
                float3 in_color = shader_bssrdf_sum(sd, (bump)? N: NULL, NULL);
 
                /* we simply divide out the average color and multiply with the average
@@ -311,9 +310,7 @@ ccl_device_noinline void subsurface_scatter_multi_setup(
         int hit,
         ShaderData *sd,
         ccl_addr_space PathState *state,
-        int state_flag,
-        const ShaderClosure *sc,
-        bool all)
+        const ShaderClosure *sc)
 {
 #ifdef __SPLIT_KERNEL__
        Ray ray_object = ss_isect->ray;
@@ -333,7 +330,7 @@ ccl_device_noinline void subsurface_scatter_multi_setup(
        /* Optionally blur colors and bump mapping. */
        float3 weight = ss_isect->weight[hit];
        float3 N = sd->N;
-       subsurface_color_bump_blur(kg, sd, state, state_flag, &weight, &N);
+       subsurface_color_bump_blur(kg, sd, state, &weight, &N);
 
        /* Setup diffuse BSDF. */
        subsurface_scatter_setup_diffuse_bsdf(kg, sd, sc, weight, true, N);
@@ -341,7 +338,7 @@ ccl_device_noinline void subsurface_scatter_multi_setup(
 
 /* subsurface scattering step, from a point on the surface to another nearby point on the same object */
 ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state,
-       int state_flag, const ShaderClosure *sc, uint *lcg_state, float disk_u, float disk_v, bool all)
+       const ShaderClosure *sc, uint *lcg_state, float disk_u, float disk_v, bool all)
 {
        float3 eval = make_float3(0.0f, 0.0f, 0.0f);
 
@@ -430,7 +427,7 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_a
 
        /* optionally blur colors and bump mapping */
        float3 N = sd->N;
-       subsurface_color_bump_blur(kg, sd, state, state_flag, &eval, &N);
+       subsurface_color_bump_blur(kg, sd, state, &eval, &N);
 
        /* setup diffuse bsdf */
        subsurface_scatter_setup_diffuse_bsdf(kg, sd, sc, eval, (ss_isect.num_hits > 0), N);
index 3e7905f26dfd34e101eb253f66509b655c249239..db6426f60e5d114e2a3deb9857c1864c2c4c6f5f 100644 (file)
@@ -48,9 +48,38 @@ CCL_NAMESPACE_BEGIN
 
 using namespace OSL;
 
+static ustring u_cubic("cubic");
+static ustring u_gaussian("gaussian");
+static ustring u_burley("burley");
+static ustring u_principled("principled");
+
 class CBSSRDFClosure : public CClosurePrimitive {
 public:
        Bssrdf params;
+       ustring method;
+
+       CBSSRDFClosure()
+       {
+               params.texture_blur = 0.0f;
+               params.sharpness = 0.0f;
+               params.roughness = 0.0f;
+       }
+
+       void setup(ShaderData *sd, int path_flag, float3 weight)
+       {
+               if (method == u_cubic) {
+                       alloc(sd, path_flag, weight, CLOSURE_BSSRDF_CUBIC_ID);
+               }
+               else if (method == u_gaussian) {
+                       alloc(sd, path_flag, weight, CLOSURE_BSSRDF_GAUSSIAN_ID);
+               }
+               else if (method == u_burley) {
+                       alloc(sd, path_flag, weight, CLOSURE_BSSRDF_BURLEY_ID);
+               }
+               else if (method == u_principled) {
+                       alloc(sd, path_flag, weight, CLOSURE_BSSRDF_PRINCIPLED_ID);
+               }
+       }
 
        void alloc(ShaderData *sd, int path_flag, float3 weight, ClosureType type)
        {
@@ -76,105 +105,23 @@ public:
        }
 };
 
-/* Cubic */
-
-class CubicBSSRDFClosure : public CBSSRDFClosure {
-public:
-       void setup(ShaderData *sd, int path_flag, float3 weight)
-       {
-               alloc(sd, path_flag, weight, CLOSURE_BSSRDF_CUBIC_ID);
-       }
-};
-
-ClosureParam *closure_bssrdf_cubic_params()
-{
-       static ClosureParam params[] = {
-               CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, params.N),
-               CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, params.radius),
-               CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, params.texture_blur),
-               CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, params.sharpness),
-               CLOSURE_STRING_KEYPARAM(CubicBSSRDFClosure, label, "label"),
-               CLOSURE_FINISH_PARAM(CubicBSSRDFClosure)
-       };
-       return params;
-}
-
-CCLOSURE_PREPARE(closure_bssrdf_cubic_prepare, CubicBSSRDFClosure)
-
-/* Gaussian */
-
-class GaussianBSSRDFClosure : public CBSSRDFClosure {
-public:
-       void setup(ShaderData *sd, int path_flag, float3 weight)
-       {
-               alloc(sd, path_flag, weight, CLOSURE_BSSRDF_GAUSSIAN_ID);
-       }
-};
-
-ClosureParam *closure_bssrdf_gaussian_params()
-{
-       static ClosureParam params[] = {
-               CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, params.N),
-               CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, params.radius),
-               CLOSURE_FLOAT_PARAM(GaussianBSSRDFClosure, params.texture_blur),
-               CLOSURE_STRING_KEYPARAM(GaussianBSSRDFClosure, label, "label"),
-               CLOSURE_FINISH_PARAM(GaussianBSSRDFClosure)
-       };
-       return params;
-}
-
-CCLOSURE_PREPARE(closure_bssrdf_gaussian_prepare, GaussianBSSRDFClosure)
-
-/* Burley */
-
-class BurleyBSSRDFClosure : public CBSSRDFClosure {
-public:
-       void setup(ShaderData *sd, int path_flag, float3 weight)
-       {
-               alloc(sd, path_flag, weight, CLOSURE_BSSRDF_BURLEY_ID);
-       }
-};
-
-ClosureParam *closure_bssrdf_burley_params()
-{
-       static ClosureParam params[] = {
-               CLOSURE_FLOAT3_PARAM(BurleyBSSRDFClosure, params.N),
-               CLOSURE_FLOAT3_PARAM(BurleyBSSRDFClosure, params.radius),
-               CLOSURE_FLOAT_PARAM(BurleyBSSRDFClosure, params.texture_blur),
-               CLOSURE_FLOAT3_PARAM(BurleyBSSRDFClosure, params.albedo),
-               CLOSURE_STRING_KEYPARAM(BurleyBSSRDFClosure, label, "label"),
-               CLOSURE_FINISH_PARAM(BurleyBSSRDFClosure)
-       };
-       return params;
-}
-
-CCLOSURE_PREPARE(closure_bssrdf_burley_prepare, BurleyBSSRDFClosure)
-
-/* Disney principled */
-
-class PrincipledBSSRDFClosure : public CBSSRDFClosure {
-public:
-       void setup(ShaderData *sd, int path_flag, float3 weight)
-       {
-               alloc(sd, path_flag, weight, CLOSURE_BSSRDF_PRINCIPLED_ID);
-       }
-};
-
-ClosureParam *closure_bssrdf_principled_params()
+ClosureParam *closure_bssrdf_params()
 {
        static ClosureParam params[] = {
-               CLOSURE_FLOAT3_PARAM(PrincipledBSSRDFClosure, params.N),
-               CLOSURE_FLOAT3_PARAM(PrincipledBSSRDFClosure, params.radius),
-               CLOSURE_FLOAT_PARAM(PrincipledBSSRDFClosure, params.texture_blur),
-               CLOSURE_FLOAT3_PARAM(PrincipledBSSRDFClosure, params.albedo),
-               CLOSURE_FLOAT_PARAM(PrincipledBSSRDFClosure, params.roughness),
-               CLOSURE_STRING_KEYPARAM(PrincipledBSSRDFClosure, label, "label"),
-               CLOSURE_FINISH_PARAM(PrincipledBSSRDFClosure)
+               CLOSURE_STRING_PARAM(CBSSRDFClosure, method),
+               CLOSURE_FLOAT3_PARAM(CBSSRDFClosure, params.N),
+               CLOSURE_FLOAT3_PARAM(CBSSRDFClosure, params.radius),
+               CLOSURE_FLOAT3_PARAM(CBSSRDFClosure, params.albedo),
+               CLOSURE_FLOAT_KEYPARAM(CBSSRDFClosure, params.texture_blur, "texture_blur"),
+               CLOSURE_FLOAT_KEYPARAM(CBSSRDFClosure, params.sharpness, "sharpness"),
+               CLOSURE_FLOAT_KEYPARAM(CBSSRDFClosure, params.roughness, "roughness"),
+               CLOSURE_STRING_KEYPARAM(CBSSRDFClosure, label, "label"),
+               CLOSURE_FINISH_PARAM(CBSSRDFClosure)
        };
        return params;
 }
 
-CCLOSURE_PREPARE(closure_bssrdf_principled_prepare, PrincipledBSSRDFClosure)
+CCLOSURE_PREPARE(closure_bssrdf_prepare, CBSSRDFClosure)
 
 CCL_NAMESPACE_END
 
index 8acab1ab55845ec3c374ef11303b05655d5c2c09..d0c357580fd3f77a8acf4d015b137e60c9e4cee2 100644 (file)
@@ -316,14 +316,8 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
                closure_bsdf_diffuse_ramp_params(), closure_bsdf_diffuse_ramp_prepare);
        register_closure(ss, "phong_ramp", id++,
                closure_bsdf_phong_ramp_params(), closure_bsdf_phong_ramp_prepare);
-       register_closure(ss, "bssrdf_cubic", id++,
-               closure_bssrdf_cubic_params(), closure_bssrdf_cubic_prepare);
-       register_closure(ss, "bssrdf_gaussian", id++,
-               closure_bssrdf_gaussian_params(), closure_bssrdf_gaussian_prepare);
-       register_closure(ss, "bssrdf_burley", id++,
-               closure_bssrdf_burley_params(), closure_bssrdf_burley_prepare);
-       register_closure(ss, "bssrdf_principled", id++,
-               closure_bssrdf_principled_params(), closure_bssrdf_principled_prepare);
+       register_closure(ss, "bssrdf", id++,
+               closure_bssrdf_params(), closure_bssrdf_prepare);
 
        register_closure(ss, "hair_reflection", id++,
                bsdf_hair_reflection_params(), bsdf_hair_reflection_prepare);
index 38943b77656596f6afcca901815db89083ff96e5..dca7e74f154ffd4c10f788c9b4abb753894c1eca 100644 (file)
@@ -49,10 +49,7 @@ OSL::ClosureParam *closure_ambient_occlusion_params();
 OSL::ClosureParam *closure_bsdf_diffuse_ramp_params();
 OSL::ClosureParam *closure_bsdf_phong_ramp_params();
 OSL::ClosureParam *closure_bsdf_transparent_params();
-OSL::ClosureParam *closure_bssrdf_cubic_params();
-OSL::ClosureParam *closure_bssrdf_gaussian_params();
-OSL::ClosureParam *closure_bssrdf_burley_params();
-OSL::ClosureParam *closure_bssrdf_principled_params();
+OSL::ClosureParam *closure_bssrdf_params();
 OSL::ClosureParam *closure_absorption_params();
 OSL::ClosureParam *closure_henyey_greenstein_params();
 OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_params();
@@ -72,10 +69,7 @@ void closure_ambient_occlusion_prepare(OSL::RendererServices *, int id, void *da
 void closure_bsdf_diffuse_ramp_prepare(OSL::RendererServices *, int id, void *data);
 void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data);
 void closure_bsdf_transparent_prepare(OSL::RendererServices *, int id, void *data);
-void closure_bssrdf_cubic_prepare(OSL::RendererServices *, int id, void *data);
-void closure_bssrdf_gaussian_prepare(OSL::RendererServices *, int id, void *data);
-void closure_bssrdf_burley_prepare(OSL::RendererServices *, int id, void *data);
-void closure_bssrdf_principled_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bssrdf_prepare(OSL::RendererServices *, int id, void *data);
 void closure_absorption_prepare(OSL::RendererServices *, int id, void *data);
 void closure_henyey_greenstein_prepare(OSL::RendererServices *, int id, void *data);
 void closure_bsdf_microfacet_multi_ggx_prepare(OSL::RendererServices *, int id, void *data);
index 6870d479af3a01335b962177edd7f291d793318e..0e31dcedee42361084d6d353144d4feb714c0666 100644 (file)
@@ -58,7 +58,7 @@ shader node_principled_bsdf(
        if (diffuse_weight > 1e-5) {
                if (Subsurface > 1e-5) {
                        color mixed_ss_base_color = SubsurfaceColor * Subsurface + BaseColor * (1.0 - Subsurface);
-                       BSDF = mixed_ss_base_color * bssrdf_principled(Normal, Subsurface * SubsurfaceRadius, 0.0, SubsurfaceColor, Roughness);
+                       BSDF = mixed_ss_base_color * bssrdf("principled", Normal, Subsurface * SubsurfaceRadius, SubsurfaceColor, "roughness", Roughness);
                } else {
                        BSDF = BaseColor * principled_diffuse(Normal, Roughness);
                }
index 5ba8f34021de350a9b09a14bb1f181d03357d47c..c9983fcd5ddfbe3b70133c4c2a5047008db24928 100644 (file)
@@ -27,10 +27,10 @@ shader node_subsurface_scattering(
        output closure color BSSRDF = 0)
 {
        if (falloff == "gaussian")
-               BSSRDF = Color * bssrdf_gaussian(Normal, Scale * Radius, TextureBlur);
+               BSSRDF = Color * bssrdf("gaussian", Normal, Scale * Radius, Color, "texture_blur", TextureBlur);
        else if (falloff == "cubic")
-               BSSRDF = Color * bssrdf_cubic(Normal, Scale * Radius, TextureBlur, Sharpness);
+               BSSRDF = Color * bssrdf("cubic", Normal, Scale * Radius, Color, "texture_blur", TextureBlur, "sharpness", Sharpness);
        else
-               BSSRDF = Color * bssrdf_burley(Normal, Scale * Radius, TextureBlur, Color);
+               BSSRDF = Color * bssrdf("burley", Normal, Scale * Radius, Color, "texture_blur", TextureBlur);
 }
 
index c91d29186879d20a5b67fee73b7a070ec7047e9b..091ade4a60d0d28b5a3a76971fb6facdbc3ffeb6 100644 (file)
@@ -549,10 +549,7 @@ closure color principled_sheen(normal N) BUILTIN;
 closure color principled_clearcoat(normal N, float clearcoat, float clearcoat_roughness) BUILTIN;
 
 // BSSRDF
-closure color bssrdf_cubic(normal N, vector radius, float texture_blur, float sharpness) BUILTIN;
-closure color bssrdf_gaussian(normal N, vector radius, float texture_blur) BUILTIN;
-closure color bssrdf_burley(normal N, vector radius, float texture_blur, color albedo) BUILTIN;
-closure color bssrdf_principled(normal N, vector radius, float texture_blur, color subsurface_color, float roughness) BUILTIN;
+closure color bssrdf(string method, normal N, vector radius, color albedo) BUILTIN;
 
 // Hair
 closure color hair_reflection(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN;
index 5f40fdc9240558d954504ffc0d8d5fa5f895a4d8..56194d9f857fd094446ba2bc6743038022a1a072 100644 (file)
@@ -67,10 +67,6 @@ typedef ccl_global struct SplitBranchedState {
 
        uint lcg_state;
        LocalIntersection ss_isect;
-
-#  ifdef __VOLUME__
-       VolumeStack volume_stack[VOLUME_STACK_SIZE];
-#  endif  /* __VOLUME__ */
 #endif  /*__SUBSURFACE__ */
 
        int shared_sample_count; /* number of branched samples shared with other threads */
index 38dd1dc5654f7b214133590bd6ad27a60a29f9f0..f902d0009187aed4c9345acb25eaaebc53be876d 100644 (file)
@@ -61,11 +61,16 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
                /* do subsurface scatter step with copy of shader data, this will
                 * replace the BSSRDF with a diffuse BSDF closure */
                for(int j = branched_state->ss_next_sample; j < num_samples; j++) {
+                       ccl_global PathState *hit_state = &kernel_split_state.path_state[ray_index];
+                       *hit_state = branched_state->path_state;
+                       hit_state->rng_hash = bssrdf_rng_hash;
+                       path_state_branch(hit_state, j, num_samples);
+
                        ccl_global LocalIntersection *ss_isect = &branched_state->ss_isect;
                        float bssrdf_u, bssrdf_v;
                        path_branched_rng_2D(kg,
                                             bssrdf_rng_hash,
-                                            &branched_state->path_state,
+                                            hit_state,
                                             j,
                                             num_samples,
                                             PRNG_BSDF_U,
@@ -89,6 +94,8 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
                                *ss_isect = ss_isect_private;
                        }
 
+                       hit_state->rng_offset += PRNG_BOUNCE_NUM;
+
 #ifdef __VOLUME__
                        Ray volume_ray = branched_state->ray;
                        bool need_update_volume_stack =
@@ -107,38 +114,24 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
                                                               &ss_isect_private,
                                                               hit,
                                                               bssrdf_sd,
-                                                              &branched_state->path_state,
-                                                              branched_state->path_state.flag,
-                                                              sc,
-                                                              true);
+                                                              hit_state,
+                                                              sc);
                                *ss_isect = ss_isect_private;
 
-                               ccl_global PathState *hit_state = &kernel_split_state.path_state[ray_index];
-                               *hit_state = branched_state->path_state;
-
-                               path_state_branch(hit_state, j, num_samples);
-
 #ifdef __VOLUME__
                                if(need_update_volume_stack) {
                                        /* Setup ray from previous surface point to the new one. */
                                        float3 P = ray_offset(bssrdf_sd->P, -bssrdf_sd->Ng);
                                        volume_ray.D = normalize_len(P - volume_ray.P, &volume_ray.t);
 
-                                       /* this next part is expensive as it does scene intersection so only do once */
-                                       if(branched_state->next_closure == 0 && branched_state->next_sample == 0) {
-                                               for(int k = 0; k < VOLUME_STACK_SIZE; k++) {
-                                                       branched_state->volume_stack[k] = hit_state->volume_stack[k];
-                                               }
-
-                                               kernel_volume_stack_update_for_subsurface(kg,
-                                                                                         emission_sd,
-                                                                                         &volume_ray,
-                                                                                         branched_state->volume_stack);
-                                       }
-
                                        for(int k = 0; k < VOLUME_STACK_SIZE; k++) {
-                                               hit_state->volume_stack[k] = branched_state->volume_stack[k];
+                                               hit_state->volume_stack[k] = branched_state->path_state.volume_stack[k];
                                        }
+
+                                       kernel_volume_stack_update_for_subsurface(kg,
+                                                                                 emission_sd,
+                                                                                 &volume_ray,
+                                                                                 hit_state->volume_stack);
                                }
 #endif  /* __VOLUME__ */
 
@@ -147,7 +140,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
                                        /* direct light */
                                        if(kernel_data.integrator.use_direct_light) {
                                                int all = (kernel_data.integrator.sample_all_lights_direct) ||
-                                                             (branched_state->path_state.flag & PATH_RAY_SHADOW_CATCHER);
+                                                             (hit_state->flag & PATH_RAY_SHADOW_CATCHER);
                                                kernel_branched_path_surface_connect_light(kg,
                                                                                           bssrdf_sd,
                                                                                           emission_sd,
@@ -264,7 +257,6 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg)
                                        subsurface_scatter_step(kg,
                                                                sd,
                                                                state,
-                                                               state->flag,
                                                                sc,
                                                                &lcg_state,
                                                                bssrdf_u, bssrdf_v,
index e89f54349f7fab5a482d8fe3421e74fb6729ff52..beee9065eceeb6316143e346cdcf1389e40b666d 100644 (file)
@@ -1879,7 +1879,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
        }
 }
 
-#if 0
+#ifdef DEBUG_ADJUST
 static void print_adjust_stats(BoundVert *vstart)
 {
        BoundVert *v;
@@ -1921,21 +1921,25 @@ static void print_adjust_stats(BoundVert *vstart)
                if (v->adjchain != NULL) {
                        eright = v->efirst;
                        eleft = v->adjchain->elast;
-                       delta = fabs(eright->offset_r - eright->offset_r_spec);
+                       delta = eright->offset_r - eright->offset_r_spec;
                        delta_pct = 100.0 * delta / eright->offset_r_spec;
-                       printf("e%d r(%f) vs r spec(%f): abs(delta)=%f, delta_pct=%f\n",
+                       printf("e%d r(%f) vs r spec(%f): delta=%f, delta_pct=%f\n",
                                BM_elem_index_get(eright->e), eright->offset_r, eright->offset_r_spec, delta, delta_pct);
                        spec_residual2 += delta * delta;
+                       delta = fabs(delta);
+                       delta_pct = fabs(delta_pct);
                        if (delta > max_spec_r)
                                max_spec_r = delta;
                        if (delta_pct > max_spec_r_pct)
                                max_spec_r_pct = delta_pct;
 
-                       delta = fabs(eleft->offset_l - eleft->offset_l_spec);
+                       delta = eleft->offset_l - eleft->offset_l_spec;
                        delta_pct = 100.0 * delta / eright->offset_l_spec;
-                       printf("e%d l(%f) vs l spec(%f): abs(delta)=%f, delta_pct=%f\n",
+                       printf("e%d l(%f) vs l spec(%f): delta=%f, delta_pct=%f\n",
                                BM_elem_index_get(eright->e), eleft->offset_l, eleft->offset_l_spec, delta, delta_pct);
                        spec_residual2 += delta * delta;
+                       delta = fabs(delta);
+                       delta_pct = fabs(delta_pct);
                        if (delta > max_spec_r)
                                max_spec_r = delta;
                        if (delta_pct > max_spec_r_pct)
@@ -1951,6 +1955,15 @@ static void print_adjust_stats(BoundVert *vstart)
 }
 #endif
 
+#ifdef FAST_ADJUST_CODE
+/* This code uses a direct solution to the adjustment problem for chains and certain cycles.
+ * It is a two-step approach: first solve for the exact solution of the 'match widths' constraints
+ * using the one degree of freedom that allows for expressing all other widths in terms of that.
+ * And then minimize the spec-matching constraints using the derivative of the least squares
+ * residual in terms of that one degree of freedom.
+ * Unfortunately, the results are in some cases worse than the general least squares solution
+ * for the combined (with weights) problem, so this code is not used.
+ * But keep it here for a while in case peformance issues demand that it be used sometimes. */
 static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscycle)
 {
        BoundVert *v;
@@ -2027,6 +2040,7 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc
        MEM_freeN(g_prod);
        return true;
 }
+#endif
 
 /* Adjust the offsets for a single cycle or chain.
  * For chains and some cycles, a fast solution exists.
@@ -2038,22 +2052,35 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc
 static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
 {
        BoundVert *v;
-       EdgeHalf *eleft, *eright;
+       EdgeHalf *eleft, *eright, *enextleft;
        LinearSolver *solver;
        double weight, val;
        int i, np, nrows, row;
 
        np = 0;
+#ifdef DEBUG_ADJUST
+       printf("\nadjust the %s (with eigen)\n", iscycle ? "cycle" : "chain");
+#endif
        v = vstart;
        do {
+#ifdef DEBUG_ADJUST
+               eleft = v->elast;
+               eright = v->efirst;
+               printf(" (left=e%d, right=e%d)", BM_elem_index_get(eleft->e), BM_elem_index_get(eright->e));
+#endif
                np++;
                v = v->adjchain;
        } while (v && v != vstart);
+#ifdef DEBUG_ADJUST
+               printf(" -> %d parms\n", np);
+#endif
 
+#ifdef FAST_ADJUST_CODE
        if (adjust_the_cycle_or_chain_fast(vstart, np, iscycle))
                return;
+#endif
 
-       nrows = iscycle ? 2 * np : 2 * np - 1;
+       nrows = iscycle ? 3 * np : 3 * np - 3;
 
        solver = EIG_linear_least_squares_solver_new(nrows, np, 1);
 
@@ -2062,9 +2089,15 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
        weight = BEVEL_MATCH_SPEC_WEIGHT; /* sqrt of factor to weight down importance of spec match */
        do {
                /* except at end of chain, v's indep variable is offset_r of v->efirst */
-               if (iscycle || v->adjchain != NULL) {
+               if (iscycle || i < np - 1) {
                        eright = v->efirst;
                        eleft = v->elast;
+                       enextleft = v->adjchain->elast;
+#ifdef DEBUG_ADJUST
+                       printf("p%d: e%d->offset_r = %f\n", i, BM_elem_index_get(eright->e), eright->offset_r);
+                       if (iscycle || v != vstart)
+                               printf("  dependent: e%d->offset_l = %f * p%d\n", BM_elem_index_get(eleft->e), v->sinratio, i);
+#endif
 
                        /* residue i: width difference between eright and eleft of next */
                        EIG_linear_solver_matrix_add(solver, i, i, 1.0);
@@ -2073,53 +2106,87 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
                                EIG_linear_solver_matrix_add(solver, i > 0 ? i - 1 : np - 1, i, -v->sinratio);
                        }
                        else {
-                               if (i > 0)
+                               if (i > 0) {
                                        EIG_linear_solver_matrix_add(solver, i - 1, i, -v->sinratio);
+                               }
                        }
 
-                       /* residue np + i (if cycle) else np - 1 + i:
+                       /* residue np + 2*i (if cycle) else np - 1 + 2*i:
                         * right offset for parm i matches its spec; weighted */
-                       row = iscycle ? np + i : np - 1 + i;
+                       row = iscycle ? np + 2 * i : np - 1 + 2 *  i;
                        EIG_linear_solver_matrix_add(solver, row, i, weight);
                        EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * eright->offset_r);
+#ifdef DEBUG_ADJUST
+                       printf("b[%d]=%f * %f, for e%d->offset_r\n", row, weight, eright->offset_r, BM_elem_index_get(eright->e));
+#endif
+                       
+                       /* residue np + 2*i + 1 (if cycle) else np - 1 + 2*i + 1:
+                        * left offset for parm i matches its spec; weighted */
+                        row = row + 1;
+                       EIG_linear_solver_matrix_add(solver, row, (i == np - 1) ? 0 : i + 1, weight * v->adjchain->sinratio);
+                       EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * enextleft->offset_l);
+#ifdef DEBUG_ADJUST
+                       printf("b[%d]=%f * %f, for e%d->offset_l\n", row, weight, enextleft->offset_l,
+                               BM_elem_index_get(enextleft->e));
+#endif
                }
                else {
                        /* not a cycle, and last of chain */
                        eleft = v->elast;
+#ifdef DEBUG_ADJUST
+                       printf("p%d: e%d->offset_l = %f\n", i, BM_elem_index_get(eleft->e), eleft->offset_l);
+#endif
                        /* second part of residue i for last i */
                        EIG_linear_solver_matrix_add(solver, i - 1, i, -1.0);
-                       /* residue 2 * np -2 : last spec match residue is for left offset of final parm */
-                       row = 2 * np - 2;
-                       EIG_linear_solver_matrix_add(solver, row, i, weight);
-                       EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * eleft->offset_l);
                }
                i++;
                v = v->adjchain;
        } while (v && v != vstart);
        EIG_linear_solver_solve(solver);
+#ifdef DEBUG_ADJUST
+       /* Note: this print only works after solve, but by that time b has been cleared */
+       EIG_linear_solver_print_matrix(solver);
+       printf("\nSolution:\n");
+       for (i = 0; i < np; i++)
+               printf("p%d = %f\n", i, EIG_linear_solver_variable_get(solver, 0, i));
+#endif
 
        /* Use the solution to set new widths */
        v = vstart;
        i = 0;
        do {
                val = EIG_linear_solver_variable_get(solver, 0, i);
-               if (iscycle || v->adjchain != NULL) {
+               if (iscycle || i < np - 1) {
                        eright = v->efirst;
                        eleft = v->elast;
                        eright->offset_r = (float)val;
+#ifdef DEBUG_ADJUST
+                       printf("e%d->offset_r = %f\n", BM_elem_index_get(eright->e), eright->offset_r);
+#endif
                        if (iscycle || v != vstart) {
                                eleft->offset_l = (float)(v->sinratio * val);
+#ifdef DEBUG_ADJUST
+                               printf("e%d->offset_l = %f\n", BM_elem_index_get(eleft->e), eleft->offset_l);
+#endif
                        }
                }
                else {
                        /* not a cycle, and last of chain */
                        eleft = v->elast;
                        eleft->offset_l = (float)val;
+#ifdef DEBUG_ADJUST
+                       printf("e%d->offset_l = %f\n", BM_elem_index_get(eleft->e), eleft->offset_l);
+#endif
                }
                i++;
                v = v->adjchain;
        } while (v && v != vstart);
 
+#ifdef DEBUG_ADJUST
+               print_adjust_stats(vstart);
+               EIG_linear_solver_print_matrix(solver);
+#endif
+
        EIG_linear_solver_delete(solver);
 }
 
index 9f1de64c2e9187fb5b543d1f78cb356d7881cab2..537a3e3a07e70818ea095d8e30f53462079c954f 100644 (file)
@@ -547,6 +547,7 @@ if(WITH_CYCLES)
                add_cycles_render_test(shader)
                add_cycles_render_test(shader_tangent)
                add_cycles_render_test(shadow_catcher)
+               add_cycles_render_test(sss)
                add_cycles_render_test(texture_space)
                add_cycles_render_test(volume)
        else()