[Bf-blender-cvs] [6a529e1] master: Cycles: Support user-defined shutter curve

Sergey Sharybin noreply at git.blender.org
Tue Oct 27 23:17:13 CET 2015


Commit: 6a529e14f4c25fc20b797799b602472d3a22a0f9
Author: Sergey Sharybin
Date:   Tue Oct 27 13:16:04 2015 +0500
Branches: master
https://developer.blender.org/rB6a529e14f4c25fc20b797799b602472d3a22a0f9

Cycles: Support user-defined shutter curve

Previously shutter was instantly opening, staying opened for the shutter time
period of time and then instantly closing. This isn't quite how real cameras
are working, where shutter is opening with some curve. Now it is possible to
define user curve for how much shutter is opened across the sampling period
of time.

This could be used for example to make motion blur trails softer.

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

M	intern/cycles/kernel/kernel_camera.h
M	intern/cycles/kernel/kernel_types.h
M	intern/cycles/render/camera.cpp
M	intern/cycles/render/camera.h
M	intern/cycles/render/scene.cpp
M	intern/cycles/util/util_math_cdf.cpp

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

diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index 8d439ce..01017ea 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -290,10 +290,13 @@ ccl_device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, f
 
 #ifdef __CAMERA_MOTION__
 	/* motion blur */
-	if(kernel_data.cam.shuttertime == -1.0f)
+	if(kernel_data.cam.shuttertime == -1.0f) {
 		ray->time = TIME_INVALID;
-	else
-		ray->time = time;
+	}
+	else {
+		const int shutter_table_offset = kernel_data.cam.shutter_table_offset;
+		ray->time = lookup_table_read(kg, time, shutter_table_offset, SHUTTER_TABLE_SIZE);
+	}
 #endif
 
 	/* sample */
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 740a5f1..1d71e64 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -39,6 +39,7 @@ CCL_NAMESPACE_BEGIN
 #define LIGHT_SIZE			5
 #define FILTER_TABLE_SIZE	256
 #define RAMP_TABLE_SIZE		256
+#define SHUTTER_TABLE_SIZE		256
 #define PARTICLE_SIZE 		5
 #define TIME_INVALID		FLT_MAX
 
