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 "attribute.h" 00020 #include "graph.h" 00021 #include "nodes.h" 00022 00023 #include "util_algorithm.h" 00024 #include "util_debug.h" 00025 #include "util_foreach.h" 00026 00027 CCL_NAMESPACE_BEGIN 00028 00029 /* Input and Output */ 00030 00031 ShaderInput::ShaderInput(ShaderNode *parent_, const char *name_, ShaderSocketType type_) 00032 { 00033 parent = parent_; 00034 name = name_; 00035 type = type_; 00036 link = NULL; 00037 value = make_float3(0, 0, 0); 00038 stack_offset = SVM_STACK_INVALID; 00039 default_value = NONE; 00040 osl_only = false; 00041 } 00042 00043 ShaderOutput::ShaderOutput(ShaderNode *parent_, const char *name_, ShaderSocketType type_) 00044 { 00045 parent = parent_; 00046 name = name_; 00047 type = type_; 00048 stack_offset = SVM_STACK_INVALID; 00049 } 00050 00051 /* Node */ 00052 00053 ShaderNode::ShaderNode(const char *name_) 00054 { 00055 name = name_; 00056 id = -1; 00057 bump = SHADER_BUMP_NONE; 00058 } 00059 00060 ShaderNode::~ShaderNode() 00061 { 00062 foreach(ShaderInput *socket, inputs) 00063 delete socket; 00064 00065 foreach(ShaderOutput *socket, outputs) 00066 delete socket; 00067 } 00068 00069 ShaderInput *ShaderNode::input(const char *name) 00070 { 00071 foreach(ShaderInput *socket, inputs) 00072 if(strcmp(socket->name, name) == 0) 00073 return socket; 00074 00075 return NULL; 00076 } 00077 00078 ShaderOutput *ShaderNode::output(const char *name) 00079 { 00080 foreach(ShaderOutput *socket, outputs) 00081 if(strcmp(socket->name, name) == 0) 00082 return socket; 00083 00084 return NULL; 00085 } 00086 00087 ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value) 00088 { 00089 ShaderInput *input = new ShaderInput(this, name, type); 00090 input->value.x = value; 00091 inputs.push_back(input); 00092 return input; 00093 } 00094 00095 ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value) 00096 { 00097 ShaderInput *input = new ShaderInput(this, name, type); 00098 input->value = value; 00099 inputs.push_back(input); 00100 return input; 00101 } 00102 00103 ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, bool osl_only) 00104 { 00105 ShaderInput *input = add_input(name, type); 00106 input->default_value = value; 00107 input->osl_only = osl_only; 00108 return input; 00109 } 00110 00111 ShaderOutput *ShaderNode::add_output(const char *name, ShaderSocketType type) 00112 { 00113 ShaderOutput *output = new ShaderOutput(this, name, type); 00114 outputs.push_back(output); 00115 return output; 00116 } 00117 00118 void ShaderNode::attributes(AttributeRequestSet *attributes) 00119 { 00120 foreach(ShaderInput *input, inputs) { 00121 if(!input->link) { 00122 if(input->default_value == ShaderInput::TEXTURE_GENERATED) 00123 attributes->add(Attribute::STD_GENERATED); 00124 else if(input->default_value == ShaderInput::TEXTURE_UV) 00125 attributes->add(Attribute::STD_UV); 00126 } 00127 } 00128 } 00129 00130 /* Graph */ 00131 00132 ShaderGraph::ShaderGraph() 00133 { 00134 finalized = false; 00135 add(new OutputNode()); 00136 } 00137 00138 ShaderGraph::~ShaderGraph() 00139 { 00140 foreach(ShaderNode *node, nodes) 00141 delete node; 00142 } 00143 00144 ShaderNode *ShaderGraph::add(ShaderNode *node) 00145 { 00146 assert(!finalized); 00147 node->id = nodes.size(); 00148 nodes.push_back(node); 00149 return node; 00150 } 00151 00152 ShaderNode *ShaderGraph::output() 00153 { 00154 return nodes.front(); 00155 } 00156 00157 ShaderGraph *ShaderGraph::copy() 00158 { 00159 ShaderGraph *newgraph = new ShaderGraph(); 00160 00161 /* copy nodes */ 00162 set<ShaderNode*> nodes_all; 00163 foreach(ShaderNode *node, nodes) 00164 nodes_all.insert(node); 00165 00166 map<ShaderNode*, ShaderNode*> nodes_copy; 00167 copy_nodes(nodes_all, nodes_copy); 00168 00169 /* add nodes (in same order, so output is still first) */ 00170 newgraph->nodes.clear(); 00171 foreach(ShaderNode *node, nodes) 00172 newgraph->add(nodes_copy[node]); 00173 00174 return newgraph; 00175 } 00176 00177 void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to) 00178 { 00179 assert(!finalized); 00180 assert(from && to); 00181 00182 if(to->link) { 00183 fprintf(stderr, "ShaderGraph connect: input already connected.\n"); 00184 return; 00185 } 00186 00187 if(from->type != to->type) { 00188 /* for closures we can't do automatic conversion */ 00189 if(from->type == SHADER_SOCKET_CLOSURE || to->type == SHADER_SOCKET_CLOSURE) { 00190 fprintf(stderr, "ShaderGraph connect: can only connect closure to closure.\n"); 00191 return; 00192 } 00193 00194 /* add automatic conversion node in case of type mismatch */ 00195 ShaderNode *convert = add(new ConvertNode(from->type, to->type)); 00196 00197 connect(from, convert->inputs[0]); 00198 connect(convert->outputs[0], to); 00199 } 00200 else { 00201 /* types match, just connect */ 00202 to->link = from; 00203 from->links.push_back(to); 00204 } 00205 } 00206 00207 void ShaderGraph::disconnect(ShaderInput *to) 00208 { 00209 assert(!finalized); 00210 assert(to->link); 00211 00212 ShaderOutput *from = to->link; 00213 00214 to->link = NULL; 00215 from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end()); 00216 } 00217 00218 void ShaderGraph::finalize(bool do_bump, bool do_osl) 00219 { 00220 /* before compiling, the shader graph may undergo a number of modifications. 00221 * currently we set default geometry shader inputs, and create automatic bump 00222 * from displacement. a graph can be finalized only once, and should not be 00223 * modified afterwards. */ 00224 00225 if(!finalized) { 00226 clean(); 00227 default_inputs(do_osl); 00228 if(do_bump) 00229 bump_from_displacement(); 00230 00231 finalized = true; 00232 } 00233 } 00234 00235 void ShaderGraph::find_dependencies(set<ShaderNode*>& dependencies, ShaderInput *input) 00236 { 00237 /* find all nodes that this input dependes on directly and indirectly */ 00238 ShaderNode *node = (input->link)? input->link->parent: NULL; 00239 00240 if(node) { 00241 foreach(ShaderInput *in, node->inputs) 00242 find_dependencies(dependencies, in); 00243 00244 dependencies.insert(node); 00245 } 00246 } 00247 00248 void ShaderGraph::copy_nodes(set<ShaderNode*>& nodes, map<ShaderNode*, ShaderNode*>& nnodemap) 00249 { 00250 /* copy a set of nodes, and the links between them. the assumption is 00251 * made that all nodes that inputs are linked to are in the set too. */ 00252 00253 /* copy nodes */ 00254 foreach(ShaderNode *node, nodes) { 00255 ShaderNode *nnode = node->clone(); 00256 nnodemap[node] = nnode; 00257 00258 nnode->inputs.clear(); 00259 nnode->outputs.clear(); 00260 00261 foreach(ShaderInput *input, node->inputs) { 00262 ShaderInput *ninput = new ShaderInput(*input); 00263 nnode->inputs.push_back(ninput); 00264 00265 ninput->parent = nnode; 00266 ninput->link = NULL; 00267 } 00268 00269 foreach(ShaderOutput *output, node->outputs) { 00270 ShaderOutput *noutput = new ShaderOutput(*output); 00271 nnode->outputs.push_back(noutput); 00272 00273 noutput->parent = nnode; 00274 noutput->links.clear(); 00275 } 00276 } 00277 00278 /* recreate links */ 00279 foreach(ShaderNode *node, nodes) { 00280 foreach(ShaderInput *input, node->inputs) { 00281 if(input->link) { 00282 /* find new input and output */ 00283 ShaderNode *nfrom = nnodemap[input->link->parent]; 00284 ShaderNode *nto = nnodemap[input->parent]; 00285 ShaderOutput *noutput = nfrom->output(input->link->name); 00286 ShaderInput *ninput = nto->input(input->name); 00287 00288 /* connect */ 00289 connect(noutput, ninput); 00290 } 00291 } 00292 } 00293 } 00294 00295 void ShaderGraph::remove_proxy_nodes(vector<bool>& removed) 00296 { 00297 foreach(ShaderNode *node, nodes) { 00298 ProxyNode *proxy = dynamic_cast<ProxyNode*>(node); 00299 if (proxy) { 00300 ShaderInput *input = proxy->inputs[0]; 00301 ShaderOutput *output = proxy->outputs[0]; 00302 00303 /* temp. copy of the output links list. 00304 * output->links is modified when we disconnect! 00305 */ 00306 vector<ShaderInput*> links(output->links); 00307 ShaderOutput *from = input->link; 00308 00309 /* bypass the proxy node */ 00310 if (from) { 00311 disconnect(input); 00312 foreach(ShaderInput *to, links) { 00313 disconnect(to); 00314 connect(from, to); 00315 } 00316 } 00317 else { 00318 foreach(ShaderInput *to, links) { 00319 disconnect(to); 00320 00321 /* transfer the default input value to the target socket */ 00322 to->set(input->value); 00323 } 00324 } 00325 00326 removed[proxy->id] = true; 00327 } 00328 } 00329 } 00330 00331 void ShaderGraph::break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack) 00332 { 00333 visited[node->id] = true; 00334 on_stack[node->id] = true; 00335 00336 foreach(ShaderInput *input, node->inputs) { 00337 if(input->link) { 00338 ShaderNode *depnode = input->link->parent; 00339 00340 if(on_stack[depnode->id]) { 00341 /* break cycle */ 00342 disconnect(input); 00343 fprintf(stderr, "ShaderGraph: detected cycle in graph, connection removed.\n"); 00344 } 00345 else if(!visited[depnode->id]) { 00346 /* visit dependencies */ 00347 break_cycles(depnode, visited, on_stack); 00348 } 00349 } 00350 } 00351 00352 on_stack[node->id] = false; 00353 } 00354 00355 void ShaderGraph::clean() 00356 { 00357 /* we do two things here: find cycles and break them, and remove unused 00358 nodes that don't feed into the output. how cycles are broken is 00359 undefined, they are invalid input, the important thing is to not crash */ 00360 00361 vector<bool> removed(nodes.size(), false); 00362 vector<bool> visited(nodes.size(), false); 00363 vector<bool> on_stack(nodes.size(), false); 00364 00365 list<ShaderNode*> newnodes; 00366 00367 /* remove proxy nodes */ 00368 remove_proxy_nodes(removed); 00369 00370 foreach(ShaderNode *node, nodes) { 00371 if(!removed[node->id]) 00372 newnodes.push_back(node); 00373 else 00374 delete node; 00375 } 00376 nodes = newnodes; 00377 newnodes.clear(); 00378 00379 /* break cycles */ 00380 break_cycles(output(), visited, on_stack); 00381 00382 /* remove unused nodes */ 00383 foreach(ShaderNode *node, nodes) { 00384 if(visited[node->id]) 00385 newnodes.push_back(node); 00386 else 00387 delete node; 00388 } 00389 00390 nodes = newnodes; 00391 } 00392 00393 void ShaderGraph::default_inputs(bool do_osl) 00394 { 00395 /* nodes can specify default texture coordinates, for now we give 00396 * everything the position by default, except for the sky texture */ 00397 00398 ShaderNode *geom = NULL; 00399 ShaderNode *texco = NULL; 00400 00401 foreach(ShaderNode *node, nodes) { 00402 foreach(ShaderInput *input, node->inputs) { 00403 if(!input->link && !(input->osl_only && !do_osl)) { 00404 if(input->default_value == ShaderInput::TEXTURE_GENERATED) { 00405 if(!texco) 00406 texco = new TextureCoordinateNode(); 00407 00408 connect(texco->output("Generated"), input); 00409 } 00410 else if(input->default_value == ShaderInput::TEXTURE_UV) { 00411 if(!texco) 00412 texco = new TextureCoordinateNode(); 00413 00414 connect(texco->output("UV"), input); 00415 } 00416 else if(input->default_value == ShaderInput::INCOMING) { 00417 if(!geom) 00418 geom = new GeometryNode(); 00419 00420 connect(geom->output("Incoming"), input); 00421 } 00422 else if(input->default_value == ShaderInput::NORMAL) { 00423 if(!geom) 00424 geom = new GeometryNode(); 00425 00426 connect(geom->output("Normal"), input); 00427 } 00428 else if(input->default_value == ShaderInput::POSITION) { 00429 if(!geom) 00430 geom = new GeometryNode(); 00431 00432 connect(geom->output("Position"), input); 00433 } 00434 } 00435 } 00436 } 00437 00438 if(geom) 00439 add(geom); 00440 if(texco) 00441 add(texco); 00442 } 00443 00444 void ShaderGraph::bump_from_displacement() 00445 { 00446 /* generate bump mapping automatically from displacement. bump mapping is 00447 * done using a 3-tap filter, computing the displacement at the center, 00448 * and two other positions shifted by ray differentials. 00449 * 00450 * since the input to displacement is a node graph, we need to ensure that 00451 * all texture coordinates use are shift by the ray differentials. for this 00452 * reason we make 3 copies of the node subgraph defining the displacement, 00453 * with each different geometry and texture coordinate nodes that generate 00454 * different shifted coordinates. 00455 * 00456 * these 3 displacement values are then fed into the bump node, which will 00457 * modify the normal. */ 00458 00459 ShaderInput *displacement_in = output()->input("Displacement"); 00460 00461 if(!displacement_in->link) 00462 return; 00463 00464 /* find dependencies for the given input */ 00465 set<ShaderNode*> nodes_displace; 00466 find_dependencies(nodes_displace, displacement_in); 00467 00468 /* copy nodes for 3 bump samples */ 00469 map<ShaderNode*, ShaderNode*> nodes_center; 00470 map<ShaderNode*, ShaderNode*> nodes_dx; 00471 map<ShaderNode*, ShaderNode*> nodes_dy; 00472 00473 copy_nodes(nodes_displace, nodes_center); 00474 copy_nodes(nodes_displace, nodes_dx); 00475 copy_nodes(nodes_displace, nodes_dy); 00476 00477 /* mark nodes to indicate they are use for bump computation, so 00478 that any texture coordinates are shifted by dx/dy when sampling */ 00479 foreach(NodePair& pair, nodes_center) 00480 pair.second->bump = SHADER_BUMP_CENTER; 00481 foreach(NodePair& pair, nodes_dx) 00482 pair.second->bump = SHADER_BUMP_DX; 00483 foreach(NodePair& pair, nodes_dy) 00484 pair.second->bump = SHADER_BUMP_DY; 00485 00486 /* add bump node and connect copied graphs to it */ 00487 ShaderNode *bump = add(new BumpNode()); 00488 00489 ShaderOutput *out = displacement_in->link; 00490 ShaderOutput *out_center = nodes_center[out->parent]->output(out->name); 00491 ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name); 00492 ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name); 00493 00494 connect(out_center, bump->input("SampleCenter")); 00495 connect(out_dx, bump->input("SampleX")); 00496 connect(out_dy, bump->input("SampleY")); 00497 00498 /* connect bump output to normal input nodes that aren't set yet. actually 00499 this will only set the normal input to the geometry node that we created 00500 and connected to all other normal inputs already. */ 00501 foreach(ShaderNode *node, nodes) 00502 foreach(ShaderInput *input, node->inputs) 00503 if(!input->link && input->default_value == ShaderInput::NORMAL) 00504 connect(bump->output("Normal"), input); 00505 00506 /* finally, add the copied nodes to the graph. we can't do this earlier 00507 because we would create dependency cycles in the above loop */ 00508 foreach(NodePair& pair, nodes_center) 00509 add(pair.second); 00510 foreach(NodePair& pair, nodes_dx) 00511 add(pair.second); 00512 foreach(NodePair& pair, nodes_dy) 00513 add(pair.second); 00514 } 00515 00516 CCL_NAMESPACE_END 00517