From d3248bb50bf9f8f6aae6292e76ae1ed27dff159d Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Thu, 8 Feb 2018 10:48:24 -0500 Subject: Disable fast adjust code. Add other end spec matching. This fixes a few caess where new width adjustment code was less than ideal. --- source/blender/bmesh/tools/bmesh_bevel.c | 99 ++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 16 deletions(-) diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index e89f54349f7..beee9065ece 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -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); } -- cgit v1.2.3 From 8c8e53c12dfdb8a8d6f687b0a05bfca935402cc5 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 8 Feb 2018 13:32:07 +0100 Subject: Cycles tests: separate directory for sss tests. --- tests/python/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index 781e12a6955..63709aae74f 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -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() -- cgit v1.2.3 From 28e2bc90dd8df3032b831a502e15e3a2976eb9de Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 8 Feb 2018 13:58:02 +0100 Subject: Code refactor: remove unnecessary RNG offset in branched path code. This is only needed for SSS which bounces to a different shading point. --- intern/cycles/kernel/kernel_path_branched.h | 1 + intern/cycles/kernel/kernel_path_state.h | 2 -- intern/cycles/kernel/split/kernel_subsurface_scatter.h | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h index fe2a7d179a4..70d0292c5a5 100644 --- a/intern/cycles/kernel/kernel_path_branched.h +++ b/intern/cycles/kernel/kernel_path_branched.h @@ -372,6 +372,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, PathState hit_state = *state; path_state_branch(&hit_state, j, num_samples); + hit_state.rng_offset += PRNG_BOUNCE_NUM; #ifdef __VOLUME__ if(need_update_volume_stack) { diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h index 2ae866bb051..a16c20cbee6 100644 --- a/intern/cycles/kernel/kernel_path_state.h +++ b/intern/cycles/kernel/kernel_path_state.h @@ -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. */ diff --git a/intern/cycles/kernel/split/kernel_subsurface_scatter.h b/intern/cycles/kernel/split/kernel_subsurface_scatter.h index 38dd1dc5654..993e8d4d477 100644 --- a/intern/cycles/kernel/split/kernel_subsurface_scatter.h +++ b/intern/cycles/kernel/split/kernel_subsurface_scatter.h @@ -117,6 +117,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it *hit_state = branched_state->path_state; path_state_branch(hit_state, j, num_samples); + hit_state->rng_offset += PRNG_BOUNCE_NUM; #ifdef __VOLUME__ if(need_update_volume_stack) { -- cgit v1.2.3 From aabafece03fee807d6b9e5e6d40273f70cc4b9d8 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 8 Feb 2018 12:45:12 +0100 Subject: Code refactor: tweaks in SSS code to prepare for coming changes. This also fixes a subtle bug in the split kernel branched path SSS, the volume stack update can't be shared between multiple hit points. --- intern/cycles/kernel/kernel_path.h | 1 - intern/cycles/kernel/kernel_path_branched.h | 26 +++++++------ intern/cycles/kernel/kernel_path_subsurface.h | 4 +- intern/cycles/kernel/kernel_subsurface.h | 13 +++---- .../cycles/kernel/split/kernel_split_data_types.h | 4 -- .../kernel/split/kernel_subsurface_scatter.h | 43 +++++++++------------- 6 files changed, 38 insertions(+), 53 deletions(-) diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 1e98bca66ad..afca4575331 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -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, diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h index 70d0292c5a5..5f917d509ec 100644 --- a/intern/cycles/kernel/kernel_path_branched.h +++ b/intern/cycles/kernel/kernel_path_branched.h @@ -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,15 +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.rng_offset += PRNG_BOUNCE_NUM; + &hit_state, + sc); #ifdef __VOLUME__ if(need_update_volume_stack) { @@ -381,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, @@ -393,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, diff --git a/intern/cycles/kernel/kernel_path_subsurface.h b/intern/cycles/kernel/kernel_path_subsurface.h index c29b41e4222..a48bde6443e 100644 --- a/intern/cycles/kernel/kernel_path_subsurface.h +++ b/intern/cycles/kernel/kernel_path_subsurface.h @@ -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); diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h index 582a20704d3..f4759b26191 100644 --- a/intern/cycles/kernel/kernel_subsurface.h +++ b/intern/cycles/kernel/kernel_subsurface.h @@ -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); diff --git a/intern/cycles/kernel/split/kernel_split_data_types.h b/intern/cycles/kernel/split/kernel_split_data_types.h index 5f40fdc9240..56194d9f857 100644 --- a/intern/cycles/kernel/split/kernel_split_data_types.h +++ b/intern/cycles/kernel/split/kernel_split_data_types.h @@ -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 */ diff --git a/intern/cycles/kernel/split/kernel_subsurface_scatter.h b/intern/cycles/kernel/split/kernel_subsurface_scatter.h index 993e8d4d477..f902d000918 100644 --- a/intern/cycles/kernel/split/kernel_subsurface_scatter.h +++ b/intern/cycles/kernel/split/kernel_subsurface_scatter.h @@ -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,39 +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); - hit_state->rng_offset += PRNG_BOUNCE_NUM; - #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__ */ @@ -148,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, @@ -265,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, -- cgit v1.2.3 From 29d2ff7b31aef4fe490446e8a82fdc34021e2592 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 8 Feb 2018 16:14:04 +0100 Subject: Cycles: unify OSL BSSRDF closure into a single bssrdf() closure with method. This is similar to the upstream unified microfacet() closure, and makes it easier to extend in the future. --- intern/cycles/kernel/osl/osl_bssrdf.cpp | 133 +++++++-------------- intern/cycles/kernel/osl/osl_closures.cpp | 10 +- intern/cycles/kernel/osl/osl_closures.h | 10 +- .../cycles/kernel/shaders/node_principled_bsdf.osl | 2 +- .../kernel/shaders/node_subsurface_scattering.osl | 6 +- intern/cycles/kernel/shaders/stdosl.h | 5 +- 6 files changed, 49 insertions(+), 117 deletions(-) diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp index 3e7905f26df..db6426f60e5 100644 --- a/intern/cycles/kernel/osl/osl_bssrdf.cpp +++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp @@ -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 diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index 8acab1ab558..d0c357580fd 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -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); diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h index 38943b77656..dca7e74f154 100644 --- a/intern/cycles/kernel/osl/osl_closures.h +++ b/intern/cycles/kernel/osl/osl_closures.h @@ -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); diff --git a/intern/cycles/kernel/shaders/node_principled_bsdf.osl b/intern/cycles/kernel/shaders/node_principled_bsdf.osl index 6870d479af3..0e31dcedee4 100644 --- a/intern/cycles/kernel/shaders/node_principled_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_principled_bsdf.osl @@ -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); } diff --git a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl index 5ba8f34021d..c9983fcd5dd 100644 --- a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl +++ b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl @@ -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); } diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index c91d2918687..091ade4a60d 100644 --- a/intern/cycles/kernel/shaders/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -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; -- cgit v1.2.3 From 859379ac487509f3eed96de5c78f934fbd3490d2 Mon Sep 17 00:00:00 2001 From: Tamito Kajiyama Date: Fri, 9 Feb 2018 02:46:20 +0900 Subject: Fix for missing "Use Freestyle" toggle in the Cycles "Layer" options panel. Reviewed By: Brecht Van Lommel (brecht), Dalai Felinto (dfelinto) Differential Revision: https://developer.blender.org/D3048 --- intern/cycles/blender/addon/ui.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 07fd491dc04..e3076a8ec2c 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -449,6 +449,7 @@ 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 @@ -477,6 +478,10 @@ class CYCLES_RENDER_PT_layer_options(CyclesButtonsPanel, Panel): col.prop(rl, "use_ao", "Use AO") col.prop(rl, "use_solid", "Use Surfaces") col.prop(rl, "use_strand", "Use Hair") + if with_freestyle: + row = col.row() + row.prop(rl, "use_freestyle", "Use Freestyle") + row.active = rd.use_freestyle class CYCLES_RENDER_PT_layer_passes(CyclesButtonsPanel, Panel): -- cgit v1.2.3