Blender V2.61 - r43446
|
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