@@ -813,6 +814,9 @@ typedef struct KernelCamera {
 	 * Used for camera zoom motion blur,
 	 */
 	PerspectiveMotionTransform perspective_motion;
+
+	int shutter_table_offset;
+	int pad;
 } KernelCamera;
 
 typedef struct KernelFilm {
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 88ff7fb..c599719 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -18,18 +18,36 @@
 #include "mesh.h"
 #include "object.h"
 #include "scene.h"
+#include "tables.h"
 
 #include "device.h"
 
 #include "util_foreach.h"
+#include "util_function.h"
+#include "util_math_cdf.h"
 #include "util_vector.h"
 
 CCL_NAMESPACE_BEGIN
 
+static float shutter_curve_eval(float x,
+                                float shutter_curve[RAMP_TABLE_SIZE])
+{
+	x *= RAMP_TABLE_SIZE;
+	int index = (int)x;
+	float frac = x - index;
+	if(index < RAMP_TABLE_SIZE - 1) {
+		return lerp(shutter_curve[index], shutter_curve[index + 1], frac);
+	}
+	else {
+		return shutter_curve[RAMP_TABLE_SIZE - 1];
+	}
+}
+
 Camera::Camera()
 {
 	shuttertime = 1.0f;
 	motion_position = MOTION_POSITION_CENTER;
+	shutter_table_offset = TABLE_OFFSET_INVALID;
 
 	aperturesize = 0.0f;
 	focaldistance = 10.0f;
@@ -85,6 +103,12 @@ Camera::Camera()
 	need_device_update = true;
 	need_flags_update = true;
 	previous_need_motion = -1;
+
+	/* Initialize shutter curve. */
+	const int num_shutter_points = sizeof(shutter_curve) / sizeof(*shutter_curve);
+	for(int i = 0; i < num_shutter_points; ++i) {
+		shutter_curve[i] = 1.0f;
+	}
 }
 
 Camera::~Camera()
@@ -279,6 +303,23 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
 	/* motion blur */
 #ifdef __CAMERA_MOTION__
 	kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: -1.0f;
+
+	if(need_motion == Scene::MOTION_BLUR) {
+		vector<float> shutter_table;
+		util_cdf_inverted(SHUTTER_TABLE_SIZE,
+		                  0.0f,
+		                  1.0f,
+		                  function_bind(shutter_curve_eval, _1, shutter_curve),
+		                  false,
+		                  shutter_table);
+		shutter_table_offset = scene->lookup_tables->add_table(dscene,
+		                                                       shutter_table);
+		kcam->shutter_table_offset = (int)shutter_table_offset;
+	}
+	else if(shutter_table_offset != TABLE_OFFSET_INVALID) {
+		scene->lookup_tables->remove_table(shutter_table_offset);
+		shutter_table_offset = TABLE_OFFSET_INVALID;
+	}
 #else
 	kcam->shuttertime = -1.0f;
 #endif
@@ -342,9 +383,14 @@ void Camera::device_update_volume(Device * /*device*/,
 	need_flags_update = false;
 }
 
-void Camera::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
+void Camera::device_free(Device * /*device*/,
+                         DeviceScene * /*dscene*/,
+                         Scene *scene)
 {
-	/* nothing to free, only writing to constant memory */
+	if(shutter_table_offset != TABLE_OFFSET_INVALID) {
+		scene->lookup_tables->remove_table(shutter_table_offset);
+		shutter_table_offset = TABLE_OFFSET_INVALID;
+	}
 }
 
 bool Camera::modified(const Camera& cam)
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 53bd4f0..1c26afa 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -50,6 +50,8 @@ public:
 	/* motion blur */
 	float shuttertime;
 	MotionPosition motion_position;
+	float shutter_curve[RAMP_TABLE_SIZE];
+	size_t shutter_table_offset;
 
 	/* depth of field */
 	float focaldistance;
@@ -132,7 +134,7 @@ public:
 
 	void device_update(Device *device, DeviceScene *dscene, Scene *scene);
 	void device_update_volume(Device *device, DeviceScene *dscene, Scene *scene);
-	void device_free(Device *device, DeviceScene *dscene);
+	void device_free(Device *device, DeviceScene *dscene, Scene *scene);
 
 	bool modified(const Camera& cam);
 	bool motion_modified(const Camera& cam);
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 19d715d..25f8122 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -97,7 +97,7 @@ void Scene::free_memory(bool final)
 	particle_systems.clear();
 
 	if(device) {
-		camera->device_free(device, &dscene);
+		camera->device_free(device, &dscene, this);
 		film->device_free(device, &dscene, this);
 		background->device_free(device, &dscene);
 		integrator->device_free(device, &dscene);
diff --git a/intern/cycles/util/util_math_cdf.cpp b/intern/cycles/util/util_math_cdf.cpp
index cafe4c5..ec78ca1 100644
--- a/intern/cycles/util/util_math_cdf.cpp
+++ b/intern/cycles/util/util_math_cdf.cpp
@@ -37,7 +37,7 @@ void util_cdf_invert(const int resolution,
 			float x = i / (float)half_size;
 			int index = upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin();
 			float t;
-			if(index < cdf.size()) {
+			if(index < cdf.size() - 1) {
 				t = (x - cdf[index])/(cdf[index+1] - cdf[index]);
 			} else {
 				t = 0.0f;
@@ -49,11 +49,11 @@ void util_cdf_invert(const int resolution,
 		}
 	}
 	else {
-		for(int i = 0; i <= resolution; i++) {
+		for(int i = 0; i < resolution; i++) {
 			float x = from + range * (float)i * inv_resolution;
 			int index = upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin();
 			float t;
-			if(index < cdf.size()) {
+			if(index < cdf.size() - 1) {
 				t = (x - cdf[index])/(cdf[index+1] - cdf[index]);
 			} else {
 				t = 0.0f;




More information about the Bf-blender-cvs mailing list