Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/render/filter.cpp')
-rw-r--r--intern/cycles/render/filter.cpp129
1 files changed, 129 insertions, 0 deletions
diff --git a/intern/cycles/render/filter.cpp b/intern/cycles/render/filter.cpp
new file mode 100644
index 00000000000..d7682bedc12
--- /dev/null
+++ b/intern/cycles/render/filter.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * 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.
+ */
+
+#include "camera.h"
+#include "device.h"
+#include "filter.h"
+#include "scene.h"
+
+#include "util_algorithm.h"
+#include "util_debug.h"
+#include "util_math.h"
+
+CCL_NAMESPACE_BEGIN
+
+Filter::Filter()
+{
+ filter_type = FILTER_BOX;
+ filter_width = 1.0f;
+ need_update = true;
+}
+
+Filter::~Filter()
+{
+}
+
+static float filter_func_box(float v, float width)
+{
+ return (float)1;
+}
+
+static float filter_func_gaussian(float v, float width)
+{
+ v *= (float)2/width;
+ return (float)expf((float)-2*v*v);
+}
+
+static vector<float> filter_table(FilterType type, float width)
+{
+ const int filter_table_size = 256;
+ vector<float> filter_table_cdf(filter_table_size+1);
+ vector<float> filter_table(filter_table_size+1);
+ float (*filter_func)(float, float) = NULL;
+ int i, half_size = filter_table_size/2;
+
+ switch(type) {
+ case FILTER_BOX:
+ filter_func = filter_func_box;
+ break;
+ case FILTER_GAUSSIAN:
+ filter_func = filter_func_gaussian;
+ break;
+ default:
+ assert(0);
+ }
+
+ /* compute cumulative distribution function */
+ filter_table_cdf[0] = 0.0f;
+
+ for(i=0; i<filter_table_size; i++) {
+ float x = i*width*0.5f/(filter_table_size-1);
+ float y = filter_func(x, width);
+ filter_table_cdf[i+1] += filter_table_cdf[i] + fabsf(y);
+ }
+
+ for(i=0; i<=filter_table_size; i++)
+ filter_table_cdf[i] /= filter_table_cdf[filter_table_size];
+
+ /* create importance sampling table */
+ for(i=0; i<=half_size; i++) {
+ float x = i/(float)half_size;
+ int index = upper_bound(filter_table_cdf.begin(), filter_table_cdf.end(), x) - filter_table_cdf.begin();
+ float t;
+
+ if(index < filter_table_size+1) {
+ t = (x - filter_table_cdf[index])/(filter_table_cdf[index+1] - filter_table_cdf[index]);
+ }
+ else {
+ t = 0.0f;
+ index = filter_table_size;
+ }
+
+ float y = ((index + t)/(filter_table_size))*width;
+
+ filter_table[half_size+i] = 0.5f*(1.0f + y);
+ filter_table[half_size-i] = 0.5f*(1.0f - y);
+ }
+
+ return filter_table;
+}
+
+void Filter::device_update(Device *device, DeviceScene *dscene)
+{
+ if(!need_update)
+ return;
+
+ device_free(device, dscene);
+
+ /* update __filter_table */
+ vector<float> table = filter_table(filter_type, filter_width);
+
+ dscene->filter_table.copy(&table[0], table.size());
+ device->tex_alloc("__filter_table", dscene->filter_table, true);
+
+ need_update = false;
+}
+
+void Filter::device_free(Device *device, DeviceScene *dscene)
+{
+ device->tex_free(dscene->filter_table);
+ dscene->filter_table.clear();
+}
+
+CCL_NAMESPACE_END
+