diff options
-rw-r--r-- | intern/cycles/kernel/kernel_path_state.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_random.h | 13 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_volume.h | 81 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_curve.c | 96 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_curve_undo.c | 129 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_intern.h | 4 |
8 files changed, 199 insertions, 128 deletions
diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h index 90937dbf86e..479bb22d780 100644 --- a/intern/cycles/kernel/kernel_path_state.h +++ b/intern/cycles/kernel/kernel_path_state.h @@ -60,8 +60,6 @@ ccl_device_inline void path_state_init(KernelGlobals *kg, if(kernel_data.integrator.use_volumes) { /* Initialize volume stack with volume we are inside of. */ kernel_volume_stack_init(kg, stack_sd, state, ray, state->volume_stack); - /* Seed RNG for cases where we can't use stratified samples .*/ - state->rng_congruential = lcg_init(rng_hash + sample*0x51633e2d); } else { state->volume_stack[0].shader = SHADER_NONE; diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h index efb9048beb8..93152e9ff1c 100644 --- a/intern/cycles/kernel/kernel_random.h +++ b/intern/cycles/kernel/kernel_random.h @@ -199,6 +199,19 @@ ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, fx, fy); } +ccl_device_inline float path_state_rng_1D_hash(KernelGlobals *kg, + const ccl_addr_space PathState *state, + uint hash) +{ + /* Use a hash instead of dimension, this is not great but avoids adding + * more dimensions to each bounce which reduces quality of dimensions we + * are already using. */ + return path_rng_1D(kg, + cmj_hash_simple(state->rng_hash, hash), + state->sample, state->num_samples, + state->rng_offset); +} + ccl_device_inline float path_branched_rng_1D( KernelGlobals *kg, uint rng_hash, diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 2945cdb4593..af1ecb05788 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -1107,7 +1107,6 @@ typedef struct PathState { #ifdef __VOLUME__ int volume_bounce; int volume_bounds_bounce; - uint rng_congruential; VolumeStack volume_stack[VOLUME_STACK_SIZE]; #endif } PathState; diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 88360e5f1ae..86378289b02 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -156,6 +156,24 @@ ccl_device int volume_stack_sampling_method(KernelGlobals *kg, VolumeStack *stac return method; } +ccl_device_inline void kernel_volume_step_init(KernelGlobals *kg, + ccl_addr_space PathState *state, + float t, + float *step_size, + float *step_offset) +{ + const int max_steps = kernel_data.integrator.volume_max_steps; + float step = min(kernel_data.integrator.volume_step_size, t); + + /* compute exact steps in advance for malloc */ + if(t > max_steps * step) { + step = t / (float)max_steps; + } + + *step_size = step; + *step_offset = path_state_rng_1D_hash(kg, state, 0x1e31d8a4) * step; +} + /* Volume Shadows * * These functions are used to attenuate shadow rays to lights. Both absorption @@ -188,8 +206,8 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, /* prepare for stepping */ int max_steps = kernel_data.integrator.volume_max_steps; - float step = kernel_data.integrator.volume_step_size; - float random_jitter_offset = lcg_step_float_addrspace(&state->rng_congruential) * step; + float step_offset, step_size; + kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset); /* compute extinction at the start */ float t = 0.0f; @@ -198,14 +216,15 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, for(int i = 0; i < max_steps; i++) { /* advance to new position */ - float new_t = min(ray->t, (i+1) * step); - float dt = new_t - t; + float new_t = min(ray->t, (i+1) * step_size); - /* use random position inside this segment to sample shader */ - if(new_t == ray->t) - random_jitter_offset = lcg_step_float_addrspace(&state->rng_congruential) * dt; + /* use random position inside this segment to sample shader, adjust + * for last step that is shorter than other steps. */ + if(new_t == ray->t) { + step_offset *= (new_t - t) / step_size; + } - float3 new_P = ray->P + ray->D * (t + random_jitter_offset); + float3 new_P = ray->P + ray->D * (t + step_offset); float3 sigma_t; /* compute attenuation over segment */ @@ -504,8 +523,8 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance( /* prepare for stepping */ int max_steps = kernel_data.integrator.volume_max_steps; - float step_size = kernel_data.integrator.volume_step_size; - float random_jitter_offset = lcg_step_float_addrspace(&state->rng_congruential) * step_size; + float step_offset, step_size; + kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset); /* compute coefficients at the start */ float t = 0.0f; @@ -522,11 +541,13 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance( float new_t = min(ray->t, (i+1) * step_size); float dt = new_t - t; - /* use random position inside this segment to sample shader */ - if(new_t == ray->t) - random_jitter_offset = lcg_step_float_addrspace(&state->rng_congruential) * dt; + /* use random position inside this segment to sample shader, + * for last shorter step we remap it to fit within the segment. */ + if(new_t == ray->t) { + step_offset *= (new_t - t) / step_size; + } - float3 new_P = ray->P + ray->D * (t + random_jitter_offset); + float3 new_P = ray->P + ray->D * (t + step_offset); VolumeShaderCoefficients coeff; /* compute segment */ @@ -694,19 +715,12 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta /* prepare for volume stepping */ int max_steps; - float step_size, random_jitter_offset; + float step_size, step_offset; if(heterogeneous) { - const int global_max_steps = kernel_data.integrator.volume_max_steps; - step_size = kernel_data.integrator.volume_step_size; - /* compute exact steps in advance for malloc */ - if(ray->t > global_max_steps*step_size) { - max_steps = global_max_steps; - step_size = ray->t / (float)max_steps; - } - else { - max_steps = max((int)ceilf(ray->t/step_size), 1); - } + max_steps = kernel_data.integrator.volume_max_steps; + kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset); + #ifdef __KERNEL_CPU__ /* NOTE: For the branched path tracing it's possible to have direct * and indirect light integration both having volume segments allocated. @@ -723,19 +737,18 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta sizeof(*kg->decoupled_volume_steps)); if(kg->decoupled_volume_steps[index] == NULL) { kg->decoupled_volume_steps[index] = - (VolumeStep*)malloc(sizeof(VolumeStep)*global_max_steps); + (VolumeStep*)malloc(sizeof(VolumeStep)*max_steps); } segment->steps = kg->decoupled_volume_steps[index]; ++kg->decoupled_volume_steps_index; #else segment->steps = (VolumeStep*)malloc(sizeof(VolumeStep)*max_steps); #endif - random_jitter_offset = lcg_step_float(&state->rng_congruential) * step_size; } else { max_steps = 1; step_size = ray->t; - random_jitter_offset = 0.0f; + step_offset = 0.0f; segment->steps = &segment->stack_step; } @@ -757,11 +770,13 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta float new_t = min(ray->t, (i+1) * step_size); float dt = new_t - t; - /* use random position inside this segment to sample shader */ - if(heterogeneous && new_t == ray->t) - random_jitter_offset = lcg_step_float(&state->rng_congruential) * dt; + /* use random position inside this segment to sample shader, + * for last shorter step we remap it to fit within the segment. */ + if(new_t == ray->t) { + step_offset *= (new_t - t) / step_size; + } - float3 new_P = ray->P + ray->D * (t + random_jitter_offset); + float3 new_P = ray->P + ray->D * (t + step_offset); VolumeShaderCoefficients coeff; /* compute segment */ @@ -818,7 +833,7 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta step->accum_transmittance = accum_transmittance; step->cdf_distance = cdf_distance; step->t = new_t; - step->shade_t = t + random_jitter_offset; + step->shade_t = t + step_offset; /* stop if at the end of the volume */ t = new_t; diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 1a709382581..040bcc10ca2 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -43,6 +43,7 @@ set(INC_SYS set(SRC paint_cursor.c paint_curve.c + paint_curve_undo.c paint_hide.c paint_image.c paint_image_2d.c diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c index c9ad4a46a13..fb8dea2af0e 100644 --- a/source/blender/editors/sculpt_paint/paint_curve.c +++ b/source/blender/editors/sculpt_paint/paint_curve.c @@ -35,7 +35,6 @@ #include "DNA_workspace_types.h" #include "BLI_math_vector.h" -#include "BLI_string.h" #include "BKE_context.h" #include "BKE_main.h" @@ -43,7 +42,6 @@ #include "DEG_depsgraph.h" -#include "ED_paint.h" #include "ED_view3d.h" #include "WM_api.h" @@ -59,7 +57,6 @@ #define PAINT_CURVE_SELECT_THRESHOLD 40.0f #define PAINT_CURVE_POINT_SELECT(pcp, i) (*(&pcp->bez.f1 + i) = SELECT) - int paint_curve_poll(bContext *C) { const WorkSpace *workspace = CTX_wm_workspace(C); @@ -85,91 +82,6 @@ int paint_curve_poll(bContext *C) return false; } -/* Paint Curve Undo*/ - -typedef struct UndoCurve { - struct UndoImageTile *next, *prev; - - PaintCurvePoint *points; /* points of curve */ - int tot_points; - int active_point; - - char idname[MAX_ID_NAME]; /* name instead of pointer*/ -} UndoCurve; - -static void paintcurve_undo_restore(bContext *C, ListBase *lb) -{ - Paint *p = BKE_paint_get_active_from_context(C); - UndoCurve *uc; - PaintCurve *pc = NULL; - - if (p->brush) { - pc = p->brush->paint_curve; - } - - if (!pc) - return; - - uc = (UndoCurve *)lb->first; - - if (STREQLEN(uc->idname, pc->id.name, BLI_strnlen(uc->idname, sizeof(uc->idname)))) { - SWAP(PaintCurvePoint *, pc->points, uc->points); - SWAP(int, pc->tot_points, uc->tot_points); - SWAP(int, pc->add_index, uc->active_point); - } -} - -static void paintcurve_undo_delete(ListBase *lb) -{ - UndoCurve *uc; - uc = (UndoCurve *)lb->first; - - if (uc->points) - MEM_freeN(uc->points); - uc->points = NULL; -} - - -static void paintcurve_undo_begin(bContext *C, wmOperator *op, PaintCurve *pc) -{ - ePaintMode mode = BKE_paintmode_get_active_from_context(C); - ListBase *lb = NULL; - int undo_stack_id; - UndoCurve *uc; - - switch (mode) { - case ePaintTexture2D: - case ePaintTextureProjective: - undo_stack_id = UNDO_PAINT_IMAGE; - break; - - case ePaintSculpt: - undo_stack_id = UNDO_PAINT_MESH; - break; - - default: - /* do nothing, undo is handled by global */ - return; - } - - - ED_undo_paint_push_begin(undo_stack_id, op->type->name, - paintcurve_undo_restore, paintcurve_undo_delete, NULL); - lb = undo_paint_push_get_list(undo_stack_id); - - uc = MEM_callocN(sizeof(*uc), "Undo_curve"); - - lb->first = uc; - - BLI_strncpy(uc->idname, pc->id.name, sizeof(uc->idname)); - uc->tot_points = pc->tot_points; - uc->active_point = pc->add_index; - uc->points = MEM_dupallocN(pc->points); - - undo_paint_push_count_alloc(undo_stack_id, sizeof(*uc) + sizeof(*pc->points) * pc->tot_points); - - ED_undo_paint_push_end(undo_stack_id); -} #define SEL_F1 (1 << 0) #define SEL_F2 (1 << 1) #define SEL_F3 (1 << 2) @@ -295,7 +207,7 @@ static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2]) br->paint_curve = pc = BKE_paint_curve_add(bmain, "PaintCurve"); } - paintcurve_undo_begin(C, op, pc); + ED_paintcurve_undo_push(C, op, pc); pcp = MEM_mallocN((pc->tot_points + 1) * sizeof(PaintCurvePoint), "PaintCurvePoint"); add_index = pc->add_index; @@ -394,7 +306,7 @@ static int paintcurve_delete_point_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - paintcurve_undo_begin(C, op, pc); + ED_paintcurve_undo_push(C, op, pc); #define DELETE_TAG 2 @@ -471,7 +383,7 @@ static bool paintcurve_point_select(bContext *C, wmOperator *op, const int loc[2 if (!pc) return false; - paintcurve_undo_begin(C, op, pc); + ED_paintcurve_undo_push(C, op, pc); if (toggle) { PaintCurvePoint *pcp; @@ -655,7 +567,7 @@ static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *e op->customdata = psd; if (do_select) - paintcurve_undo_begin(C, op, pc); + ED_paintcurve_undo_push(C, op, pc); /* first, clear all selection from points */ for (i = 0; i < pc->tot_points; i++) diff --git a/source/blender/editors/sculpt_paint/paint_curve_undo.c b/source/blender/editors/sculpt_paint/paint_curve_undo.c new file mode 100644 index 00000000000..70f92999864 --- /dev/null +++ b/source/blender/editors/sculpt_paint/paint_curve_undo.c @@ -0,0 +1,129 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/sculpt_paint/paint_curve_undo.c + * \ingroup edsculpt + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_brush_types.h" +#include "DNA_space_types.h" + +#include "BLI_string.h" + +#include "BKE_context.h" +#include "BKE_paint.h" + +#include "ED_paint.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "paint_intern.h" + +typedef struct UndoCurve { + struct UndoImageTile *next, *prev; + + PaintCurvePoint *points; /* points of curve */ + int tot_points; + int active_point; + + char idname[MAX_ID_NAME]; /* name instead of pointer*/ +} UndoCurve; + +static void paintcurve_undo_restore(bContext *C, ListBase *lb) +{ + Paint *p = BKE_paint_get_active_from_context(C); + UndoCurve *uc; + PaintCurve *pc = NULL; + + if (p->brush) { + pc = p->brush->paint_curve; + } + + if (!pc) { + return; + } + + uc = (UndoCurve *)lb->first; + + if (STREQLEN(uc->idname, pc->id.name, BLI_strnlen(uc->idname, sizeof(uc->idname)))) { + SWAP(PaintCurvePoint *, pc->points, uc->points); + SWAP(int, pc->tot_points, uc->tot_points); + SWAP(int, pc->add_index, uc->active_point); + } +} + +static void paintcurve_undo_delete(ListBase *lb) +{ + UndoCurve *uc; + uc = (UndoCurve *)lb->first; + + if (uc->points) + MEM_freeN(uc->points); + uc->points = NULL; +} + +/** + * \note This is called before executing steps (not after). + */ +void ED_paintcurve_undo_push(bContext *C, wmOperator *op, PaintCurve *pc) +{ + ePaintMode mode = BKE_paintmode_get_active_from_context(C); + ListBase *lb = NULL; + int undo_stack_id; + UndoCurve *uc; + + switch (mode) { + case ePaintTexture2D: + case ePaintTextureProjective: + undo_stack_id = UNDO_PAINT_IMAGE; + break; + + case ePaintSculpt: + undo_stack_id = UNDO_PAINT_MESH; + break; + + default: + /* do nothing, undo is handled by global */ + return; + } + + + ED_undo_paint_push_begin(undo_stack_id, op->type->name, + paintcurve_undo_restore, paintcurve_undo_delete, NULL); + lb = undo_paint_push_get_list(undo_stack_id); + + uc = MEM_callocN(sizeof(*uc), "Undo_curve"); + + lb->first = uc; + + BLI_strncpy(uc->idname, pc->id.name, sizeof(uc->idname)); + uc->tot_points = pc->tot_points; + uc->active_point = pc->add_index; + uc->points = MEM_dupallocN(pc->points); + + undo_paint_push_count_alloc(undo_stack_id, sizeof(*uc) + sizeof(*pc->points) * pc->tot_points); + + ED_undo_paint_push_end(undo_stack_id); +} diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 089a12dbd45..ccca0d248a5 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -43,6 +43,7 @@ struct MTex; struct Object; struct PaintStroke; struct Paint; +struct PaintCurve; struct PointerRNA; struct rcti; struct Scene; @@ -342,6 +343,9 @@ void PAINTCURVE_OT_slide(struct wmOperatorType *ot); void PAINTCURVE_OT_draw(struct wmOperatorType *ot); void PAINTCURVE_OT_cursor(struct wmOperatorType *ot); +/* paint_curve_undo.c */ +void ED_paintcurve_undo_push(struct bContext *C, struct wmOperator *op, struct PaintCurve *pc); + /* image painting blur kernel */ typedef struct { float *wdata; /* actual kernel */ |