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 "device.h" 00020 #include "light.h" 00021 #include "mesh.h" 00022 #include "object.h" 00023 #include "scene.h" 00024 #include "shader.h" 00025 00026 #include "util_foreach.h" 00027 #include "util_progress.h" 00028 00029 CCL_NAMESPACE_BEGIN 00030 00031 /* Light */ 00032 00033 Light::Light() 00034 { 00035 type = LIGHT_POINT; 00036 00037 co = make_float3(0.0f, 0.0f, 0.0f); 00038 00039 dir = make_float3(0.0f, 0.0f, 0.0f); 00040 size = 0.0f; 00041 00042 axisu = make_float3(0.0f, 0.0f, 0.0f); 00043 sizeu = 1.0f; 00044 axisv = make_float3(0.0f, 0.0f, 0.0f); 00045 sizev = 1.0f; 00046 00047 cast_shadow = true; 00048 shader = 0; 00049 } 00050 00051 void Light::tag_update(Scene *scene) 00052 { 00053 scene->light_manager->need_update = true; 00054 } 00055 00056 /* Light Manager */ 00057 00058 LightManager::LightManager() 00059 { 00060 need_update = true; 00061 } 00062 00063 LightManager::~LightManager() 00064 { 00065 } 00066 00067 void LightManager::device_update_distribution(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) 00068 { 00069 /* option to always sample all point lights */ 00070 bool multi_light = false; 00071 00072 /* count */ 00073 size_t num_lights = scene->lights.size(); 00074 size_t num_triangles = 0; 00075 00076 foreach(Object *object, scene->objects) { 00077 Mesh *mesh = object->mesh; 00078 bool have_emission = false; 00079 00080 /* skip if we have no emission shaders */ 00081 foreach(uint sindex, mesh->used_shaders) { 00082 Shader *shader = scene->shaders[sindex]; 00083 00084 if(shader->sample_as_light && shader->has_surface_emission) { 00085 have_emission = true; 00086 break; 00087 } 00088 } 00089 00090 /* count triangles */ 00091 if(have_emission) { 00092 for(size_t i = 0; i < mesh->triangles.size(); i++) { 00093 Shader *shader = scene->shaders[mesh->shader[i]]; 00094 00095 if(shader->sample_as_light && shader->has_surface_emission) 00096 num_triangles++; 00097 } 00098 } 00099 } 00100 00101 size_t num_distribution = num_triangles; 00102 00103 if(!multi_light) 00104 num_distribution += num_lights; 00105 00106 /* emission area */ 00107 float4 *distribution = dscene->light_distribution.resize(num_distribution + 1); 00108 float totarea = 0.0f; 00109 00110 /* triangles */ 00111 size_t offset = 0; 00112 size_t j = 0; 00113 00114 foreach(Object *object, scene->objects) { 00115 Mesh *mesh = object->mesh; 00116 bool have_emission = false; 00117 00118 /* skip if we have no emission shaders */ 00119 foreach(uint sindex, mesh->used_shaders) { 00120 Shader *shader = scene->shaders[sindex]; 00121 00122 if(shader->sample_as_light && shader->has_surface_emission) { 00123 have_emission = true; 00124 break; 00125 } 00126 } 00127 00128 /* sum area */ 00129 if(have_emission) { 00130 Transform tfm = object->tfm; 00131 int object_id = (mesh->transform_applied)? -j-1: j; 00132 00133 for(size_t i = 0; i < mesh->triangles.size(); i++) { 00134 Shader *shader = scene->shaders[mesh->shader[i]]; 00135 00136 if(shader->sample_as_light && shader->has_surface_emission) { 00137 distribution[offset].x = totarea; 00138 distribution[offset].y = __int_as_float(i + mesh->tri_offset); 00139 distribution[offset].z = 1.0f; 00140 distribution[offset].w = __int_as_float(object_id); 00141 offset++; 00142 00143 Mesh::Triangle t = mesh->triangles[i]; 00144 float3 p1 = transform(&tfm, mesh->verts[t.v[0]]); 00145 float3 p2 = transform(&tfm, mesh->verts[t.v[1]]); 00146 float3 p3 = transform(&tfm, mesh->verts[t.v[2]]); 00147 00148 totarea += triangle_area(p1, p2, p3); 00149 } 00150 } 00151 } 00152 00153 if(progress.get_cancel()) return; 00154 00155 j++; 00156 } 00157 00158 float trianglearea = totarea; 00159 00160 /* point lights */ 00161 if(!multi_light) { 00162 float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f; 00163 00164 for(size_t i = 0; i < scene->lights.size(); i++, offset++) { 00165 distribution[offset].x = totarea; 00166 distribution[offset].y = __int_as_float(-i-1); 00167 distribution[offset].z = 1.0f; 00168 distribution[offset].w = scene->lights[i]->size; 00169 totarea += lightarea; 00170 } 00171 } 00172 00173 /* normalize cumulative distribution functions */ 00174 distribution[num_distribution].x = totarea; 00175 distribution[num_distribution].y = 0.0f; 00176 distribution[num_distribution].z = 0.0f; 00177 distribution[num_distribution].w = 0.0f; 00178 00179 if(totarea > 0.0f) { 00180 for(size_t i = 0; i < num_distribution; i++) 00181 distribution[i].x /= totarea; 00182 distribution[num_distribution].x = 1.0f; 00183 } 00184 00185 if(progress.get_cancel()) return; 00186 00187 /* update device */ 00188 KernelIntegrator *kintegrator = &dscene->data.integrator; 00189 kintegrator->use_direct_light = (totarea > 0.0f) || (multi_light && num_lights); 00190 00191 if(kintegrator->use_direct_light) { 00192 /* number of emissives */ 00193 kintegrator->num_distribution = (totarea > 0.0f)? num_distribution: 0; 00194 00195 /* precompute pdfs */ 00196 kintegrator->pdf_triangles = 0.0f; 00197 kintegrator->pdf_lights = 0.0f; 00198 00199 if(multi_light) { 00200 /* sample one of all triangles and all lights */ 00201 kintegrator->num_all_lights = num_lights; 00202 00203 if(trianglearea > 0.0f) 00204 kintegrator->pdf_triangles = 1.0f/trianglearea; 00205 if(num_lights) 00206 kintegrator->pdf_lights = 1.0f; 00207 } 00208 else { 00209 /* sample one, with 0.5 probability of light or triangle */ 00210 kintegrator->num_all_lights = 0; 00211 00212 if(trianglearea > 0.0f) { 00213 kintegrator->pdf_triangles = 1.0f/trianglearea; 00214 if(num_lights) 00215 kintegrator->pdf_triangles *= 0.5f; 00216 } 00217 00218 if(num_lights) { 00219 kintegrator->pdf_lights = 1.0f/num_lights; 00220 if(trianglearea > 0.0f) 00221 kintegrator->pdf_lights *= 0.5f; 00222 } 00223 } 00224 00225 /* CDF */ 00226 device->tex_alloc("__light_distribution", dscene->light_distribution); 00227 } 00228 else 00229 dscene->light_distribution.clear(); 00230 } 00231 00232 void LightManager::device_update_points(Device *device, DeviceScene *dscene, Scene *scene) 00233 { 00234 if(scene->lights.size() == 0) 00235 return; 00236 00237 float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE); 00238 00239 for(size_t i = 0; i < scene->lights.size(); i++) { 00240 Light *light = scene->lights[i]; 00241 float3 co = light->co; 00242 float3 dir = normalize(light->dir); 00243 int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader); 00244 00245 if(!light->cast_shadow) 00246 shader_id &= ~SHADER_CAST_SHADOW; 00247 00248 if(light->type == LIGHT_POINT) { 00249 shader_id &= ~SHADER_AREA_LIGHT; 00250 00251 light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); 00252 light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, 0.0f, 0.0f); 00253 light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); 00254 light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); 00255 } 00256 else if(light->type == LIGHT_DISTANT) { 00257 shader_id &= ~SHADER_AREA_LIGHT; 00258 00259 light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z); 00260 light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, 0.0f, 0.0f); 00261 light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); 00262 light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); 00263 } 00264 else if(light->type == LIGHT_AREA) { 00265 float3 axisu = light->axisu*(light->sizeu*light->size); 00266 float3 axisv = light->axisv*(light->sizev*light->size); 00267 00268 light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); 00269 light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z); 00270 light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, axisv.x, axisv.y, axisv.z); 00271 light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, dir.x, dir.y, dir.z); 00272 } 00273 } 00274 00275 device->tex_alloc("__light_data", dscene->light_data); 00276 } 00277 00278 void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) 00279 { 00280 if(!need_update) 00281 return; 00282 00283 device_free(device, dscene); 00284 00285 device_update_points(device, dscene, scene); 00286 if(progress.get_cancel()) return; 00287 00288 device_update_distribution(device, dscene, scene, progress); 00289 if(progress.get_cancel()) return; 00290 00291 need_update = false; 00292 } 00293 00294 void LightManager::device_free(Device *device, DeviceScene *dscene) 00295 { 00296 device->tex_free(dscene->light_distribution); 00297 device->tex_free(dscene->light_data); 00298 00299 dscene->light_distribution.clear(); 00300 dscene->light_data.clear(); 00301 } 00302 00303 void LightManager::tag_update(Scene *scene) 00304 { 00305 need_update = true; 00306 } 00307 00308 CCL_NAMESPACE_END 00309