Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 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 * The Original Code is Copyright (C) 2005 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include "node_shader_util.h" 00034 00035 /* **************** MATERIAL ******************** */ 00036 00037 static bNodeSocketTemplate sh_node_material_in[]= { 00038 { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f}, 00039 { SOCK_RGBA, 1, "Spec", 0.0f, 0.0f, 0.0f, 1.0f}, 00040 { SOCK_FLOAT, 1, "Refl", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, 00041 { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, 00042 { -1, 0, "" } 00043 }; 00044 00045 static bNodeSocketTemplate sh_node_material_out[]= { 00046 { SOCK_RGBA, 0, "Color"}, 00047 { SOCK_FLOAT, 0, "Alpha"}, 00048 { SOCK_VECTOR, 0, "Normal"}, 00049 { -1, 0, "" } 00050 }; 00051 00052 /* **************** EXTENDED MATERIAL ******************** */ 00053 00054 static bNodeSocketTemplate sh_node_material_ext_in[]= { 00055 { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f}, 00056 { SOCK_RGBA, 1, "Spec", 0.0f, 0.0f, 0.0f, 1.0f}, 00057 { SOCK_FLOAT, 1, "Refl", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, 00058 { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, 00059 { SOCK_RGBA, 1, "Mirror", 0.0f, 0.0f, 0.0f, 1.0f}, 00060 { SOCK_FLOAT, 1, "Ambient", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, 00061 { SOCK_FLOAT, 1, "Emit", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, 00062 { SOCK_FLOAT, 1, "SpecTra", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, 00063 { SOCK_FLOAT, 1, "Ray Mirror", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, 00064 { SOCK_FLOAT, 1, "Alpha", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, 00065 { SOCK_FLOAT, 1, "Translucency", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, 00066 { -1, 0, "" } 00067 }; 00068 00069 static bNodeSocketTemplate sh_node_material_ext_out[]= { 00070 { SOCK_RGBA, 0, "Color"}, 00071 { SOCK_FLOAT, 0, "Alpha"}, 00072 { SOCK_VECTOR, 0, "Normal"}, 00073 { SOCK_RGBA, 0, "Diffuse"}, 00074 { SOCK_RGBA, 0, "Spec"}, 00075 { SOCK_RGBA, 0, "AO"}, 00076 { -1, 0, "" } 00077 }; 00078 00079 static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, bNodeStack **out) 00080 { 00081 if(data && node->id) { 00082 ShadeResult shrnode; 00083 ShadeInput *shi; 00084 ShaderCallData *shcd= data; 00085 float col[4]; 00086 bNodeSocket *sock; 00087 char hasinput[NUM_MAT_IN]= {'\0'}; 00088 int i; 00089 00090 /* note: cannot use the in[]->hasinput flags directly, as these are not necessarily 00091 * the constant input stack values (e.g. in case material node is inside a group). 00092 * we just want to know if a node input uses external data or the material setting. 00093 * this is an ugly hack, but so is this node as a whole. 00094 */ 00095 for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) 00096 hasinput[i] = (sock->link != NULL); 00097 00098 shi= shcd->shi; 00099 shi->mat= (Material *)node->id; 00100 00101 /* copy all relevant material vars, note, keep this synced with render_types.h */ 00102 memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); 00103 shi->har= shi->mat->har; 00104 00105 /* write values */ 00106 if(hasinput[MAT_IN_COLOR]) 00107 nodestack_get_vec(&shi->r, SOCK_VECTOR, in[MAT_IN_COLOR]); 00108 00109 if(hasinput[MAT_IN_SPEC]) 00110 nodestack_get_vec(&shi->specr, SOCK_VECTOR, in[MAT_IN_SPEC]); 00111 00112 if(hasinput[MAT_IN_REFL]) 00113 nodestack_get_vec(&shi->refl, SOCK_FLOAT, in[MAT_IN_REFL]); 00114 00115 /* retrieve normal */ 00116 if(hasinput[MAT_IN_NORMAL]) { 00117 nodestack_get_vec(shi->vn, SOCK_VECTOR, in[MAT_IN_NORMAL]); 00118 normalize_v3(shi->vn); 00119 } 00120 else 00121 copy_v3_v3(shi->vn, shi->vno); 00122 00123 /* custom option to flip normal */ 00124 if(node->custom1 & SH_NODE_MAT_NEG) { 00125 negate_v3(shi->vn); 00126 } 00127 00128 if (node->type == SH_NODE_MATERIAL_EXT) { 00129 if(hasinput[MAT_IN_MIR]) 00130 nodestack_get_vec(&shi->mirr, SOCK_VECTOR, in[MAT_IN_MIR]); 00131 if(hasinput[MAT_IN_AMB]) 00132 nodestack_get_vec(&shi->amb, SOCK_FLOAT, in[MAT_IN_AMB]); 00133 if(hasinput[MAT_IN_EMIT]) 00134 nodestack_get_vec(&shi->emit, SOCK_FLOAT, in[MAT_IN_EMIT]); 00135 if(hasinput[MAT_IN_SPECTRA]) 00136 nodestack_get_vec(&shi->spectra, SOCK_FLOAT, in[MAT_IN_SPECTRA]); 00137 if(hasinput[MAT_IN_RAY_MIRROR]) 00138 nodestack_get_vec(&shi->ray_mirror, SOCK_FLOAT, in[MAT_IN_RAY_MIRROR]); 00139 if(hasinput[MAT_IN_ALPHA]) 00140 nodestack_get_vec(&shi->alpha, SOCK_FLOAT, in[MAT_IN_ALPHA]); 00141 if(hasinput[MAT_IN_TRANSLUCENCY]) 00142 nodestack_get_vec(&shi->translucency, SOCK_FLOAT, in[MAT_IN_TRANSLUCENCY]); 00143 } 00144 00145 shi->nodes= 1; /* temp hack to prevent trashadow recursion */ 00146 node_shader_lamp_loop(shi, &shrnode); /* clears shrnode */ 00147 shi->nodes= 0; 00148 00149 /* write to outputs */ 00150 if(node->custom1 & SH_NODE_MAT_DIFF) { 00151 copy_v3_v3(col, shrnode.combined); 00152 if(!(node->custom1 & SH_NODE_MAT_SPEC)) { 00153 sub_v3_v3(col, shrnode.spec); 00154 } 00155 } 00156 else if(node->custom1 & SH_NODE_MAT_SPEC) { 00157 copy_v3_v3(col, shrnode.spec); 00158 } 00159 else 00160 col[0]= col[1]= col[2]= 0.0f; 00161 00162 col[3]= shrnode.alpha; 00163 00164 if(shi->do_preview) 00165 nodeAddToPreview(node, col, shi->xs, shi->ys, shi->do_manage); 00166 00167 copy_v3_v3(out[MAT_OUT_COLOR]->vec, col); 00168 out[MAT_OUT_ALPHA]->vec[0]= shrnode.alpha; 00169 00170 if(node->custom1 & SH_NODE_MAT_NEG) { 00171 shi->vn[0]= -shi->vn[0]; 00172 shi->vn[1]= -shi->vn[1]; 00173 shi->vn[2]= -shi->vn[2]; 00174 } 00175 00176 copy_v3_v3(out[MAT_OUT_NORMAL]->vec, shi->vn); 00177 00178 /* Extended material options */ 00179 if (node->type == SH_NODE_MATERIAL_EXT) { 00180 /* Shadow, Reflect, Refract, Radiosity, Speed seem to cause problems inside 00181 * a node tree :( */ 00182 copy_v3_v3(out[MAT_OUT_DIFFUSE]->vec, shrnode.diff); 00183 copy_v3_v3(out[MAT_OUT_SPEC]->vec, shrnode.spec); 00184 copy_v3_v3(out[MAT_OUT_AO]->vec, shrnode.ao); 00185 } 00186 00187 /* copy passes, now just active node */ 00188 if(node->flag & NODE_ACTIVE_ID) { 00189 float combined[4], alpha; 00190 00191 copy_v4_v4(combined, shcd->shr->combined); 00192 alpha= shcd->shr->alpha; 00193 00194 *(shcd->shr)= shrnode; 00195 00196 copy_v4_v4(shcd->shr->combined, combined); 00197 shcd->shr->alpha= alpha; 00198 } 00199 } 00200 } 00201 00202 00203 static void node_shader_init_material(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) 00204 { 00205 node->custom1= SH_NODE_MAT_DIFF|SH_NODE_MAT_SPEC; 00206 } 00207 00208 /* XXX this is also done as a local static function in gpu_codegen.c, 00209 * but we need this to hack around the crappy material node. 00210 */ 00211 static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) 00212 { 00213 if (in->link) 00214 return in->link; 00215 else 00216 return GPU_uniform(in->vec); 00217 } 00218 00219 static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) 00220 { 00221 if(node->id) { 00222 GPUShadeInput shi; 00223 GPUShadeResult shr; 00224 bNodeSocket *sock; 00225 char hasinput[NUM_MAT_IN]= {'\0'}; 00226 int i; 00227 00228 /* note: cannot use the in[]->hasinput flags directly, as these are not necessarily 00229 * the constant input stack values (e.g. in case material node is inside a group). 00230 * we just want to know if a node input uses external data or the material setting. 00231 */ 00232 for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) 00233 hasinput[i] = (sock->link != NULL); 00234 00235 GPU_shadeinput_set(mat, (Material*)node->id, &shi); 00236 00237 /* write values */ 00238 if(hasinput[MAT_IN_COLOR]) 00239 shi.rgb = gpu_get_input_link(&in[MAT_IN_COLOR]); 00240 00241 if(hasinput[MAT_IN_SPEC]) 00242 shi.specrgb = gpu_get_input_link(&in[MAT_IN_SPEC]); 00243 00244 if(hasinput[MAT_IN_REFL]) 00245 shi.refl = gpu_get_input_link(&in[MAT_IN_REFL]); 00246 00247 /* retrieve normal */ 00248 if(hasinput[MAT_IN_NORMAL]) { 00249 GPUNodeLink *tmp; 00250 shi.vn = gpu_get_input_link(&in[MAT_IN_NORMAL]); 00251 GPU_link(mat, "vec_math_normalize", shi.vn, &shi.vn, &tmp); 00252 } 00253 00254 /* custom option to flip normal */ 00255 if(node->custom1 & SH_NODE_MAT_NEG) 00256 GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); 00257 00258 if (node->type == SH_NODE_MATERIAL_EXT) { 00259 if(hasinput[MAT_IN_AMB]) 00260 shi.amb= gpu_get_input_link(&in[MAT_IN_AMB]); 00261 if(hasinput[MAT_IN_EMIT]) 00262 shi.emit= gpu_get_input_link(&in[MAT_IN_EMIT]); 00263 if(hasinput[MAT_IN_ALPHA]) 00264 shi.alpha= gpu_get_input_link(&in[MAT_IN_ALPHA]); 00265 } 00266 00267 GPU_shaderesult_set(&shi, &shr); /* clears shr */ 00268 00269 /* write to outputs */ 00270 if(node->custom1 & SH_NODE_MAT_DIFF) { 00271 out[MAT_OUT_COLOR].link= shr.combined; 00272 00273 if(!(node->custom1 & SH_NODE_MAT_SPEC)) { 00274 GPUNodeLink *link; 00275 GPU_link(mat, "vec_math_sub", shr.combined, shr.spec, &out[MAT_OUT_COLOR].link, &link); 00276 } 00277 } 00278 else if(node->custom1 & SH_NODE_MAT_SPEC) { 00279 out[MAT_OUT_COLOR].link= shr.spec; 00280 } 00281 else 00282 GPU_link(mat, "set_rgb_zero", &out[MAT_OUT_COLOR].link); 00283 00284 GPU_link(mat, "mtex_alpha_to_col", out[MAT_OUT_COLOR].link, shr.alpha, &out[MAT_OUT_COLOR].link); 00285 00286 out[MAT_OUT_ALPHA].link = shr.alpha; // 00287 00288 if(node->custom1 & SH_NODE_MAT_NEG) 00289 GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); 00290 out[MAT_OUT_NORMAL].link = shi.vn; 00291 00292 if (node->type == SH_NODE_MATERIAL_EXT) { 00293 out[MAT_OUT_DIFFUSE].link = shr.diff; 00294 out[MAT_OUT_SPEC].link = shr.spec; 00295 } 00296 00297 return 1; 00298 } 00299 00300 return 0; 00301 } 00302 00303 void register_node_type_sh_material(bNodeTreeType *ttype) 00304 { 00305 static bNodeType ntype; 00306 00307 node_type_base(ttype, &ntype, SH_NODE_MATERIAL, "Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); 00308 node_type_compatibility(&ntype, NODE_OLD_SHADING); 00309 node_type_socket_templates(&ntype, sh_node_material_in, sh_node_material_out); 00310 node_type_size(&ntype, 120, 80, 240); 00311 node_type_init(&ntype, node_shader_init_material); 00312 node_type_exec(&ntype, node_shader_exec_material); 00313 node_type_gpu(&ntype, gpu_shader_material); 00314 00315 nodeRegisterType(ttype, &ntype); 00316 } 00317 00318 00319 void register_node_type_sh_material_ext(bNodeTreeType *ttype) 00320 { 00321 static bNodeType ntype; 00322 00323 node_type_base(ttype, &ntype, SH_NODE_MATERIAL_EXT, "Extended Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); 00324 node_type_compatibility(&ntype, NODE_OLD_SHADING); 00325 node_type_socket_templates(&ntype, sh_node_material_ext_in, sh_node_material_ext_out); 00326 node_type_size(&ntype, 120, 80, 240); 00327 node_type_init(&ntype, node_shader_init_material); 00328 node_type_exec(&ntype, node_shader_exec_material); 00329 node_type_gpu(&ntype, gpu_shader_material); 00330 00331 nodeRegisterType(ttype, &ntype); 00332 }