Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Tue, 27 Mar 2018 05:08:58 +0000 (07:08 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 27 Mar 2018 05:08:58 +0000 (07:08 +0200)
intern/cycles/kernel/kernel_path_state.h
intern/cycles/kernel/kernel_random.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/kernel_volume.h
source/blender/editors/sculpt_paint/CMakeLists.txt
source/blender/editors/sculpt_paint/paint_curve.c
source/blender/editors/sculpt_paint/paint_curve_undo.c [new file with mode: 0644]
source/blender/editors/sculpt_paint/paint_intern.h

index 90937dbf86e7ed074647de4ff4ed52b0f1c08992..479bb22d7808659ac81535c7379ee0efab7d87fe 100644 (file)
@@ -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;
index efb9048beb8b44b6efaf7cb11bb6b0fdc42730a1..93152e9ff1c4ab3fa8297aae15192a1f82ab81eb 100644 (file)
@@ -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,
index 2945cdb45934112e871446f559ad7bfac55a65f2..af1ecb057880cd6cb4c6b1e19cd4ea21b858efbf 100644 (file)
@@ -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;
index 88360e5f1ae5afde85cdcd4b4cd8789f1c6e8612..86378289b02a70fcc9dcc4b212908acdb1d3e477 100644 (file)
@@ -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;
index 1a70938258126e84f029916d4c85bb6f871bae82..040bcc10ca2b6f230cc1a0118c4ac8e7bca9a5c6 100644 (file)
@@ -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
index c9ad4a46a137e9c73a2a39314184c8ab6ec89447..fb8dea2af0e3a26d653bcd16f590ed0634b3b61e 100644 (file)
@@ -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 (file)
index 0000000..70f9299
--- /dev/null
@@ -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);
+}
index 089a12dbd45e168b30364ec59adb5ee66a5418f5..ccca0d248a583c195a07af36cb82124397c5e69c 100644 (file)
@@ -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 */