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 00021 #include "graph.h" 00022 #include "light.h" 00023 #include "osl.h" 00024 #include "scene.h" 00025 #include "shader.h" 00026 00027 #ifdef WITH_OSL 00028 00029 #include "osl_globals.h" 00030 #include "osl_services.h" 00031 #include "osl_shader.h" 00032 00033 #include "util_foreach.h" 00034 #include "util_path.h" 00035 #include "util_progress.h" 00036 00037 #endif 00038 00039 CCL_NAMESPACE_BEGIN 00040 00041 #ifdef WITH_OSL 00042 00043 /* Shader Manager */ 00044 00045 OSLShaderManager::OSLShaderManager() 00046 { 00047 services = new OSLRenderServices(); 00048 00049 /* if we let OSL create it, it leaks */ 00050 ts = TextureSystem::create(true); 00051 ts->attribute("automip", 1); 00052 ts->attribute("autotile", 64); 00053 00054 ss = OSL::ShadingSystem::create(services, ts, &errhandler); 00055 ss->attribute("lockgeom", 1); 00056 ss->attribute("commonspace", "world"); 00057 ss->attribute("optimize", 2); 00058 //ss->attribute("debug", 1); 00059 //ss->attribute("statistics:level", 1); 00060 ss->attribute("searchpath:shader", path_get("shader").c_str()); 00061 00062 OSLShader::register_closures(ss); 00063 } 00064 00065 OSLShaderManager::~OSLShaderManager() 00066 { 00067 OSL::ShadingSystem::destroy(ss); 00068 OSL::TextureSystem::destroy(ts); 00069 delete services; 00070 } 00071 00072 void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) 00073 { 00074 /* test if we need to update */ 00075 bool need_update = false; 00076 00077 foreach(Shader *shader, scene->shaders) 00078 if(shader->need_update) 00079 need_update = true; 00080 00081 if(!need_update) 00082 return; 00083 00084 device_free(device, dscene); 00085 00086 /* create shaders */ 00087 OSLGlobals *og = (OSLGlobals*)device->osl_memory(); 00088 00089 foreach(Shader *shader, scene->shaders) { 00090 assert(shader->graph); 00091 00092 if(progress.get_cancel()) return; 00093 00094 if(shader->sample_as_light && shader->has_surface_emission) 00095 scene->light_manager->need_update = true; 00096 00097 OSLCompiler compiler((void*)ss); 00098 compiler.background = (shader == scene->shaders[scene->default_background]); 00099 compiler.compile(og, shader); 00100 } 00101 00102 /* setup shader engine */ 00103 og->ss = ss; 00104 int background_id = scene->shader_manager->get_shader_id(scene->default_background); 00105 og->background_state = og->surface_state[background_id]; 00106 og->use = true; 00107 00108 tls_create(OSLGlobals::ThreadData, og->thread_data); 00109 00110 foreach(Shader *shader, scene->shaders) 00111 shader->need_update = false; 00112 00113 /* set texture system */ 00114 scene->image_manager->set_osl_texture_system((void*)ts); 00115 00116 device_update_common(device, dscene, scene, progress); 00117 } 00118 00119 void OSLShaderManager::device_free(Device *device, DeviceScene *dscene) 00120 { 00121 OSLGlobals *og = (OSLGlobals*)device->osl_memory(); 00122 00123 device_free_common(device, dscene); 00124 00125 /* clear shader engine */ 00126 og->use = false; 00127 og->ss = NULL; 00128 00129 tls_delete(OSLGlobals::ThreadData, og->thread_data); 00130 00131 og->surface_state.clear(); 00132 og->volume_state.clear(); 00133 og->displacement_state.clear(); 00134 og->background_state.reset(); 00135 } 00136 00137 /* Graph Compiler */ 00138 00139 OSLCompiler::OSLCompiler(void *shadingsys_) 00140 { 00141 shadingsys = shadingsys_; 00142 current_type = SHADER_TYPE_SURFACE; 00143 current_shader = NULL; 00144 background = false; 00145 } 00146 00147 string OSLCompiler::id(ShaderNode *node) 00148 { 00149 /* assign layer unique name based on pointer address + bump mode */ 00150 stringstream stream; 00151 stream << "node_" << node->name << "_" << node; 00152 00153 return stream.str(); 00154 } 00155 00156 string OSLCompiler::compatible_name(const char *name) 00157 { 00158 string sname = name; 00159 size_t i; 00160 00161 while((i = sname.find(" ")) != string::npos) 00162 sname.replace(i, 1, ""); 00163 00164 return sname; 00165 } 00166 00167 bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input) 00168 { 00169 /* exception for output node, only one input is actually used 00170 depending on the current shader type */ 00171 00172 if(node->name == ustring("output")) { 00173 if(strcmp(input->name, "Surface") == 0 && current_type != SHADER_TYPE_SURFACE) 00174 return true; 00175 if(strcmp(input->name, "Volume") == 0 && current_type != SHADER_TYPE_VOLUME) 00176 return true; 00177 if(strcmp(input->name, "Displacement") == 0 && current_type != SHADER_TYPE_DISPLACEMENT) 00178 return true; 00179 } 00180 else if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->name == ustring("bump")) 00181 return true; 00182 00183 return false; 00184 } 00185 00186 void OSLCompiler::add(ShaderNode *node, const char *name) 00187 { 00188 OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; 00189 00190 /* pass in fixed parameter values */ 00191 foreach(ShaderInput *input, node->inputs) { 00192 if(!input->link) { 00193 /* checks to untangle graphs */ 00194 if(node_skip_input(node, input)) 00195 continue; 00196 /* already has default value assigned */ 00197 else if(input->default_value != ShaderInput::NONE) 00198 continue; 00199 00200 switch(input->type) { 00201 case SHADER_SOCKET_COLOR: 00202 parameter_color(input->name, input->value); 00203 break; 00204 case SHADER_SOCKET_POINT: 00205 parameter_point(input->name, input->value); 00206 break; 00207 case SHADER_SOCKET_VECTOR: 00208 parameter_vector(input->name, input->value); 00209 break; 00210 case SHADER_SOCKET_NORMAL: 00211 parameter_normal(input->name, input->value); 00212 break; 00213 case SHADER_SOCKET_FLOAT: 00214 parameter(input->name, input->value.x); 00215 break; 00216 case SHADER_SOCKET_CLOSURE: 00217 break; 00218 } 00219 } 00220 } 00221 00222 /* create shader of the appropriate type. we pass "surface" to all shaders, 00223 * because "volume" and "displacement" don't work yet in OSL. the shaders 00224 * work fine, but presumably these values would be used for more strict 00225 * checking, so when that is fixed, we should update the code here too. */ 00226 if(current_type == SHADER_TYPE_SURFACE) 00227 ss->Shader("surface", name, id(node).c_str()); 00228 else if(current_type == SHADER_TYPE_VOLUME) 00229 ss->Shader("surface", name, id(node).c_str()); 00230 else if(current_type == SHADER_TYPE_DISPLACEMENT) 00231 ss->Shader("surface", name, id(node).c_str()); 00232 else 00233 assert(0); 00234 00235 /* link inputs to other nodes */ 00236 foreach(ShaderInput *input, node->inputs) { 00237 if(input->link) { 00238 if(node_skip_input(node, input)) 00239 continue; 00240 00241 /* connect shaders */ 00242 string id_from = id(input->link->parent); 00243 string id_to = id(node); 00244 string param_from = compatible_name(input->link->name); 00245 string param_to = compatible_name(input->name); 00246 00247 /* avoid name conflict with same input/output socket name */ 00248 if(input->link->parent->input(input->link->name)) 00249 param_from += "_"; 00250 00251 ss->ConnectShaders(id_from.c_str(), param_from.c_str(), id_to.c_str(), param_to.c_str()); 00252 } 00253 } 00254 } 00255 00256 void OSLCompiler::parameter(const char *name, float f) 00257 { 00258 OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; 00259 ss->Parameter(name, TypeDesc::TypeFloat, &f); 00260 } 00261 00262 void OSLCompiler::parameter_color(const char *name, float3 f) 00263 { 00264 OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; 00265 ss->Parameter(name, TypeDesc::TypeColor, &f); 00266 } 00267 00268 void OSLCompiler::parameter_point(const char *name, float3 f) 00269 { 00270 OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; 00271 ss->Parameter(name, TypeDesc::TypePoint, &f); 00272 } 00273 00274 void OSLCompiler::parameter_normal(const char *name, float3 f) 00275 { 00276 OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; 00277 ss->Parameter(name, TypeDesc::TypeNormal, &f); 00278 } 00279 00280 void OSLCompiler::parameter_vector(const char *name, float3 f) 00281 { 00282 OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; 00283 ss->Parameter(name, TypeDesc::TypeVector, &f); 00284 } 00285 00286 void OSLCompiler::parameter(const char *name, int f) 00287 { 00288 OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; 00289 ss->Parameter(name, TypeDesc::TypeInt, &f); 00290 } 00291 00292 void OSLCompiler::parameter(const char *name, const char *s) 00293 { 00294 OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; 00295 ss->Parameter(name, TypeDesc::TypeString, &s); 00296 } 00297 00298 void OSLCompiler::parameter(const char *name, ustring s) 00299 { 00300 OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; 00301 const char *str = s.c_str(); 00302 ss->Parameter(name, TypeDesc::TypeString, &str); 00303 } 00304 00305 void OSLCompiler::parameter(const char *name, const Transform& tfm) 00306 { 00307 OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; 00308 ss->Parameter(name, TypeDesc::TypeMatrix, (float*)&tfm); 00309 } 00310 00311 void OSLCompiler::find_dependencies(set<ShaderNode*>& dependencies, ShaderInput *input) 00312 { 00313 ShaderNode *node = (input->link)? input->link->parent: NULL; 00314 00315 if(node) { 00316 foreach(ShaderInput *in, node->inputs) 00317 if(!node_skip_input(node, in)) 00318 find_dependencies(dependencies, in); 00319 00320 dependencies.insert(node); 00321 } 00322 } 00323 00324 void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes) 00325 { 00326 set<ShaderNode*> done; 00327 bool nodes_done; 00328 00329 do { 00330 nodes_done = true; 00331 00332 foreach(ShaderNode *node, nodes) { 00333 if(done.find(node) == done.end()) { 00334 bool inputs_done = true; 00335 00336 foreach(ShaderInput *input, node->inputs) 00337 if(!node_skip_input(node, input)) 00338 if(input->link && done.find(input->link->parent) == done.end()) 00339 inputs_done = false; 00340 00341 if(inputs_done) { 00342 node->compile(*this); 00343 done.insert(node); 00344 00345 if(node->name == ustring("emission")) 00346 current_shader->has_surface_emission = true; 00347 if(node->name == ustring("transparent")) 00348 current_shader->has_surface_transparent = true; 00349 } 00350 else 00351 nodes_done = false; 00352 } 00353 } 00354 } while(!nodes_done); 00355 } 00356 00357 void OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type) 00358 { 00359 OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; 00360 00361 current_type = type; 00362 00363 ss->ShaderGroupBegin(); 00364 00365 ShaderNode *output = graph->output(); 00366 set<ShaderNode*> dependencies; 00367 00368 if(type == SHADER_TYPE_SURFACE) { 00369 /* generate surface shader */ 00370 find_dependencies(dependencies, output->input("Surface")); 00371 generate_nodes(dependencies); 00372 output->compile(*this); 00373 } 00374 else if(type == SHADER_TYPE_VOLUME) { 00375 /* generate volume shader */ 00376 find_dependencies(dependencies, output->input("Volume")); 00377 generate_nodes(dependencies); 00378 output->compile(*this); 00379 } 00380 else if(type == SHADER_TYPE_DISPLACEMENT) { 00381 /* generate displacement shader */ 00382 find_dependencies(dependencies, output->input("Displacement")); 00383 generate_nodes(dependencies); 00384 output->compile(*this); 00385 } 00386 else 00387 assert(0); 00388 00389 ss->ShaderGroupEnd(); 00390 } 00391 00392 void OSLCompiler::compile(OSLGlobals *og, Shader *shader) 00393 { 00394 OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; 00395 ShaderGraph *graph = shader->graph; 00396 ShaderNode *output = (graph)? graph->output(): NULL; 00397 00398 /* copy graph for shader with bump mapping */ 00399 if(output->input("Surface")->link && output->input("Displacement")->link) 00400 if(!shader->graph_bump) 00401 shader->graph_bump = shader->graph->copy(); 00402 00403 /* finalize */ 00404 shader->graph->finalize(false, true); 00405 if(shader->graph_bump) 00406 shader->graph_bump->finalize(true, true); 00407 00408 current_shader = shader; 00409 00410 shader->has_surface = false; 00411 shader->has_surface_emission = false; 00412 shader->has_surface_transparent = false; 00413 shader->has_volume = false; 00414 shader->has_displacement = false; 00415 00416 /* generate surface shader */ 00417 if(graph && output->input("Surface")->link) { 00418 compile_type(shader, shader->graph, SHADER_TYPE_SURFACE); 00419 og->surface_state.push_back(ss->state()); 00420 00421 if(shader->graph_bump) { 00422 ss->clear_state(); 00423 compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE); 00424 og->surface_state.push_back(ss->state()); 00425 } 00426 else 00427 og->surface_state.push_back(ss->state()); 00428 00429 ss->clear_state(); 00430 00431 shader->has_surface = true; 00432 } 00433 else { 00434 og->surface_state.push_back(OSL::ShadingAttribStateRef()); 00435 og->surface_state.push_back(OSL::ShadingAttribStateRef()); 00436 } 00437 00438 /* generate volume shader */ 00439 if(graph && output->input("Volume")->link) { 00440 compile_type(shader, shader->graph, SHADER_TYPE_VOLUME); 00441 shader->has_volume = true; 00442 00443 og->volume_state.push_back(ss->state()); 00444 og->volume_state.push_back(ss->state()); 00445 ss->clear_state(); 00446 } 00447 else { 00448 og->volume_state.push_back(OSL::ShadingAttribStateRef()); 00449 og->volume_state.push_back(OSL::ShadingAttribStateRef()); 00450 } 00451 00452 /* generate displacement shader */ 00453 if(graph && output->input("Displacement")->link) { 00454 compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT); 00455 shader->has_displacement = true; 00456 00457 og->displacement_state.push_back(ss->state()); 00458 og->displacement_state.push_back(ss->state()); 00459 ss->clear_state(); 00460 } 00461 else { 00462 og->displacement_state.push_back(OSL::ShadingAttribStateRef()); 00463 og->displacement_state.push_back(OSL::ShadingAttribStateRef()); 00464 } 00465 } 00466 00467 #else 00468 00469 void OSLCompiler::add(ShaderNode *node, const char *name) 00470 { 00471 } 00472 00473 void OSLCompiler::parameter(const char *name, float f) 00474 { 00475 } 00476 00477 void OSLCompiler::parameter_color(const char *name, float3 f) 00478 { 00479 } 00480 00481 void OSLCompiler::parameter_vector(const char *name, float3 f) 00482 { 00483 } 00484 00485 void OSLCompiler::parameter(const char *name, int f) 00486 { 00487 } 00488 00489 void OSLCompiler::parameter(const char *name, const char *s) 00490 { 00491 } 00492 00493 void OSLCompiler::parameter(const char *name, ustring s) 00494 { 00495 } 00496 00497 void OSLCompiler::parameter(const char *name, const Transform& tfm) 00498 { 00499 } 00500 00501 #endif /* WITH_OSL */ 00502 00503 CCL_NAMESPACE_END 00504