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) 2006 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): Brecht Van Lommel. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <math.h> 00034 #include <string.h> 00035 00036 #include "GL/glew.h" 00037 00038 #include "MEM_guardedalloc.h" 00039 00040 #include "DNA_lamp_types.h" 00041 #include "DNA_material_types.h" 00042 #include "DNA_object_types.h" 00043 #include "DNA_scene_types.h" 00044 #include "DNA_world_types.h" 00045 00046 #include "BLI_math.h" 00047 #include "BLI_blenlib.h" 00048 #include "BLI_utildefines.h" 00049 00050 #include "BKE_anim.h" 00051 #include "BKE_colortools.h" 00052 #include "BKE_DerivedMesh.h" 00053 #include "BKE_global.h" 00054 #include "BKE_image.h" 00055 #include "BKE_main.h" 00056 #include "BKE_node.h" 00057 #include "BKE_scene.h" 00058 #include "BKE_texture.h" 00059 00060 #include "IMB_imbuf_types.h" 00061 00062 #include "GPU_extensions.h" 00063 #include "GPU_material.h" 00064 00065 #include "gpu_codegen.h" 00066 00067 #include <string.h> 00068 00069 /* Structs */ 00070 00071 typedef enum DynMatProperty { 00072 DYN_LAMP_CO = 1, 00073 DYN_LAMP_VEC = 2, 00074 DYN_LAMP_IMAT = 4, 00075 DYN_LAMP_PERSMAT = 8, 00076 } DynMatProperty; 00077 00078 struct GPUMaterial { 00079 Scene *scene; 00080 Material *ma; 00081 00082 /* for creating the material */ 00083 ListBase nodes; 00084 GPUNodeLink *outlink; 00085 00086 /* for binding the material */ 00087 GPUPass *pass; 00088 GPUVertexAttribs attribs; 00089 int bound; 00090 int builtins; 00091 int alpha, obcolalpha; 00092 int dynproperty; 00093 00094 /* for passing uniforms */ 00095 int viewmatloc, invviewmatloc; 00096 int obmatloc, invobmatloc; 00097 int obcolloc, obautobumpscaleloc; 00098 00099 ListBase lamps; 00100 }; 00101 00102 struct GPULamp { 00103 Scene *scene; 00104 Object *ob; 00105 Object *par; 00106 Lamp *la; 00107 00108 int type, mode, lay, hide; 00109 00110 float dynenergy, dyncol[3]; 00111 float energy, col[3]; 00112 00113 float co[3], vec[3]; 00114 float dynco[3], dynvec[3]; 00115 float obmat[4][4]; 00116 float imat[4][4]; 00117 float dynimat[4][4]; 00118 00119 float spotsi, spotbl, k; 00120 float dist, att1, att2; 00121 00122 float bias, d, clipend; 00123 int size; 00124 00125 int falloff_type; 00126 struct CurveMapping *curfalloff; 00127 00128 float winmat[4][4]; 00129 float viewmat[4][4]; 00130 float persmat[4][4]; 00131 float dynpersmat[4][4]; 00132 00133 GPUFrameBuffer *fb; 00134 GPUTexture *tex; 00135 00136 ListBase materials; 00137 }; 00138 00139 /* Functions */ 00140 00141 static GPUMaterial *GPU_material_construct_begin(Material *ma) 00142 { 00143 GPUMaterial *material = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial"); 00144 00145 material->ma= ma; 00146 00147 return material; 00148 } 00149 00150 static void gpu_material_set_attrib_id(GPUMaterial *material) 00151 { 00152 GPUVertexAttribs *attribs; 00153 GPUShader *shader; 00154 GPUPass *pass; 00155 char name[32]; 00156 int a, b; 00157 00158 attribs= &material->attribs; 00159 pass= material->pass; 00160 if(!pass) { 00161 attribs->totlayer = 0; 00162 return; 00163 } 00164 00165 shader= GPU_pass_shader(pass); 00166 if(!shader) { 00167 attribs->totlayer = 0; 00168 return; 00169 } 00170 00171 /* convert from attribute number to the actual id assigned by opengl, 00172 * in case the attrib does not get a valid index back, it was probably 00173 * removed by the glsl compiler by dead code elimination */ 00174 00175 for(a=0, b=0; a<attribs->totlayer; a++) { 00176 BLI_snprintf(name, sizeof(name), "att%d", attribs->layer[a].attribid); 00177 attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name); 00178 00179 if(attribs->layer[a].glindex >= 0) { 00180 attribs->layer[b] = attribs->layer[a]; 00181 b++; 00182 } 00183 } 00184 00185 attribs->totlayer = b; 00186 } 00187 00188 static int GPU_material_construct_end(GPUMaterial *material) 00189 { 00190 if (material->outlink) { 00191 GPUNodeLink *outlink; 00192 GPUShader *shader; 00193 00194 outlink = material->outlink; 00195 material->pass = GPU_generate_pass(&material->nodes, outlink, 00196 &material->attribs, &material->builtins, material->ma->id.name); 00197 00198 if(!material->pass) 00199 return 0; 00200 00201 gpu_material_set_attrib_id(material); 00202 00203 shader = GPU_pass_shader(material->pass); 00204 00205 if(material->builtins & GPU_VIEW_MATRIX) 00206 material->viewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_VIEW_MATRIX)); 00207 if(material->builtins & GPU_INVERSE_VIEW_MATRIX) 00208 material->invviewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_VIEW_MATRIX)); 00209 if(material->builtins & GPU_OBJECT_MATRIX) 00210 material->obmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBJECT_MATRIX)); 00211 if(material->builtins & GPU_INVERSE_OBJECT_MATRIX) 00212 material->invobmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_OBJECT_MATRIX)); 00213 if(material->builtins & GPU_OBCOLOR) 00214 material->obcolloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBCOLOR)); 00215 if(material->builtins & GPU_AUTO_BUMPSCALE) 00216 material->obautobumpscaleloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_AUTO_BUMPSCALE)); 00217 return 1; 00218 } 00219 00220 return 0; 00221 } 00222 00223 void GPU_material_free(Material *ma) 00224 { 00225 LinkData *link; 00226 LinkData *nlink, *mlink, *next; 00227 00228 for(link=ma->gpumaterial.first; link; link=link->next) { 00229 GPUMaterial *material = link->data; 00230 00231 if(material->pass) 00232 GPU_pass_free(material->pass); 00233 00234 for(nlink=material->lamps.first; nlink; nlink=nlink->next) { 00235 GPULamp *lamp = nlink->data; 00236 00237 for(mlink=lamp->materials.first; mlink; mlink=next) { 00238 next = mlink->next; 00239 if(mlink->data == ma) 00240 BLI_freelinkN(&lamp->materials, mlink); 00241 } 00242 } 00243 00244 BLI_freelistN(&material->lamps); 00245 00246 MEM_freeN(material); 00247 } 00248 00249 BLI_freelistN(&ma->gpumaterial); 00250 } 00251 00252 void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap) 00253 { 00254 if(material->pass) { 00255 LinkData *nlink; 00256 GPULamp *lamp; 00257 00258 /* handle layer lamps */ 00259 for(nlink=material->lamps.first; nlink; nlink=nlink->next) { 00260 lamp= nlink->data; 00261 00262 if(!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))) { 00263 lamp->dynenergy = lamp->energy; 00264 copy_v3_v3(lamp->dyncol, lamp->col); 00265 } 00266 else { 00267 lamp->dynenergy = 0.0f; 00268 lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f; 00269 } 00270 } 00271 00272 GPU_pass_bind(material->pass, time, mipmap); 00273 material->bound = 1; 00274 } 00275 } 00276 00277 void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4], float autobumpscale) 00278 { 00279 if(material->pass) { 00280 GPUShader *shader = GPU_pass_shader(material->pass); 00281 LinkData *nlink; 00282 GPULamp *lamp; 00283 float invmat[4][4], col[4]; 00284 00285 /* handle builtins */ 00286 if(material->builtins & GPU_VIEW_MATRIX) { 00287 GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float*)viewmat); 00288 } 00289 if(material->builtins & GPU_INVERSE_VIEW_MATRIX) { 00290 GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv); 00291 } 00292 if(material->builtins & GPU_OBJECT_MATRIX) { 00293 GPU_shader_uniform_vector(shader, material->obmatloc, 16, 1, (float*)obmat); 00294 } 00295 if(material->builtins & GPU_INVERSE_OBJECT_MATRIX) { 00296 invert_m4_m4(invmat, obmat); 00297 GPU_shader_uniform_vector(shader, material->invobmatloc, 16, 1, (float*)invmat); 00298 } 00299 if(material->builtins & GPU_OBCOLOR) { 00300 copy_v4_v4(col, obcol); 00301 CLAMP(col[3], 0.0f, 1.0f); 00302 GPU_shader_uniform_vector(shader, material->obcolloc, 4, 1, col); 00303 } 00304 if(material->builtins & GPU_AUTO_BUMPSCALE) { 00305 GPU_shader_uniform_vector(shader, material->obautobumpscaleloc, 1, 1, &autobumpscale); 00306 } 00307 /* update lamps */ 00308 for(nlink=material->lamps.first; nlink; nlink=nlink->next) { 00309 lamp= nlink->data; 00310 00311 if(material->dynproperty & DYN_LAMP_VEC) { 00312 copy_v3_v3(lamp->dynvec, lamp->vec); 00313 normalize_v3(lamp->dynvec); 00314 negate_v3(lamp->dynvec); 00315 mul_mat3_m4_v3(viewmat, lamp->dynvec); 00316 } 00317 00318 if(material->dynproperty & DYN_LAMP_CO) { 00319 copy_v3_v3(lamp->dynco, lamp->co); 00320 mul_m4_v3(viewmat, lamp->dynco); 00321 } 00322 00323 if(material->dynproperty & DYN_LAMP_IMAT) 00324 mult_m4_m4m4(lamp->dynimat, lamp->imat, viewinv); 00325 if(material->dynproperty & DYN_LAMP_PERSMAT) 00326 mult_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv); 00327 } 00328 00329 GPU_pass_update_uniforms(material->pass); 00330 } 00331 } 00332 00333 void GPU_material_unbind(GPUMaterial *material) 00334 { 00335 if (material->pass) { 00336 material->bound = 0; 00337 GPU_pass_unbind(material->pass); 00338 } 00339 } 00340 00341 int GPU_material_bound(GPUMaterial *material) 00342 { 00343 return material->bound; 00344 } 00345 00346 void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs) 00347 { 00348 *attribs = material->attribs; 00349 } 00350 00351 void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link) 00352 { 00353 if(!material->outlink) 00354 material->outlink= link; 00355 } 00356 00357 void GPU_material_enable_alpha(GPUMaterial *material) 00358 { 00359 material->alpha= 1; 00360 } 00361 00362 GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]) 00363 { 00364 if(material->alpha || (material->obcolalpha && obcol[3] < 1.0f)) 00365 return GPU_BLEND_ALPHA; 00366 else 00367 return GPU_BLEND_SOLID; 00368 } 00369 00370 void gpu_material_add_node(GPUMaterial *material, GPUNode *node) 00371 { 00372 BLI_addtail(&material->nodes, node); 00373 } 00374 00375 /* Code generation */ 00376 00377 static int gpu_do_color_management(GPUMaterial *mat) 00378 { 00379 return ((mat->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) && 00380 !((mat->scene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT))); 00381 } 00382 00383 static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **lv, GPUNodeLink **dist) 00384 { 00385 GPUNodeLink *visifac, *inpr; 00386 00387 /* from get_lamp_visibility */ 00388 if(lamp->type==LA_SUN || lamp->type==LA_HEMI) { 00389 mat->dynproperty |= DYN_LAMP_VEC; 00390 GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), lv, dist, &visifac); 00391 return visifac; 00392 } 00393 else { 00394 mat->dynproperty |= DYN_LAMP_CO; 00395 GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), lv, dist, &visifac); 00396 00397 if(lamp->type==LA_AREA) 00398 return visifac; 00399 00400 switch(lamp->falloff_type) 00401 { 00402 case LA_FALLOFF_CONSTANT: 00403 break; 00404 case LA_FALLOFF_INVLINEAR: 00405 GPU_link(mat, "lamp_falloff_invlinear", GPU_uniform(&lamp->dist), *dist, &visifac); 00406 break; 00407 case LA_FALLOFF_INVSQUARE: 00408 GPU_link(mat, "lamp_falloff_invsquare", GPU_uniform(&lamp->dist), *dist, &visifac); 00409 break; 00410 case LA_FALLOFF_SLIDERS: 00411 GPU_link(mat, "lamp_falloff_sliders", GPU_uniform(&lamp->dist), GPU_uniform(&lamp->att1), GPU_uniform(&lamp->att2), *dist, &visifac); 00412 break; 00413 case LA_FALLOFF_CURVE: 00414 { 00415 float *array; 00416 int size; 00417 00418 curvemapping_table_RGBA(lamp->curfalloff, &array, &size); 00419 GPU_link(mat, "lamp_falloff_curve", GPU_uniform(&lamp->dist), GPU_texture(size, array), *dist, &visifac); 00420 } 00421 break; 00422 } 00423 00424 if(lamp->mode & LA_SPHERE) 00425 GPU_link(mat, "lamp_visibility_sphere", GPU_uniform(&lamp->dist), *dist, visifac, &visifac); 00426 00427 if(lamp->type == LA_SPOT) { 00428 if(lamp->mode & LA_SQUARE) { 00429 mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_IMAT; 00430 GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), GPU_dynamic_uniform((float*)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob), *lv, &inpr); 00431 } 00432 else { 00433 mat->dynproperty |= DYN_LAMP_VEC; 00434 GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), *lv, &inpr); 00435 } 00436 00437 GPU_link(mat, "lamp_visibility_spot", GPU_uniform(&lamp->spotsi), GPU_uniform(&lamp->spotbl), inpr, visifac, &visifac); 00438 } 00439 00440 GPU_link(mat, "lamp_visibility_clamp", visifac, &visifac); 00441 00442 return visifac; 00443 } 00444 } 00445 00446 #if 0 00447 static void area_lamp_vectors(LampRen *lar) 00448 { 00449 float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac; 00450 00451 /* make it smaller, so area light can be multisampled */ 00452 multifac= 1.0f/sqrt((float)lar->ray_totsamp); 00453 xsize *= multifac; 00454 ysize *= multifac; 00455 00456 /* corner vectors */ 00457 lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; 00458 lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; 00459 lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; 00460 00461 /* corner vectors */ 00462 lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; 00463 lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; 00464 lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; 00465 00466 /* corner vectors */ 00467 lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; 00468 lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; 00469 lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; 00470 00471 /* corner vectors */ 00472 lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; 00473 lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; 00474 lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; 00475 /* only for correction button size, matrix size works on energy */ 00476 lar->areasize= lar->dist*lar->dist/(4.0*xsize*ysize); 00477 } 00478 #endif 00479 00480 static void ramp_blend(GPUMaterial *mat, GPUNodeLink *fac, GPUNodeLink *col1, GPUNodeLink *col2, int type, GPUNodeLink **outcol) 00481 { 00482 static const char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub", 00483 "mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light", 00484 "mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat", 00485 "mix_val", "mix_color", "mix_soft", "mix_linear"}; 00486 00487 GPU_link(mat, names[type], fac, col1, col2, outcol); 00488 } 00489 00490 static void do_colorband_blend(GPUMaterial *mat, ColorBand *coba, GPUNodeLink *fac, float rampfac, int type, GPUNodeLink *incol, GPUNodeLink **outcol) 00491 { 00492 GPUNodeLink *tmp, *alpha, *col; 00493 float *array; 00494 int size; 00495 00496 /* do colorband */ 00497 colorband_table_RGBA(coba, &array, &size); 00498 GPU_link(mat, "valtorgb", fac, GPU_texture(size, array), &col, &tmp); 00499 00500 /* use alpha in fac */ 00501 GPU_link(mat, "mtex_alpha_from_col", col, &alpha); 00502 GPU_link(mat, "math_multiply", alpha, GPU_uniform(&rampfac), &fac); 00503 00504 /* blending method */ 00505 ramp_blend(mat, fac, incol, col, type, outcol); 00506 } 00507 00508 static void ramp_diffuse_result(GPUShadeInput *shi, GPUNodeLink **diff) 00509 { 00510 Material *ma= shi->mat; 00511 GPUMaterial *mat= shi->gpumat; 00512 GPUNodeLink *fac; 00513 00514 if(!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS)) { 00515 if(ma->ramp_col) { 00516 if(ma->rampin_col==MA_RAMP_IN_RESULT) { 00517 GPU_link(mat, "ramp_rgbtobw", *diff, &fac); 00518 00519 /* colorband + blend */ 00520 do_colorband_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, *diff, diff); 00521 } 00522 } 00523 } 00524 } 00525 00526 static void add_to_diffuse(GPUMaterial *mat, Material *ma, GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *rgb, GPUNodeLink **diff) 00527 { 00528 GPUNodeLink *fac, *tmp, *addcol; 00529 00530 if(!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS) && 00531 ma->ramp_col && (ma->mode & MA_RAMP_COL)) { 00532 /* MA_RAMP_IN_RESULT is exceptional */ 00533 if(ma->rampin_col==MA_RAMP_IN_RESULT) { 00534 addcol = shi->rgb; 00535 } 00536 else { 00537 /* input */ 00538 switch(ma->rampin_col) { 00539 case MA_RAMP_IN_ENERGY: 00540 GPU_link(mat, "ramp_rgbtobw", rgb, &fac); 00541 break; 00542 case MA_RAMP_IN_SHADER: 00543 fac= is; 00544 break; 00545 case MA_RAMP_IN_NOR: 00546 GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac); 00547 break; 00548 default: 00549 GPU_link(mat, "set_value_zero", &fac); 00550 break; 00551 } 00552 00553 /* colorband + blend */ 00554 do_colorband_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, shi->rgb, &addcol); 00555 } 00556 } 00557 else 00558 addcol = shi->rgb; 00559 00560 /* output to */ 00561 GPU_link(mat, "shade_madd_clamped", *diff, rgb, addcol, diff); 00562 } 00563 00564 static void ramp_spec_result(GPUShadeInput *shi, GPUNodeLink **spec) 00565 { 00566 Material *ma= shi->mat; 00567 GPUMaterial *mat= shi->gpumat; 00568 GPUNodeLink *fac; 00569 00570 if(!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS) && 00571 ma->ramp_spec && ma->rampin_spec==MA_RAMP_IN_RESULT) { 00572 GPU_link(mat, "ramp_rgbtobw", *spec, &fac); 00573 00574 /* colorband + blend */ 00575 do_colorband_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec); 00576 } 00577 } 00578 00579 static void do_specular_ramp(GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *t, GPUNodeLink **spec) 00580 { 00581 Material *ma= shi->mat; 00582 GPUMaterial *mat= shi->gpumat; 00583 GPUNodeLink *fac, *tmp; 00584 00585 *spec = shi->specrgb; 00586 00587 /* MA_RAMP_IN_RESULT is exception */ 00588 if(ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) { 00589 00590 /* input */ 00591 switch(ma->rampin_spec) { 00592 case MA_RAMP_IN_ENERGY: 00593 fac = t; 00594 break; 00595 case MA_RAMP_IN_SHADER: 00596 fac = is; 00597 break; 00598 case MA_RAMP_IN_NOR: 00599 GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac); 00600 break; 00601 default: 00602 GPU_link(mat, "set_value_zero", &fac); 00603 break; 00604 } 00605 00606 /* colorband + blend */ 00607 do_colorband_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec); 00608 } 00609 } 00610 00611 static void add_user_list(ListBase *list, void *data) 00612 { 00613 LinkData *link = MEM_callocN(sizeof(LinkData), "GPULinkData"); 00614 link->data = data; 00615 BLI_addtail(list, link); 00616 } 00617 00618 static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *lamp) 00619 { 00620 Material *ma= shi->mat; 00621 GPUMaterial *mat= shi->gpumat; 00622 GPUNodeLink *lv, *dist, *visifac, *is, *inp, *i, *vn, *view; 00623 GPUNodeLink *outcol, *specfac, *t, *shadfac= NULL; 00624 float one = 1.0f; 00625 00626 if((lamp->mode & LA_ONLYSHADOW) && !(ma->mode & MA_SHADOW)) 00627 return; 00628 00629 vn= shi->vn; 00630 view= shi->view; 00631 00632 visifac= lamp_get_visibility(mat, lamp, &lv, &dist); 00633 00634 /*if(ma->mode & MA_TANGENT_V) 00635 GPU_link(mat, "shade_tangent_v", lv, GPU_attribute(CD_TANGENT, ""), &vn);*/ 00636 00637 GPU_link(mat, "shade_inp", vn, lv, &inp); 00638 00639 if(lamp->mode & LA_NO_DIFF) { 00640 GPU_link(mat, "shade_is_no_diffuse", &is); 00641 } 00642 else if(lamp->type == LA_HEMI) { 00643 GPU_link(mat, "shade_is_hemi", inp, &is); 00644 } 00645 else { 00646 if(lamp->type == LA_AREA) { 00647 float area[4][4]= {{0.0f}}, areasize= 0.0f; 00648 00649 mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_CO; 00650 GPU_link(mat, "shade_inp_area", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), vn, GPU_uniform((float*)area), 00651 GPU_uniform(&areasize), GPU_uniform(&lamp->k), &inp); 00652 } 00653 00654 is= inp; /* Lambert */ 00655 00656 if(!(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS)) { 00657 if(ma->diff_shader==MA_DIFF_ORENNAYAR) 00658 GPU_link(mat, "shade_diffuse_oren_nayer", inp, vn, lv, view, GPU_uniform(&ma->roughness), &is); 00659 else if(ma->diff_shader==MA_DIFF_TOON) 00660 GPU_link(mat, "shade_diffuse_toon", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is); 00661 else if(ma->diff_shader==MA_DIFF_MINNAERT) 00662 GPU_link(mat, "shade_diffuse_minnaert", inp, vn, view, GPU_uniform(&ma->darkness), &is); 00663 else if(ma->diff_shader==MA_DIFF_FRESNEL) 00664 GPU_link(mat, "shade_diffuse_fresnel", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is); 00665 } 00666 } 00667 00668 if(!(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS)) 00669 if(ma->shade_flag & MA_CUBIC) 00670 GPU_link(mat, "shade_cubic", is, &is); 00671 00672 i = is; 00673 GPU_link(mat, "shade_visifac", i, visifac, shi->refl, &i); 00674 00675 00676 /*if(ma->mode & MA_TANGENT_VN) 00677 GPU_link(mat, "shade_tangent_v_spec", GPU_attribute(CD_TANGENT, ""), &vn);*/ 00678 00679 /* this replaces if(i > 0.0) conditional until that is supported */ 00680 // done in shade_visifac now, GPU_link(mat, "mtex_value_clamp_positive", i, &i); 00681 00682 if((ma->mode & MA_SHADOW) && GPU_lamp_has_shadow_buffer(lamp)) { 00683 if(!(mat->scene->gm.flag & GAME_GLSL_NO_SHADOWS)) { 00684 mat->dynproperty |= DYN_LAMP_PERSMAT; 00685 00686 GPU_link(mat, "test_shadowbuf", 00687 GPU_builtin(GPU_VIEW_POSITION), 00688 GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob), 00689 GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob), 00690 GPU_uniform(&lamp->bias), inp, &shadfac); 00691 00692 if(lamp->mode & LA_ONLYSHADOW) { 00693 GPU_link(mat, "shade_only_shadow", i, shadfac, 00694 GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob), &shadfac); 00695 00696 if(!(lamp->mode & LA_NO_DIFF)) 00697 GPU_link(mat, "shade_only_shadow_diffuse", shadfac, shi->rgb, 00698 shr->diff, &shr->diff); 00699 00700 if(!(lamp->mode & LA_NO_SPEC)) 00701 GPU_link(mat, "shade_only_shadow_specular", shadfac, shi->specrgb, 00702 shr->spec, &shr->spec); 00703 00704 add_user_list(&mat->lamps, lamp); 00705 add_user_list(&lamp->materials, shi->gpumat->ma); 00706 return; 00707 } 00708 00709 GPU_link(mat, "math_multiply", i, shadfac, &i); 00710 } 00711 } 00712 else if((mat->scene->gm.flag & GAME_GLSL_NO_SHADOWS) && (lamp->mode & LA_ONLYSHADOW)) { 00713 add_user_list(&mat->lamps, lamp); 00714 add_user_list(&lamp->materials, shi->gpumat->ma); 00715 return; 00716 } 00717 else 00718 GPU_link(mat, "set_value", GPU_uniform(&one), &shadfac); 00719 00720 if(GPU_link_changed(shi->refl) || ma->ref != 0.0f) { 00721 if(!(lamp->mode & LA_NO_DIFF)) { 00722 GPUNodeLink *rgb; 00723 GPU_link(mat, "shade_mul_value", i, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), &rgb); 00724 add_to_diffuse(mat, ma, shi, is, rgb, &shr->diff); 00725 } 00726 } 00727 00728 if(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS); 00729 else if(!(lamp->mode & LA_NO_SPEC) && !(lamp->mode & LA_ONLYSHADOW) && 00730 (GPU_link_changed(shi->spec) || ma->spec != 0.0f)) { 00731 if(lamp->type == LA_HEMI) { 00732 GPU_link(mat, "shade_hemi_spec", vn, lv, view, GPU_uniform(&ma->spec), shi->har, visifac, &t); 00733 GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), shi->specrgb, &outcol); 00734 GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec); 00735 } 00736 else { 00737 if(ma->spec_shader==MA_SPEC_PHONG) 00738 GPU_link(mat, "shade_phong_spec", vn, lv, view, shi->har, &specfac); 00739 else if(ma->spec_shader==MA_SPEC_COOKTORR) 00740 GPU_link(mat, "shade_cooktorr_spec", vn, lv, view, shi->har, &specfac); 00741 else if(ma->spec_shader==MA_SPEC_BLINN) 00742 GPU_link(mat, "shade_blinn_spec", vn, lv, view, GPU_uniform(&ma->refrac), shi->har, &specfac); 00743 else if(ma->spec_shader==MA_SPEC_WARDISO) 00744 GPU_link(mat, "shade_wardiso_spec", vn, lv, view, GPU_uniform(&ma->rms), &specfac); 00745 else 00746 GPU_link(mat, "shade_toon_spec", vn, lv, view, GPU_uniform(&ma->param[2]), GPU_uniform(&ma->param[3]), &specfac); 00747 00748 if(lamp->type==LA_AREA) 00749 GPU_link(mat, "shade_spec_area_inp", specfac, inp, &specfac); 00750 00751 GPU_link(mat, "shade_spec_t", shadfac, shi->spec, visifac, specfac, &t); 00752 00753 if(ma->mode & MA_RAMP_SPEC) { 00754 GPUNodeLink *spec; 00755 do_specular_ramp(shi, specfac, t, &spec); 00756 GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), spec, &outcol); 00757 GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec); 00758 } 00759 else { 00760 GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), shi->specrgb, &outcol); 00761 GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec); 00762 } 00763 } 00764 } 00765 00766 add_user_list(&mat->lamps, lamp); 00767 add_user_list(&lamp->materials, shi->gpumat->ma); 00768 } 00769 00770 static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr) 00771 { 00772 Base *base; 00773 Object *ob; 00774 Scene *sce_iter; 00775 GPULamp *lamp; 00776 00777 for(SETLOOPER(shi->gpumat->scene, sce_iter, base)) { 00778 ob= base->object; 00779 00780 if(ob->type==OB_LAMP) { 00781 lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, NULL); 00782 if(lamp) 00783 shade_one_light(shi, shr, lamp); 00784 } 00785 00786 if (ob->transflag & OB_DUPLI) { 00787 DupliObject *dob; 00788 ListBase *lb = object_duplilist(shi->gpumat->scene, ob); 00789 00790 for(dob=lb->first; dob; dob=dob->next) { 00791 Object *ob_iter = dob->ob; 00792 00793 if(ob_iter->type==OB_LAMP) { 00794 copy_m4_m4(ob_iter->obmat, dob->mat); 00795 00796 lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob_iter, ob); 00797 if(lamp) 00798 shade_one_light(shi, shr, lamp); 00799 } 00800 } 00801 00802 free_object_duplilist(lb); 00803 } 00804 } 00805 } 00806 00807 static void texture_rgb_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg, int blendtype, GPUNodeLink **in) 00808 { 00809 switch(blendtype) { 00810 case MTEX_BLEND: 00811 GPU_link(mat, "mtex_rgb_blend", out, tex, fact, facg, in); 00812 break; 00813 case MTEX_MUL: 00814 GPU_link(mat, "mtex_rgb_mul", out, tex, fact, facg, in); 00815 break; 00816 case MTEX_SCREEN: 00817 GPU_link(mat, "mtex_rgb_screen", out, tex, fact, facg, in); 00818 break; 00819 case MTEX_OVERLAY: 00820 GPU_link(mat, "mtex_rgb_overlay", out, tex, fact, facg, in); 00821 break; 00822 case MTEX_SUB: 00823 GPU_link(mat, "mtex_rgb_sub", out, tex, fact, facg, in); 00824 break; 00825 case MTEX_ADD: 00826 GPU_link(mat, "mtex_rgb_add", out, tex, fact, facg, in); 00827 break; 00828 case MTEX_DIV: 00829 GPU_link(mat, "mtex_rgb_div", out, tex, fact, facg, in); 00830 break; 00831 case MTEX_DIFF: 00832 GPU_link(mat, "mtex_rgb_diff", out, tex, fact, facg, in); 00833 break; 00834 case MTEX_DARK: 00835 GPU_link(mat, "mtex_rgb_dark", out, tex, fact, facg, in); 00836 break; 00837 case MTEX_LIGHT: 00838 GPU_link(mat, "mtex_rgb_light", out, tex, fact, facg, in); 00839 break; 00840 case MTEX_BLEND_HUE: 00841 GPU_link(mat, "mtex_rgb_hue", out, tex, fact, facg, in); 00842 break; 00843 case MTEX_BLEND_SAT: 00844 GPU_link(mat, "mtex_rgb_sat", out, tex, fact, facg, in); 00845 break; 00846 case MTEX_BLEND_VAL: 00847 GPU_link(mat, "mtex_rgb_val", out, tex, fact, facg, in); 00848 break; 00849 case MTEX_BLEND_COLOR: 00850 GPU_link(mat, "mtex_rgb_color", out, tex, fact, facg, in); 00851 break; 00852 default: 00853 GPU_link(mat, "set_rgb_zero", &in); 00854 break; 00855 } 00856 } 00857 00858 static void texture_value_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg, int blendtype, GPUNodeLink **in) 00859 { 00860 switch(blendtype) { 00861 case MTEX_BLEND: 00862 GPU_link(mat, "mtex_value_blend", out, tex, fact, facg, in); 00863 break; 00864 case MTEX_MUL: 00865 GPU_link(mat, "mtex_value_mul", out, tex, fact, facg, in); 00866 break; 00867 case MTEX_SCREEN: 00868 GPU_link(mat, "mtex_value_screen", out, tex, fact, facg, in); 00869 break; 00870 case MTEX_SUB: 00871 GPU_link(mat, "mtex_value_sub", out, tex, fact, facg, in); 00872 break; 00873 case MTEX_ADD: 00874 GPU_link(mat, "mtex_value_add", out, tex, fact, facg, in); 00875 break; 00876 case MTEX_DIV: 00877 GPU_link(mat, "mtex_value_div", out, tex, fact, facg, in); 00878 break; 00879 case MTEX_DIFF: 00880 GPU_link(mat, "mtex_value_diff", out, tex, fact, facg, in); 00881 break; 00882 case MTEX_DARK: 00883 GPU_link(mat, "mtex_value_dark", out, tex, fact, facg, in); 00884 break; 00885 case MTEX_LIGHT: 00886 GPU_link(mat, "mtex_value_light", out, tex, fact, facg, in); 00887 break; 00888 default: 00889 GPU_link(mat, "set_value_zero", &in); 00890 break; 00891 } 00892 } 00893 00894 static void do_material_tex(GPUShadeInput *shi) 00895 { 00896 Material *ma= shi->mat; 00897 GPUMaterial *mat= shi->gpumat; 00898 MTex *mtex; 00899 Tex *tex; 00900 GPUNodeLink *texco, *tin, *trgb, *tnor, *tcol, *stencil, *tnorfac; 00901 GPUNodeLink *texco_norm, *texco_orco, *texco_object; 00902 GPUNodeLink *texco_global, *texco_uv = NULL; 00903 GPUNodeLink *newnor, *orn; 00904 /*char *lastuvname = NULL;*/ /*UNUSED*/ 00905 float one = 1.0f, norfac, ofs[3]; 00906 int tex_nr, rgbnor, talpha; 00907 int init_done = 0, iBumpSpacePrev = 0; /* Not necessary, quiting gcc warning. */ 00908 GPUNodeLink *vNorg, *vNacc, *fPrevMagnitude; 00909 int iFirstTimeNMap=1; 00910 int found_deriv_map = 0; 00911 00912 GPU_link(mat, "set_value", GPU_uniform(&one), &stencil); 00913 00914 GPU_link(mat, "texco_norm", GPU_builtin(GPU_VIEW_NORMAL), &texco_norm); 00915 GPU_link(mat, "texco_orco", GPU_attribute(CD_ORCO, ""), &texco_orco); 00916 GPU_link(mat, "texco_object", GPU_builtin(GPU_INVERSE_VIEW_MATRIX), 00917 GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), 00918 GPU_builtin(GPU_VIEW_POSITION), &texco_object); 00919 //GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent); 00920 GPU_link(mat, "texco_global", GPU_builtin(GPU_INVERSE_VIEW_MATRIX), 00921 GPU_builtin(GPU_VIEW_POSITION), &texco_global); 00922 00923 orn= texco_norm; 00924 00925 /* go over texture slots */ 00926 for(tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) { 00927 /* separate tex switching */ 00928 if(ma->septex & (1<<tex_nr)) continue; 00929 00930 if(ma->mtex[tex_nr]) { 00931 mtex= ma->mtex[tex_nr]; 00932 00933 tex= mtex->tex; 00934 if(tex == NULL) continue; 00935 00936 /* which coords */ 00937 if(mtex->texco==TEXCO_ORCO) 00938 texco= texco_orco; 00939 else if(mtex->texco==TEXCO_OBJECT) 00940 texco= texco_object; 00941 else if(mtex->texco==TEXCO_NORM) 00942 texco= orn; 00943 else if(mtex->texco==TEXCO_TANGENT) 00944 texco= texco_object; 00945 else if(mtex->texco==TEXCO_GLOB) 00946 texco= texco_global; 00947 else if(mtex->texco==TEXCO_REFL) { 00948 GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref); 00949 texco= shi->ref; 00950 } 00951 else if(mtex->texco==TEXCO_UV) { 00952 if(1) { 00953 GPU_link(mat, "texco_uv", GPU_attribute(CD_MTFACE, mtex->uvname), &texco_uv); 00954 /*lastuvname = mtex->uvname;*/ /*UNUSED*/ 00955 } 00956 texco= texco_uv; 00957 } 00958 else 00959 continue; 00960 00961 /* in case of uv, this would just undo a multiplication in texco_uv */ 00962 if(mtex->texco != TEXCO_UV) 00963 GPU_link(mat, "mtex_2d_mapping", texco, &texco); 00964 00965 if(mtex->size[0] != 1.0f || mtex->size[1] != 1.0f || mtex->size[2] != 1.0f) 00966 GPU_link(mat, "mtex_mapping_size", texco, GPU_uniform(mtex->size), &texco); 00967 00968 ofs[0] = mtex->ofs[0] + 0.5f - 0.5f*mtex->size[0]; 00969 ofs[1] = mtex->ofs[1] + 0.5f - 0.5f*mtex->size[1]; 00970 ofs[2] = 0.0f; 00971 if(ofs[0] != 0.0f || ofs[1] != 0.0f || ofs[2] != 0.0f) 00972 GPU_link(mat, "mtex_mapping_ofs", texco, GPU_uniform(ofs), &texco); 00973 00974 talpha = 0; 00975 00976 if(tex && tex->type == TEX_IMAGE && tex->ima) { 00977 GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser), &tin, &trgb); 00978 rgbnor= TEX_RGB; 00979 00980 if(tex->imaflag & TEX_USEALPHA) 00981 talpha= 1; 00982 } 00983 else continue; 00984 00985 /* texture output */ 00986 if((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) { 00987 GPU_link(mat, "mtex_rgbtoint", trgb, &tin); 00988 rgbnor -= TEX_RGB; 00989 } 00990 00991 if(mtex->texflag & MTEX_NEGATIVE) { 00992 if(rgbnor & TEX_RGB) 00993 GPU_link(mat, "mtex_rgb_invert", trgb, &trgb); 00994 else 00995 GPU_link(mat, "mtex_value_invert", tin, &tin); 00996 } 00997 00998 if(mtex->texflag & MTEX_STENCIL) { 00999 if(rgbnor & TEX_RGB) 01000 GPU_link(mat, "mtex_rgb_stencil", stencil, trgb, &stencil, &trgb); 01001 else 01002 GPU_link(mat, "mtex_value_stencil", stencil, tin, &stencil, &tin); 01003 } 01004 01005 /* mapping */ 01006 if(mtex->mapto & (MAP_COL+MAP_COLSPEC)) { 01007 /* stencil maps on the texture control slider, not texture intensity value */ 01008 if((rgbnor & TEX_RGB)==0) { 01009 GPU_link(mat, "set_rgb", GPU_uniform(&mtex->r), &tcol); 01010 } 01011 else { 01012 GPU_link(mat, "set_rgba", trgb, &tcol); 01013 01014 if(mtex->mapto & MAP_ALPHA) 01015 GPU_link(mat, "set_value", stencil, &tin); 01016 else if(talpha) 01017 GPU_link(mat, "mtex_alpha_from_col", trgb, &tin); 01018 else 01019 GPU_link(mat, "set_value_one", &tin); 01020 } 01021 01022 if(tex->type==TEX_IMAGE) 01023 if(gpu_do_color_management(mat)) 01024 GPU_link(mat, "srgb_to_linearrgb", tcol, &tcol); 01025 01026 if(mtex->mapto & MAP_COL) { 01027 GPUNodeLink *colfac; 01028 01029 if(mtex->colfac == 1.0f) colfac = stencil; 01030 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->colfac), stencil, &colfac); 01031 01032 texture_rgb_blend(mat, tcol, shi->rgb, tin, colfac, mtex->blendtype, &shi->rgb); 01033 } 01034 01035 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_COLSPEC)) { 01036 GPUNodeLink *colspecfac; 01037 01038 if(mtex->colspecfac == 1.0f) colspecfac = stencil; 01039 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->colspecfac), stencil, &colspecfac); 01040 01041 texture_rgb_blend(mat, tcol, shi->specrgb, tin, colspecfac, mtex->blendtype, &shi->specrgb); 01042 } 01043 } 01044 01045 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_NORM)) { 01046 if(tex->type==TEX_IMAGE) { 01047 found_deriv_map = tex->imaflag & TEX_DERIVATIVEMAP; 01048 01049 if(tex->imaflag & TEX_NORMALMAP) { 01050 /* normalmap image */ 01051 GPU_link(mat, "mtex_normal", texco, GPU_image(tex->ima, &tex->iuser), &tnor ); 01052 01053 if(mtex->norfac < 0.0f) 01054 GPU_link(mat, "mtex_negate_texnormal", tnor, &tnor); 01055 01056 if(mtex->normapspace == MTEX_NSPACE_TANGENT) 01057 { 01058 if(iFirstTimeNMap!=0) 01059 { 01060 // use unnormalized normal (this is how we bake it - closer to gamedev) 01061 GPUNodeLink *vNegNorm; 01062 GPU_link(mat, "vec_math_negate", GPU_builtin(GPU_VIEW_NORMAL), &vNegNorm); 01063 GPU_link(mat, "mtex_nspace_tangent", GPU_attribute(CD_TANGENT, ""), vNegNorm, tnor, &newnor); 01064 iFirstTimeNMap = 0; 01065 } 01066 else // otherwise use accumulated perturbations 01067 { 01068 GPU_link(mat, "mtex_nspace_tangent", GPU_attribute(CD_TANGENT, ""), shi->vn, tnor, &newnor); 01069 } 01070 } 01071 else 01072 newnor = tnor; 01073 01074 norfac = MIN2(fabsf(mtex->norfac), 1.0f); 01075 01076 if(norfac == 1.0f && !GPU_link_changed(stencil)) { 01077 shi->vn = newnor; 01078 } 01079 else { 01080 tnorfac = GPU_uniform(&norfac); 01081 01082 if(GPU_link_changed(stencil)) 01083 GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac); 01084 01085 GPU_link(mat, "mtex_blend_normal", tnorfac, shi->vn, newnor, &shi->vn); 01086 } 01087 01088 } else if( (mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP|MTEX_BICUBIC_BUMP)) || found_deriv_map) { 01089 /* ntap bumpmap image */ 01090 int iBumpSpace; 01091 float ima_x, ima_y; 01092 float hScale; 01093 01094 float imag_tspace_dimension_x = 1024.0f; // only used for texture space variant 01095 float aspect = 1.0f; 01096 01097 GPUNodeLink *surf_pos = GPU_builtin(GPU_VIEW_POSITION); 01098 GPUNodeLink *vR1, *vR2; 01099 GPUNodeLink *dBs, *dBt, *fDet; 01100 01101 hScale = 0.1; // compatibility adjustment factor for all bumpspace types 01102 if( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) 01103 hScale = 13.0f; // factor for scaling texspace bumps 01104 else if(found_deriv_map!=0) 01105 hScale = 1.0f; 01106 01107 // resolve texture resolution 01108 if( (mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map ) { 01109 ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, &tex->iuser); 01110 ima_x= 512.0f; ima_y= 512.f; // prevent calling textureSize, glsl 1.3 only 01111 if(ibuf) { 01112 ima_x= ibuf->x; 01113 ima_y= ibuf->y; 01114 aspect = ((float) ima_y) / ima_x; 01115 } 01116 } 01117 01118 // The negate on norfac is done because the 01119 // normal in the renderer points inward which corresponds 01120 // to inverting the bump map. Should this ever change 01121 // this negate must be removed. 01122 norfac = -hScale * mtex->norfac; 01123 if(found_deriv_map) 01124 { 01125 float fVirtDim = sqrtf(fabsf(ima_x*mtex->size[0]*ima_y*mtex->size[1])); 01126 norfac /= MAX2(fVirtDim, FLT_EPSILON); 01127 } 01128 01129 tnorfac = GPU_uniform(&norfac); 01130 01131 if(found_deriv_map) 01132 GPU_link(mat, "math_multiply", tnorfac, GPU_builtin(GPU_AUTO_BUMPSCALE), &tnorfac); 01133 01134 if(GPU_link_changed(stencil)) 01135 GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac); 01136 01137 if( !init_done ) { 01138 // copy shi->vn to vNorg and vNacc, set magnitude to 1 01139 GPU_link(mat, "mtex_bump_normals_init", shi->vn, &vNorg, &vNacc, &fPrevMagnitude); 01140 iBumpSpacePrev = 0; 01141 init_done = 1; 01142 } 01143 01144 // find current bump space 01145 if( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) 01146 iBumpSpace = 1; 01147 else if( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) 01148 iBumpSpace = 2; 01149 else 01150 iBumpSpace = 4; // ViewSpace 01151 01152 // re-initialize if bump space changed 01153 if( iBumpSpacePrev != iBumpSpace ) { 01154 01155 if( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) 01156 GPU_link( mat, "mtex_bump_init_objspace", 01157 surf_pos, vNorg, 01158 GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), 01159 fPrevMagnitude, vNacc, 01160 &fPrevMagnitude, &vNacc, 01161 &vR1, &vR2, &fDet ); 01162 01163 else if( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) 01164 GPU_link( mat, "mtex_bump_init_texturespace", 01165 surf_pos, vNorg, 01166 fPrevMagnitude, vNacc, 01167 &fPrevMagnitude, &vNacc, 01168 &vR1, &vR2, &fDet ); 01169 01170 else 01171 GPU_link( mat, "mtex_bump_init_viewspace", 01172 surf_pos, vNorg, 01173 fPrevMagnitude, vNacc, 01174 &fPrevMagnitude, &vNacc, 01175 &vR1, &vR2, &fDet ); 01176 01177 iBumpSpacePrev = iBumpSpace; 01178 } 01179 01180 01181 if(found_deriv_map) { 01182 GPU_link( mat, "mtex_bump_deriv", 01183 texco, GPU_image(tex->ima, &tex->iuser), GPU_uniform(&ima_x), GPU_uniform(&ima_y), tnorfac, 01184 &dBs, &dBt ); 01185 } 01186 else if( mtex->texflag & MTEX_3TAP_BUMP ) 01187 GPU_link( mat, "mtex_bump_tap3", 01188 texco, GPU_image(tex->ima, &tex->iuser), tnorfac, 01189 &dBs, &dBt ); 01190 else if( mtex->texflag & MTEX_5TAP_BUMP ) 01191 GPU_link( mat, "mtex_bump_tap5", 01192 texco, GPU_image(tex->ima, &tex->iuser), tnorfac, 01193 &dBs, &dBt ); 01194 else if( mtex->texflag & MTEX_BICUBIC_BUMP ){ 01195 if(GPU_bicubic_bump_support()){ 01196 GPU_link( mat, "mtex_bump_bicubic", 01197 texco, GPU_image(tex->ima, &tex->iuser), tnorfac, 01198 &dBs, &dBt ); 01199 }else{ 01200 GPU_link( mat, "mtex_bump_tap5", 01201 texco, GPU_image(tex->ima, &tex->iuser), tnorfac, 01202 &dBs, &dBt ); 01203 } 01204 } 01205 01206 01207 if( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) { 01208 float imag_tspace_dimension_y = aspect*imag_tspace_dimension_x; 01209 GPU_link( mat, "mtex_bump_apply_texspace", 01210 fDet, dBs, dBt, vR1, vR2, 01211 GPU_image(tex->ima, &tex->iuser), texco, 01212 GPU_uniform(&imag_tspace_dimension_x), GPU_uniform(&imag_tspace_dimension_y), vNacc, 01213 &vNacc, &shi->vn ); 01214 } else 01215 GPU_link( mat, "mtex_bump_apply", 01216 fDet, dBs, dBt, vR1, vR2, vNacc, 01217 &vNacc, &shi->vn ); 01218 01219 } 01220 } 01221 01222 GPU_link(mat, "vec_math_negate", shi->vn, &orn); 01223 } 01224 01225 if((mtex->mapto & MAP_VARS)) { 01226 if(rgbnor & TEX_RGB) { 01227 if(talpha) 01228 GPU_link(mat, "mtex_alpha_from_col", trgb, &tin); 01229 else 01230 GPU_link(mat, "mtex_rgbtoint", trgb, &tin); 01231 } 01232 01233 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_REF) { 01234 GPUNodeLink *difffac; 01235 01236 if(mtex->difffac == 1.0f) difffac = stencil; 01237 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->difffac), stencil, &difffac); 01238 01239 texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->refl, tin, difffac, mtex->blendtype, &shi->refl); 01240 GPU_link(mat, "mtex_value_clamp_positive", shi->refl, &shi->refl); 01241 } 01242 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_SPEC) { 01243 GPUNodeLink *specfac; 01244 01245 if(mtex->specfac == 1.0f) specfac = stencil; 01246 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->specfac), stencil, &specfac); 01247 01248 texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->spec, tin, specfac, mtex->blendtype, &shi->spec); 01249 GPU_link(mat, "mtex_value_clamp_positive", shi->spec, &shi->spec); 01250 } 01251 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_EMIT) { 01252 GPUNodeLink *emitfac; 01253 01254 if(mtex->emitfac == 1.0f) emitfac = stencil; 01255 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->emitfac), stencil, &emitfac); 01256 01257 texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->emit, tin, emitfac, mtex->blendtype, &shi->emit); 01258 GPU_link(mat, "mtex_value_clamp_positive", shi->emit, &shi->emit); 01259 } 01260 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_HAR) { 01261 GPUNodeLink *hardfac; 01262 01263 if(mtex->hardfac == 1.0f) hardfac = stencil; 01264 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->hardfac), stencil, &hardfac); 01265 01266 GPU_link(mat, "mtex_har_divide", shi->har, &shi->har); 01267 texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->har, tin, hardfac, mtex->blendtype, &shi->har); 01268 GPU_link(mat, "mtex_har_multiply_clamp", shi->har, &shi->har); 01269 } 01270 if(mtex->mapto & MAP_ALPHA) { 01271 GPUNodeLink *alphafac; 01272 01273 if(mtex->alphafac == 1.0f) alphafac = stencil; 01274 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->alphafac), stencil, &alphafac); 01275 01276 texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->alpha, tin, alphafac, mtex->blendtype, &shi->alpha); 01277 GPU_link(mat, "mtex_value_clamp", shi->alpha, &shi->alpha); 01278 } 01279 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_AMB) { 01280 GPUNodeLink *ambfac; 01281 01282 if(mtex->ambfac == 1.0f) ambfac = stencil; 01283 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->ambfac), stencil, &ambfac); 01284 01285 texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->amb, tin, ambfac, mtex->blendtype, &shi->amb); 01286 GPU_link(mat, "mtex_value_clamp", shi->amb, &shi->amb); 01287 } 01288 } 01289 } 01290 } 01291 } 01292 01293 void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi) 01294 { 01295 float hard = ma->har; 01296 01297 memset(shi, 0, sizeof(*shi)); 01298 01299 shi->gpumat = mat; 01300 shi->mat = ma; 01301 01302 GPU_link(mat, "set_rgb", GPU_uniform(&ma->r), &shi->rgb); 01303 GPU_link(mat, "set_rgb", GPU_uniform(&ma->specr), &shi->specrgb); 01304 GPU_link(mat, "shade_norm", GPU_builtin(GPU_VIEW_NORMAL), &shi->vn); 01305 GPU_link(mat, "set_value", GPU_uniform(&ma->alpha), &shi->alpha); 01306 GPU_link(mat, "set_value", GPU_uniform(&ma->ref), &shi->refl); 01307 GPU_link(mat, "set_value", GPU_uniform(&ma->spec), &shi->spec); 01308 GPU_link(mat, "set_value", GPU_uniform(&ma->emit), &shi->emit); 01309 GPU_link(mat, "set_value", GPU_uniform(&hard), &shi->har); 01310 GPU_link(mat, "set_value", GPU_uniform(&ma->amb), &shi->amb); 01311 GPU_link(mat, "shade_view", GPU_builtin(GPU_VIEW_POSITION), &shi->view); 01312 GPU_link(mat, "vcol_attribute", GPU_attribute(CD_MCOL, ""), &shi->vcol); 01313 if(gpu_do_color_management(mat)) 01314 GPU_link(mat, "srgb_to_linearrgb", shi->vcol, &shi->vcol); 01315 GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref); 01316 } 01317 01318 void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) 01319 { 01320 GPUMaterial *mat= shi->gpumat; 01321 GPUNodeLink *emit, *ulinfac, *ulogfac, *mistfac; 01322 Material *ma= shi->mat; 01323 World *world= mat->scene->world; 01324 float linfac, logfac, misttype; 01325 01326 memset(shr, 0, sizeof(*shr)); 01327 01328 if(ma->mode & MA_VERTEXCOLP) 01329 shi->rgb = shi->vcol; 01330 01331 do_material_tex(shi); 01332 01333 if((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP)) 01334 GPU_material_enable_alpha(mat); 01335 01336 if((mat->scene->gm.flag & GAME_GLSL_NO_LIGHTS) || (ma->mode & MA_SHLESS)) { 01337 shr->combined = shi->rgb; 01338 shr->alpha = shi->alpha; 01339 GPU_link(mat, "set_rgb", shi->rgb, &shr->diff); 01340 GPU_link(mat, "set_rgb_zero", &shr->spec); 01341 } 01342 else { 01343 if(GPU_link_changed(shi->emit) || ma->emit != 0.0f) { 01344 if((ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL) { 01345 GPU_link(mat, "shade_add", shi->emit, shi->vcol, &emit); 01346 GPU_link(mat, "shade_mul", emit, shi->rgb, &shr->diff); 01347 } 01348 else 01349 GPU_link(mat, "shade_mul_value", shi->emit, shi->rgb, &shr->diff); 01350 } 01351 else 01352 GPU_link(mat, "set_rgb_zero", &shr->diff); 01353 01354 GPU_link(mat, "set_rgb_zero", &shr->spec); 01355 01356 material_lights(shi, shr); 01357 01358 shr->combined = shr->diff; 01359 shr->alpha = shi->alpha; 01360 01361 if(world) { 01362 /* exposure correction */ 01363 if(world->exp!=0.0f || world->range!=1.0f) { 01364 linfac= 1.0f + powf((2.0f*world->exp + 0.5f), -10); 01365 logfac= logf((linfac-1.0f)/linfac)/world->range; 01366 01367 GPU_link(mat, "set_value", GPU_uniform(&linfac), &ulinfac); 01368 GPU_link(mat, "set_value", GPU_uniform(&logfac), &ulogfac); 01369 01370 GPU_link(mat, "shade_exposure_correct", shr->combined, 01371 ulinfac, ulogfac, &shr->combined); 01372 GPU_link(mat, "shade_exposure_correct", shr->spec, 01373 ulinfac, ulogfac, &shr->spec); 01374 } 01375 01376 /* ambient color */ 01377 if(world->ambr!=0.0f || world->ambg!=0.0f || world->ambb!=0.0f) { 01378 if(GPU_link_changed(shi->amb) || ma->amb != 0.0f) 01379 GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb), 01380 GPU_uniform(&world->ambr), &shr->combined); 01381 } 01382 } 01383 01384 if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shi, &shr->combined); 01385 if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(shi, &shr->spec); 01386 01387 if(GPU_link_changed(shi->spec) || ma->spec != 0.0f) 01388 GPU_link(mat, "shade_add", shr->combined, shr->spec, &shr->combined); 01389 } 01390 01391 GPU_link(mat, "mtex_alpha_to_col", shr->combined, shr->alpha, &shr->combined); 01392 01393 if(ma->shade_flag & MA_OBCOLOR) 01394 GPU_link(mat, "shade_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined); 01395 01396 if(world && (world->mode & WO_MIST) && !(ma->mode & MA_NOMIST)) { 01397 misttype = world->mistype; 01398 01399 GPU_link(mat, "shade_mist_factor", GPU_builtin(GPU_VIEW_POSITION), 01400 GPU_uniform(&world->miststa), GPU_uniform(&world->mistdist), 01401 GPU_uniform(&misttype), GPU_uniform(&world->misi), &mistfac); 01402 01403 GPU_link(mat, "mix_blend", mistfac, shr->combined, 01404 GPU_uniform(&world->horr), &shr->combined); 01405 } 01406 01407 if(!((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP))) { 01408 if(world && (GPU_link_changed(shr->alpha) || ma->alpha != 1.0f)) 01409 GPU_link(mat, "shade_world_mix", GPU_uniform(&world->horr), 01410 shr->combined, &shr->combined); 01411 01412 GPU_link(mat, "shade_alpha_opaque", shr->combined, &shr->combined); 01413 } 01414 01415 if(ma->shade_flag & MA_OBCOLOR) { 01416 mat->obcolalpha = 1; 01417 GPU_link(mat, "shade_alpha_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined); 01418 } 01419 } 01420 01421 static GPUNodeLink *GPU_blender_material(GPUMaterial *mat, Material *ma) 01422 { 01423 GPUShadeInput shi; 01424 GPUShadeResult shr; 01425 01426 GPU_shadeinput_set(mat, ma, &shi); 01427 GPU_shaderesult_set(&shi, &shr); 01428 01429 return shr.combined; 01430 } 01431 01432 GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) 01433 { 01434 GPUMaterial *mat; 01435 GPUNodeLink *outlink; 01436 LinkData *link; 01437 01438 for(link=ma->gpumaterial.first; link; link=link->next) 01439 if(((GPUMaterial*)link->data)->scene == scene) 01440 return link->data; 01441 01442 /* allocate material */ 01443 mat = GPU_material_construct_begin(ma); 01444 mat->scene = scene; 01445 01446 if(!(scene->gm.flag & GAME_GLSL_NO_NODES) && ma->nodetree && ma->use_nodes) { 01447 /* create nodes */ 01448 ntreeGPUMaterialNodes(ma->nodetree, mat); 01449 } 01450 else { 01451 /* create material */ 01452 outlink = GPU_blender_material(mat, ma); 01453 GPU_material_output_link(mat, outlink); 01454 } 01455 01456 if(!scene_use_new_shading_nodes(scene)) { 01457 if(gpu_do_color_management(mat)) 01458 if(mat->outlink) 01459 GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink); 01460 } 01461 01462 01463 GPU_material_construct_end(mat); 01464 01465 /* note that even if building the shader fails in some way, we still keep 01466 it to avoid trying to compile again and again, and simple do not use 01467 the actual shader on drawing */ 01468 01469 link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink"); 01470 link->data = mat; 01471 BLI_addtail(&ma->gpumaterial, link); 01472 01473 return mat; 01474 } 01475 01476 void GPU_materials_free(void) 01477 { 01478 Object *ob; 01479 Material *ma; 01480 extern Material defmaterial; 01481 01482 for(ma=G.main->mat.first; ma; ma=ma->id.next) 01483 GPU_material_free(ma); 01484 01485 GPU_material_free(&defmaterial); 01486 01487 for(ob=G.main->object.first; ob; ob=ob->id.next) 01488 GPU_lamp_free(ob); 01489 } 01490 01491 /* Lamps and shadow buffers */ 01492 01493 void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[][4]) 01494 { 01495 float mat[4][4]; 01496 01497 lamp->lay = lay; 01498 lamp->hide = hide; 01499 01500 copy_m4_m4(mat, obmat); 01501 normalize_m4(mat); 01502 01503 copy_v3_v3(lamp->vec, mat[2]); 01504 copy_v3_v3(lamp->co, mat[3]); 01505 copy_m4_m4(lamp->obmat, mat); 01506 invert_m4_m4(lamp->imat, mat); 01507 } 01508 01509 void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy) 01510 { 01511 lamp->energy = energy; 01512 if(lamp->mode & LA_NEG) lamp->energy= -lamp->energy; 01513 01514 lamp->col[0]= r* lamp->energy; 01515 lamp->col[1]= g* lamp->energy; 01516 lamp->col[2]= b* lamp->energy; 01517 } 01518 01519 static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp) 01520 { 01521 float temp, angle, pixsize, wsize; 01522 01523 lamp->scene = scene; 01524 lamp->ob = ob; 01525 lamp->par = par; 01526 lamp->la = la; 01527 01528 /* add_render_lamp */ 01529 lamp->mode = la->mode; 01530 lamp->type = la->type; 01531 01532 lamp->energy = la->energy; 01533 if(lamp->mode & LA_NEG) lamp->energy= -lamp->energy; 01534 01535 lamp->col[0]= la->r*lamp->energy; 01536 lamp->col[1]= la->g*lamp->energy; 01537 lamp->col[2]= la->b*lamp->energy; 01538 01539 GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat); 01540 01541 lamp->spotsi= la->spotsize; 01542 if(lamp->mode & LA_HALO) 01543 if(lamp->spotsi > 170.0f) 01544 lamp->spotsi = 170.0f; 01545 lamp->spotsi= cosf((float)M_PI*lamp->spotsi/360.0f); 01546 lamp->spotbl= (1.0f - lamp->spotsi)*la->spotblend; 01547 lamp->k= la->k; 01548 01549 lamp->dist= la->dist; 01550 lamp->falloff_type= la->falloff_type; 01551 lamp->att1= la->att1; 01552 lamp->att2= la->att2; 01553 lamp->curfalloff= la->curfalloff; 01554 01555 /* initshadowbuf */ 01556 lamp->bias = 0.02f*la->bias; 01557 lamp->size = la->bufsize; 01558 lamp->d= la->clipsta; 01559 lamp->clipend= la->clipend; 01560 01561 /* arbitrary correction for the fact we do no soft transition */ 01562 lamp->bias *= 0.25f; 01563 01564 /* makeshadowbuf */ 01565 angle= saacos(lamp->spotsi); 01566 temp= 0.5f*lamp->size*cosf(angle)/sinf(angle); 01567 pixsize= (lamp->d)/temp; 01568 wsize= pixsize*0.5f*lamp->size; 01569 01570 perspective_m4( lamp->winmat,-wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend); 01571 } 01572 01573 static void gpu_lamp_shadow_free(GPULamp *lamp) 01574 { 01575 if(lamp->tex) { 01576 GPU_texture_free(lamp->tex); 01577 lamp->tex= NULL; 01578 } 01579 if(lamp->fb) { 01580 GPU_framebuffer_free(lamp->fb); 01581 lamp->fb= NULL; 01582 } 01583 } 01584 01585 GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) 01586 { 01587 Lamp *la; 01588 GPULamp *lamp; 01589 LinkData *link; 01590 01591 for(link=ob->gpulamp.first; link; link=link->next) { 01592 lamp = (GPULamp*)link->data; 01593 01594 if(lamp->par == par && lamp->scene == scene) 01595 return link->data; 01596 } 01597 01598 lamp = MEM_callocN(sizeof(GPULamp), "GPULamp"); 01599 01600 link = MEM_callocN(sizeof(LinkData), "GPULampLink"); 01601 link->data = lamp; 01602 BLI_addtail(&ob->gpulamp, link); 01603 01604 la = ob->data; 01605 gpu_lamp_from_blender(scene, ob, par, la, lamp); 01606 01607 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF)) { 01608 /* opengl */ 01609 lamp->fb = GPU_framebuffer_create(); 01610 if(!lamp->fb) { 01611 gpu_lamp_shadow_free(lamp); 01612 return lamp; 01613 } 01614 01615 lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL); 01616 if(!lamp->tex) { 01617 gpu_lamp_shadow_free(lamp); 01618 return lamp; 01619 } 01620 01621 if(!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, NULL)) { 01622 gpu_lamp_shadow_free(lamp); 01623 return lamp; 01624 } 01625 01626 GPU_framebuffer_restore(); 01627 } 01628 01629 return lamp; 01630 } 01631 01632 void GPU_lamp_free(Object *ob) 01633 { 01634 GPULamp *lamp; 01635 LinkData *link; 01636 LinkData *nlink; 01637 Material *ma; 01638 01639 for(link=ob->gpulamp.first; link; link=link->next) { 01640 lamp = link->data; 01641 01642 while(lamp->materials.first) { 01643 nlink = lamp->materials.first; 01644 ma = nlink->data; 01645 BLI_freelinkN(&lamp->materials, nlink); 01646 01647 if(ma->gpumaterial.first) 01648 GPU_material_free(ma); 01649 } 01650 01651 gpu_lamp_shadow_free(lamp); 01652 01653 MEM_freeN(lamp); 01654 } 01655 01656 BLI_freelistN(&ob->gpulamp); 01657 } 01658 01659 int GPU_lamp_has_shadow_buffer(GPULamp *lamp) 01660 { 01661 return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) && 01662 !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) && 01663 lamp->tex && lamp->fb); 01664 } 01665 01666 void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[][4], int *winsize, float winmat[][4]) 01667 { 01668 float rangemat[4][4], persmat[4][4]; 01669 01670 /* initshadowbuf */ 01671 invert_m4_m4(lamp->viewmat, lamp->obmat); 01672 normalize_v3(lamp->viewmat[0]); 01673 normalize_v3(lamp->viewmat[1]); 01674 normalize_v3(lamp->viewmat[2]); 01675 01676 /* makeshadowbuf */ 01677 mult_m4_m4m4(persmat, lamp->winmat, lamp->viewmat); 01678 01679 /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */ 01680 unit_m4(rangemat); 01681 rangemat[0][0] = 0.5f; 01682 rangemat[1][1] = 0.5f; 01683 rangemat[2][2] = 0.5f; 01684 rangemat[3][0] = 0.5f; 01685 rangemat[3][1] = 0.5f; 01686 rangemat[3][2] = 0.5f; 01687 01688 mult_m4_m4m4(lamp->persmat, rangemat, persmat); 01689 01690 /* opengl */ 01691 glDisable(GL_SCISSOR_TEST); 01692 GPU_framebuffer_texture_bind(lamp->fb, lamp->tex, 01693 GPU_texture_opengl_width(lamp->tex), GPU_texture_opengl_height(lamp->tex)); 01694 01695 /* set matrices */ 01696 copy_m4_m4(viewmat, lamp->viewmat); 01697 copy_m4_m4(winmat, lamp->winmat); 01698 *winsize = lamp->size; 01699 } 01700 01701 void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp) 01702 { 01703 GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex); 01704 GPU_framebuffer_restore(); 01705 glEnable(GL_SCISSOR_TEST); 01706 } 01707 01708 int GPU_lamp_shadow_layer(GPULamp *lamp) 01709 { 01710 if(lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER|LA_LAYER_SHADOW))) 01711 return lamp->lay; 01712 else 01713 return -1; 01714 } 01715 01716 /* export the GLSL shader */ 01717 01718 GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma) 01719 { 01720 static struct { 01721 GPUBuiltin gputype; 01722 GPUDynamicType dynamictype; 01723 GPUDataType datatype; 01724 } builtins[] = { 01725 { GPU_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWMAT, GPU_DATA_16F }, 01726 { GPU_INVERSE_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWIMAT, GPU_DATA_16F }, 01727 { GPU_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_MAT, GPU_DATA_16F }, 01728 { GPU_INVERSE_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_IMAT, GPU_DATA_16F }, 01729 { GPU_OBCOLOR, GPU_DYNAMIC_OBJECT_COLOR, GPU_DATA_4F }, 01730 { GPU_AUTO_BUMPSCALE, GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE, GPU_DATA_1F }, 01731 { 0 } 01732 }; 01733 01734 GPUShaderExport *shader = NULL; 01735 GPUPass *pass; 01736 GPUInput *input; 01737 GPUMaterial *mat; 01738 GPUInputUniform *uniform; 01739 GPUInputAttribute *attribute; 01740 GLint lastbindcode; 01741 int i, liblen, fraglen; 01742 01743 if(!GPU_glsl_support()) 01744 return NULL; 01745 01746 mat = GPU_material_from_blender(scene, ma); 01747 pass = (mat)? mat->pass: NULL; 01748 01749 if(pass && pass->fragmentcode && pass->vertexcode) { 01750 shader = MEM_callocN(sizeof(GPUShaderExport), "GPUShaderExport"); 01751 01752 for(input = pass->inputs.first; input; input = input->next) { 01753 uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform"); 01754 01755 if(input->ima) { 01756 /* image sampler uniform */ 01757 uniform->type = GPU_DYNAMIC_SAMPLER_2DIMAGE; 01758 uniform->datatype = GPU_DATA_1I; 01759 uniform->image = input->ima; 01760 uniform->texnumber = input->texid; 01761 BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname)); 01762 } 01763 else if(input->tex) { 01764 /* generated buffer */ 01765 uniform->texnumber = input->texid; 01766 uniform->datatype = GPU_DATA_1I; 01767 BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname)); 01768 01769 switch(input->textype) { 01770 case GPU_SHADOW2D: 01771 uniform->type = GPU_DYNAMIC_SAMPLER_2DSHADOW; 01772 uniform->lamp = input->dynamicdata; 01773 break; 01774 case GPU_TEX2D: 01775 if(GPU_texture_opengl_bindcode(input->tex)) { 01776 uniform->type = GPU_DYNAMIC_SAMPLER_2DBUFFER; 01777 glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode); 01778 glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(input->tex)); 01779 uniform->texsize = GPU_texture_opengl_width(input->tex) * GPU_texture_opengl_height(input->tex); 01780 uniform->texpixels = MEM_mallocN(uniform->texsize*4, "RGBApixels"); 01781 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, uniform->texpixels); 01782 glBindTexture(GL_TEXTURE_2D, lastbindcode); 01783 } 01784 break; 01785 } 01786 } 01787 else { 01788 uniform->type = input->dynamictype; 01789 BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname)); 01790 switch(input->type) { 01791 case 1: 01792 uniform->datatype = GPU_DATA_1F; 01793 break; 01794 case 2: 01795 uniform->datatype = GPU_DATA_2F; 01796 break; 01797 case 3: 01798 uniform->datatype = GPU_DATA_3F; 01799 break; 01800 case 4: 01801 uniform->datatype = GPU_DATA_4F; 01802 break; 01803 case 9: 01804 uniform->datatype = GPU_DATA_9F; 01805 break; 01806 case 16: 01807 uniform->datatype = GPU_DATA_16F; 01808 break; 01809 } 01810 01811 if(uniform->type >= GPU_DYNAMIC_LAMP_FIRST && uniform->type <= GPU_DYNAMIC_LAMP_LAST) 01812 uniform->lamp = input->dynamicdata; 01813 } 01814 01815 if(uniform->type != GPU_DYNAMIC_NONE) 01816 BLI_addtail(&shader->uniforms, uniform); 01817 else 01818 MEM_freeN(uniform); 01819 } 01820 01821 /* process builtin uniform */ 01822 for(i=0; builtins[i].gputype; i++) { 01823 if(mat->builtins & builtins[i].gputype) { 01824 uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform"); 01825 uniform->type = builtins[i].dynamictype; 01826 uniform->datatype = builtins[i].datatype; 01827 BLI_strncpy(uniform->varname, GPU_builtin_name(builtins[i].gputype), sizeof(uniform->varname)); 01828 BLI_addtail(&shader->uniforms, uniform); 01829 } 01830 } 01831 01832 // now link fragement shader with library shader 01833 // TBD: remove the function that are not used in the main function 01834 liblen = (pass->libcode) ? strlen(pass->libcode) : 0; 01835 fraglen = strlen(pass->fragmentcode); 01836 shader->fragment = (char *)MEM_mallocN(liblen+fraglen+1, "GPUFragShader"); 01837 if(pass->libcode) 01838 memcpy(shader->fragment, pass->libcode, liblen); 01839 memcpy(&shader->fragment[liblen], pass->fragmentcode, fraglen); 01840 shader->fragment[liblen+fraglen] = 0; 01841 01842 // export the attribute 01843 for(i=0; i<mat->attribs.totlayer; i++) { 01844 attribute = MEM_callocN(sizeof(GPUInputAttribute), "GPUInputAttribute"); 01845 attribute->type = mat->attribs.layer[i].type; 01846 attribute->number = mat->attribs.layer[i].glindex; 01847 BLI_snprintf(attribute->varname, sizeof(attribute->varname), "att%d", mat->attribs.layer[i].attribid); 01848 01849 switch(attribute->type) { 01850 case CD_TANGENT: 01851 attribute->datatype = GPU_DATA_4F; 01852 break; 01853 case CD_MTFACE: 01854 attribute->datatype = GPU_DATA_2F; 01855 attribute->name = mat->attribs.layer[i].name; 01856 break; 01857 case CD_MCOL: 01858 attribute->datatype = GPU_DATA_4UB; 01859 attribute->name = mat->attribs.layer[i].name; 01860 break; 01861 case CD_ORCO: 01862 attribute->datatype = GPU_DATA_3F; 01863 break; 01864 } 01865 01866 if(attribute->datatype != GPU_DATA_NONE) 01867 BLI_addtail(&shader->attributes, attribute); 01868 else 01869 MEM_freeN(attribute); 01870 } 01871 01872 // export the vertex shader 01873 shader->vertex = BLI_strdup(pass->vertexcode); 01874 } 01875 01876 return shader; 01877 } 01878 01879 void GPU_free_shader_export(GPUShaderExport *shader) 01880 { 01881 GPUInputUniform *uniform; 01882 01883 if(shader == NULL) 01884 return; 01885 01886 for(uniform = shader->uniforms.first; uniform; uniform=uniform->next) 01887 if(uniform->texpixels) 01888 MEM_freeN(uniform->texpixels); 01889 01890 BLI_freelistN(&shader->uniforms); 01891 BLI_freelistN(&shader->attributes); 01892 01893 if(shader->vertex) 01894 MEM_freeN(shader->vertex); 01895 if(shader->fragment) 01896 MEM_freeN(shader->fragment); 01897 01898 MEM_freeN(shader); 01899 } 01900