Blender V2.61 - r43446

gpu_material.c

Go to the documentation of this file.
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