Blender V2.61 - r43446

filter.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2011, Blender Foundation.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include "camera.h"
00020 #include "device.h"
00021 #include "filter.h"
00022 #include "scene.h"
00023 
00024 #include "kernel_types.h"
00025 
00026 #include "util_algorithm.h"
00027 #include "util_debug.h"
00028 #include "util_math.h"
00029 
00030 CCL_NAMESPACE_BEGIN
00031 
00032 Filter::Filter()
00033 {
00034     filter_type = FILTER_BOX;
00035     filter_width = 1.0f;
00036     need_update = true;
00037 }
00038 
00039 Filter::~Filter()
00040 {
00041 }
00042 
00043 static float filter_func_box(float v, float width)
00044 {
00045     return (float)1;
00046 }
00047 
00048 static float filter_func_gaussian(float v, float width)
00049 {
00050     v *= (float)2/width;
00051     return (float)expf((float)-2*v*v);
00052 }
00053 
00054 static vector<float> filter_table(FilterType type, float width)
00055 {
00056     const int filter_table_size = FILTER_TABLE_SIZE-1;
00057     vector<float> filter_table_cdf(filter_table_size+1);
00058     vector<float> filter_table(filter_table_size+1);
00059     float (*filter_func)(float, float) = NULL;
00060     int i, half_size = filter_table_size/2;
00061 
00062     switch(type) {
00063         case FILTER_BOX:
00064             filter_func = filter_func_box;
00065             break;
00066         case FILTER_GAUSSIAN:
00067             filter_func = filter_func_gaussian;
00068             break;
00069         default:
00070             assert(0);
00071     }
00072 
00073     /* compute cumulative distribution function */
00074     filter_table_cdf[0] = 0.0f;
00075     
00076     for(i=0; i<filter_table_size; i++) {
00077         float x = i*width*0.5f/(filter_table_size-1);
00078         float y = filter_func(x, width);
00079         filter_table_cdf[i+1] += filter_table_cdf[i] + fabsf(y);
00080     }
00081 
00082     for(i=0; i<=filter_table_size; i++)
00083         filter_table_cdf[i] /= filter_table_cdf[filter_table_size];
00084     
00085     /* create importance sampling table */
00086     for(i=0; i<=half_size; i++) {
00087         float x = i/(float)half_size;
00088         int index = upper_bound(filter_table_cdf.begin(), filter_table_cdf.end(), x) - filter_table_cdf.begin();
00089         float t;
00090 
00091         if(index < filter_table_size+1) {
00092             t = (x - filter_table_cdf[index])/(filter_table_cdf[index+1] - filter_table_cdf[index]);
00093         }
00094         else {
00095             t = 0.0f;
00096             index = filter_table_size;
00097         }
00098 
00099         float y = ((index + t)/(filter_table_size))*width;
00100 
00101         filter_table[half_size+i] = 0.5f*(1.0f + y);
00102         filter_table[half_size-i] = 0.5f*(1.0f - y);
00103     }
00104 
00105     return filter_table;
00106 }
00107 
00108 void Filter::device_update(Device *device, DeviceScene *dscene)
00109 {
00110     if(!need_update)
00111         return;
00112 
00113     device_free(device, dscene);
00114 
00115     /* update __filter_table */
00116     vector<float> table = filter_table(filter_type, filter_width);
00117 
00118     dscene->filter_table.copy(&table[0], table.size());
00119     device->tex_alloc("__filter_table", dscene->filter_table, true);
00120 
00121     need_update = false;
00122 }
00123 
00124 void Filter::device_free(Device *device, DeviceScene *dscene)
00125 {
00126     device->tex_free(dscene->filter_table);
00127     dscene->filter_table.clear();
00128 }
00129 
00130 bool Filter::modified(const Filter& filter)
00131 {
00132     return !(filter_type == filter.filter_type &&
00133         filter_width == filter.filter_width);
00134 }
00135 
00136 void Filter::tag_update(Scene *scene)
00137 {
00138     need_update = true;
00139 }
00140 
00141 CCL_NAMESPACE_END
00142