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