Cycles: working towards texture workflow design
[blender.git] / source / blender / gpu / intern / gpu_material.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2006 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Brecht Van Lommel.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/gpu/intern/gpu_material.c
31  *  \ingroup gpu
32  */
33
34
35 #include <math.h>
36 #include <string.h>
37
38 #include "GL/glew.h"
39
40 #include "MEM_guardedalloc.h"
41
42 #include "DNA_lamp_types.h"
43 #include "DNA_material_types.h"
44 #include "DNA_object_types.h"
45 #include "DNA_scene_types.h"
46 #include "DNA_world_types.h"
47
48 #include "BLI_math.h"
49 #include "BLI_blenlib.h"
50 #include "BLI_utildefines.h"
51
52 #include "BKE_anim.h"
53 #include "BKE_colortools.h"
54 #include "BKE_DerivedMesh.h"
55 #include "BKE_global.h"
56 #include "BKE_image.h"
57 #include "BKE_main.h"
58 #include "BKE_node.h"
59 #include "BKE_scene.h"
60 #include "BKE_texture.h"
61
62 #include "IMB_imbuf_types.h"
63
64 #include "GPU_extensions.h"
65 #include "GPU_material.h"
66
67 #include "gpu_codegen.h"
68
69 #include <string.h>
70
71 /* Structs */
72
73 typedef enum DynMatProperty {
74         DYN_LAMP_CO = 1,
75         DYN_LAMP_VEC = 2,
76         DYN_LAMP_IMAT = 4,
77         DYN_LAMP_PERSMAT = 8,
78 } DynMatProperty;
79
80 struct GPUMaterial {
81         Scene *scene;
82         Material *ma;
83         int drawtype;
84
85         /* for creating the material */
86         ListBase nodes;
87         GPUNodeLink *outlink;
88
89         /* for binding the material */
90         GPUPass *pass;
91         GPUVertexAttribs attribs;
92         int bound;
93         int builtins;
94         int alpha, obcolalpha;
95         int dynproperty;
96
97         /* for passing uniforms */
98         int viewmatloc, invviewmatloc;
99         int obmatloc, invobmatloc;
100         int obcolloc;
101
102         ListBase lamps;
103 };
104
105 struct GPULamp {
106         Scene *scene;
107         Object *ob;
108         Object *par;
109         Lamp *la;
110
111         int type, mode, lay, hide;
112
113         float dynenergy, dyncol[3];
114         float energy, col[3];
115
116         float co[3], vec[3];
117         float dynco[3], dynvec[3];
118         float obmat[4][4];
119         float imat[4][4];
120         float dynimat[4][4];
121
122         float spotsi, spotbl, k;
123         float dist, att1, att2;
124
125         float bias, d, clipend;
126         int size;
127
128         int falloff_type;
129         struct CurveMapping *curfalloff;
130
131         float winmat[4][4];
132         float viewmat[4][4];
133         float persmat[4][4];
134         float dynpersmat[4][4];
135
136         GPUFrameBuffer *fb;
137         GPUTexture *tex;
138
139         ListBase materials;
140 };
141
142 /* Functions */
143
144 static GPUMaterial *GPU_material_construct_begin(Material *ma)
145 {
146         GPUMaterial *material = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");
147
148         material->ma= ma;
149
150         return material;
151 }
152
153 static void gpu_material_set_attrib_id(GPUMaterial *material)
154 {
155         GPUVertexAttribs *attribs;
156         GPUShader *shader;
157         GPUPass *pass;
158         char name[32];
159         int a, b;
160
161         attribs= &material->attribs;
162         pass= material->pass;
163         if(!pass) {
164                 attribs->totlayer = 0;
165                 return;
166         }
167         
168         shader= GPU_pass_shader(pass);
169         if(!shader) {
170                 attribs->totlayer = 0;
171                 return;
172         }
173
174         /* convert from attribute number to the actual id assigned by opengl,
175          * in case the attrib does not get a valid index back, it was probably
176          * removed by the glsl compiler by dead code elimination */
177
178         for(a=0, b=0; a<attribs->totlayer; a++) {
179                 sprintf(name, "att%d", attribs->layer[a].glindex);
180                 attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name);
181
182                 if(attribs->layer[a].glindex >= 0) {
183                         attribs->layer[b] = attribs->layer[a];
184                         b++;
185                 }
186         }
187
188         attribs->totlayer = b;
189 }
190
191 static int GPU_material_construct_end(GPUMaterial *material)
192 {
193         if (material->outlink) {
194                 GPUNodeLink *outlink;
195                 GPUShader *shader;
196
197                 outlink = material->outlink;
198                 material->pass = GPU_generate_pass(&material->nodes, outlink,
199                         &material->attribs, &material->builtins, material->ma->id.name);
200
201                 if(!material->pass)
202                         return 0;
203
204                 gpu_material_set_attrib_id(material);
205                 
206                 shader = GPU_pass_shader(material->pass);
207
208                 if(material->builtins & GPU_VIEW_MATRIX)
209                         material->viewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_VIEW_MATRIX));
210                 if(material->builtins & GPU_INVERSE_VIEW_MATRIX)
211                         material->invviewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_VIEW_MATRIX));
212                 if(material->builtins & GPU_OBJECT_MATRIX)
213                         material->obmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBJECT_MATRIX));
214                 if(material->builtins & GPU_INVERSE_OBJECT_MATRIX)
215                         material->invobmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_OBJECT_MATRIX));
216                 if(material->builtins & GPU_OBCOLOR)
217                         material->obcolloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBCOLOR));
218
219                 return 1;
220         }
221
222         return 0;
223 }
224
225 void GPU_material_free(Material *ma)
226 {
227         LinkData *link;
228         LinkData *nlink, *mlink, *next;
229
230         for(link=ma->gpumaterial.first; link; link=link->next) {
231                 GPUMaterial *material = link->data;
232
233                 if(material->pass)
234                         GPU_pass_free(material->pass);
235
236                 for(nlink=material->lamps.first; nlink; nlink=nlink->next) {
237                         GPULamp *lamp = nlink->data;
238
239                         for(mlink=lamp->materials.first; mlink; mlink=next) {
240                                 next = mlink->next;
241                                 if(mlink->data == ma)
242                                         BLI_freelinkN(&lamp->materials, mlink);
243                         }
244                 }
245
246                 BLI_freelistN(&material->lamps);
247
248                 MEM_freeN(material);
249         }
250
251         BLI_freelistN(&ma->gpumaterial);
252 }
253
254 void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap)
255 {
256         if(material->pass) {
257                 LinkData *nlink;
258                 GPULamp *lamp;
259
260                 /* handle layer lamps */
261                 for(nlink=material->lamps.first; nlink; nlink=nlink->next) {
262                         lamp= nlink->data;
263
264                         if(!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))) {
265                                 lamp->dynenergy = lamp->energy;
266                                 VECCOPY(lamp->dyncol, lamp->col);
267                         }
268                         else {
269                                 lamp->dynenergy = 0.0f;
270                                 lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f;
271                         }
272                 }
273
274                 GPU_pass_bind(material->pass, time, mipmap);
275                 material->bound = 1;
276         }
277 }
278
279 void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4])
280 {
281         if(material->pass) {
282                 GPUShader *shader = GPU_pass_shader(material->pass);
283                 LinkData *nlink;
284                 GPULamp *lamp;
285                 float invmat[4][4], col[4];
286
287                 /* handle builtins */
288                 if(material->builtins & GPU_VIEW_MATRIX) {
289                         GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float*)viewmat);
290                 }
291                 if(material->builtins & GPU_INVERSE_VIEW_MATRIX) {
292                         GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv);
293                 }
294                 if(material->builtins & GPU_OBJECT_MATRIX) {
295                         GPU_shader_uniform_vector(shader, material->obmatloc, 16, 1, (float*)obmat);
296                 }
297                 if(material->builtins & GPU_INVERSE_OBJECT_MATRIX) {
298                         invert_m4_m4(invmat, obmat);
299                         GPU_shader_uniform_vector(shader, material->invobmatloc, 16, 1, (float*)invmat);
300                 }
301                 if(material->builtins & GPU_OBCOLOR) {
302                         QUATCOPY(col, obcol);
303                         CLAMP(col[3], 0.0f, 1.0f);
304                         GPU_shader_uniform_vector(shader, material->obcolloc, 4, 1, col);
305                 }
306
307                 /* update lamps */
308                 for(nlink=material->lamps.first; nlink; nlink=nlink->next) {
309                         lamp= nlink->data;
310
311                         if(material->dynproperty & DYN_LAMP_VEC) {
312                                 VECCOPY(lamp->dynvec, lamp->vec);
313                                 normalize_v3(lamp->dynvec);
314                                 negate_v3(lamp->dynvec);
315                                 mul_mat3_m4_v3(viewmat, lamp->dynvec);
316                         }
317
318                         if(material->dynproperty & DYN_LAMP_CO) {
319                                 VECCOPY(lamp->dynco, lamp->co);
320                                 mul_m4_v3(viewmat, lamp->dynco);
321                         }
322
323                         if(material->dynproperty & DYN_LAMP_IMAT)
324                                 mul_m4_m4m4(lamp->dynimat, viewinv, lamp->imat);
325                         if(material->dynproperty & DYN_LAMP_PERSMAT)
326                                 mul_m4_m4m4(lamp->dynpersmat, viewinv, lamp->persmat);
327                 }
328
329                 GPU_pass_update_uniforms(material->pass);
330         }
331 }
332
333 void GPU_material_unbind(GPUMaterial *material)
334 {
335         if (material->pass) {
336                 material->bound = 0;
337                 GPU_pass_unbind(material->pass);
338         }
339 }
340
341 int GPU_material_bound(GPUMaterial *material)
342 {
343         return material->bound;
344 }
345
346 void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
347 {
348         *attribs = material->attribs;
349 }
350
351 void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
352 {
353         if(!material->outlink)
354                 material->outlink= link;
355 }
356
357 int GPU_material_drawtype(GPUMaterial *material)
358 {
359         return material->drawtype;
360 }
361
362 void GPU_material_enable_alpha(GPUMaterial *material)
363 {
364         material->alpha= 1;
365 }
366
367 GPUBlendMode GPU_material_blend_mode(GPUMaterial *material, float obcol[3])
368 {
369         if(material->alpha || (material->obcolalpha && obcol[3] < 1.0f))
370                 return GPU_BLEND_ALPHA;
371         else
372                 return GPU_BLEND_SOLID;
373 }
374
375 void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
376 {
377         BLI_addtail(&material->nodes, node);
378 }
379
380 /* Code generation */
381
382 static int gpu_do_color_management(GPUMaterial *mat)
383 {
384         return ((mat->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) &&
385            !((mat->scene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT)));
386 }
387
388 static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **lv, GPUNodeLink **dist)
389 {
390         GPUNodeLink *visifac, *inpr;
391
392         /* from get_lamp_visibility */
393         if(lamp->type==LA_SUN || lamp->type==LA_HEMI) {
394                 mat->dynproperty |= DYN_LAMP_VEC;
395                 GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec), lv, dist, &visifac);
396                 return visifac;
397         }
398         else {
399                 mat->dynproperty |= DYN_LAMP_CO;
400                 GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco), lv, dist, &visifac);
401
402                 if(lamp->type==LA_AREA)
403                         return visifac;
404
405                 switch(lamp->falloff_type)
406                 {
407                         case LA_FALLOFF_CONSTANT:
408                                 break;
409                         case LA_FALLOFF_INVLINEAR:
410                                 GPU_link(mat, "lamp_falloff_invlinear", GPU_uniform(&lamp->dist), *dist, &visifac);
411                                 break;
412                         case LA_FALLOFF_INVSQUARE:
413                                 GPU_link(mat, "lamp_falloff_invsquare", GPU_uniform(&lamp->dist), *dist, &visifac);
414                                 break;
415                         case LA_FALLOFF_SLIDERS:
416                                 GPU_link(mat, "lamp_falloff_sliders", GPU_uniform(&lamp->dist), GPU_uniform(&lamp->att1), GPU_uniform(&lamp->att2), *dist, &visifac);
417                                 break;
418                         case LA_FALLOFF_CURVE:
419                                 {
420                                         float *array;
421                                         int size;
422
423                                         curvemapping_table_RGBA(lamp->curfalloff, &array, &size);
424                                         GPU_link(mat, "lamp_falloff_curve", GPU_uniform(&lamp->dist), GPU_texture(size, array), *dist, &visifac);
425                                 }
426                                 break;
427                 }
428
429                 if(lamp->mode & LA_SPHERE)
430                         GPU_link(mat, "lamp_visibility_sphere", GPU_uniform(&lamp->dist), *dist, visifac, &visifac);
431
432                 if(lamp->type == LA_SPOT) {
433                         if(lamp->mode & LA_SQUARE) {
434                                 mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_IMAT;
435                                 GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec), GPU_dynamic_uniform((float*)lamp->dynimat), *lv, &inpr);
436                         }
437                         else {
438                                 mat->dynproperty |= DYN_LAMP_VEC;
439                                 GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec), *lv, &inpr);
440                         }
441                         
442                         GPU_link(mat, "lamp_visibility_spot", GPU_uniform(&lamp->spotsi), GPU_uniform(&lamp->spotbl), inpr, visifac, &visifac);
443                 }
444
445                 GPU_link(mat, "lamp_visibility_clamp", visifac, &visifac);
446
447                 return visifac;
448         }
449 }
450
451 #if 0
452 static void area_lamp_vectors(LampRen *lar)
453 {
454         float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac;
455
456         /* make it smaller, so area light can be multisampled */
457         multifac= 1.0f/sqrt((float)lar->ray_totsamp);
458         xsize *= multifac;
459         ysize *= multifac;
460
461         /* corner vectors */
462         lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
463         lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
464         lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2];
465
466         /* corner vectors */
467         lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
468         lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
469         lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2];
470
471         /* corner vectors */
472         lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
473         lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
474         lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2];
475
476         /* corner vectors */
477         lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
478         lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
479         lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2];
480         /* only for correction button size, matrix size works on energy */
481         lar->areasize= lar->dist*lar->dist/(4.0*xsize*ysize);
482 }
483 #endif
484
485 static void ramp_blend(GPUMaterial *mat, GPUNodeLink *fac, GPUNodeLink *col1, GPUNodeLink *col2, int type, GPUNodeLink **outcol)
486 {
487         static const char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub",
488                 "mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light",
489                 "mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat",
490                 "mix_val", "mix_color", "mix_soft", "mix_linear"};
491
492         GPU_link(mat, names[type], fac, col1, col2, outcol);
493 }
494
495 static void do_colorband_blend(GPUMaterial *mat, ColorBand *coba, GPUNodeLink *fac, float rampfac, int type, GPUNodeLink *incol, GPUNodeLink **outcol)
496 {
497         GPUNodeLink *tmp, *alpha, *col;
498         float *array;
499         int size;
500
501         /* do colorband */
502         colorband_table_RGBA(coba, &array, &size);
503         GPU_link(mat, "valtorgb", fac, GPU_texture(size, array), &col, &tmp);
504
505         /* use alpha in fac */
506         GPU_link(mat, "mtex_alpha_from_col", col, &alpha);
507         GPU_link(mat, "math_multiply", alpha, GPU_uniform(&rampfac), &fac);
508
509         /* blending method */
510         ramp_blend(mat, fac, incol, col, type, outcol);
511 }
512
513 static void ramp_diffuse_result(GPUShadeInput *shi, GPUNodeLink **diff)
514 {
515         Material *ma= shi->mat;
516         GPUMaterial *mat= shi->gpumat;
517         GPUNodeLink *fac;
518
519         if(!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS)) {
520                 if(ma->ramp_col) {
521                         if(ma->rampin_col==MA_RAMP_IN_RESULT) {
522                                 GPU_link(mat, "ramp_rgbtobw", *diff, &fac);
523                                 
524                                 /* colorband + blend */
525                                 do_colorband_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, *diff, diff);
526                         }
527                 }
528         }
529 }
530
531 static void add_to_diffuse(GPUMaterial *mat, Material *ma, GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *rgb, GPUNodeLink **diff)
532 {
533         GPUNodeLink *fac, *tmp, *addcol;
534         
535         if(!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS) &&
536            ma->ramp_col && (ma->mode & MA_RAMP_COL)) {
537                 /* MA_RAMP_IN_RESULT is exceptional */
538                 if(ma->rampin_col==MA_RAMP_IN_RESULT) {
539                         addcol = shi->rgb;
540                 }
541                 else {
542                         /* input */
543                         switch(ma->rampin_col) {
544                         case MA_RAMP_IN_ENERGY:
545                                 GPU_link(mat, "ramp_rgbtobw", rgb, &fac);
546                                 break;
547                         case MA_RAMP_IN_SHADER:
548                                 fac= is;
549                                 break;
550                         case MA_RAMP_IN_NOR:
551                                 GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
552                                 break;
553                         default:
554                                 GPU_link(mat, "set_value_zero", &fac);
555                                 break;
556                         }
557
558                         /* colorband + blend */
559                         do_colorband_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, shi->rgb, &addcol);
560                 }
561         }
562         else
563                 addcol = shi->rgb;
564
565         /* output to */
566         GPU_link(mat, "shade_madd_clamped", *diff, rgb, addcol, diff);
567 }
568
569 static void ramp_spec_result(GPUShadeInput *shi, GPUNodeLink **spec)
570 {
571         Material *ma= shi->mat;
572         GPUMaterial *mat= shi->gpumat;
573         GPUNodeLink *fac;
574
575         if(!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS) &&
576            ma->ramp_spec && ma->rampin_spec==MA_RAMP_IN_RESULT) {
577                 GPU_link(mat, "ramp_rgbtobw", *spec, &fac);
578                 
579                 /* colorband + blend */
580                 do_colorband_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec);
581         }
582 }
583
584 static void do_specular_ramp(GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *t, GPUNodeLink **spec)
585 {
586         Material *ma= shi->mat;
587         GPUMaterial *mat= shi->gpumat;
588         GPUNodeLink *fac, *tmp;
589
590         *spec = shi->specrgb;
591
592         /* MA_RAMP_IN_RESULT is exception */
593         if(ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) {
594                 
595                 /* input */
596                 switch(ma->rampin_spec) {
597                 case MA_RAMP_IN_ENERGY:
598                         fac = t;
599                         break;
600                 case MA_RAMP_IN_SHADER:
601                         fac = is;
602                         break;
603                 case MA_RAMP_IN_NOR:
604                         GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
605                         break;
606                 default:
607                         GPU_link(mat, "set_value_zero", &fac);
608                         break;
609                 }
610                 
611                 /* colorband + blend */
612                 do_colorband_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec);
613         }
614 }
615
616 static void add_user_list(ListBase *list, void *data)
617 {
618         LinkData *link = MEM_callocN(sizeof(LinkData), "GPULinkData");
619         link->data = data;
620         BLI_addtail(list, link);
621 }
622
623 static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *lamp)
624 {
625         Material *ma= shi->mat;
626         GPUMaterial *mat= shi->gpumat;
627         GPUNodeLink *lv, *dist, *visifac, *is, *inp, *i, *vn, *view;
628         GPUNodeLink *outcol, *specfac, *t, *shadfac= NULL;
629         float one = 1.0f;
630
631         if((lamp->mode & LA_ONLYSHADOW) && !(ma->mode & MA_SHADOW))
632                 return;
633         
634         vn= shi->vn;
635         view= shi->view;
636
637         visifac= lamp_get_visibility(mat, lamp, &lv, &dist);
638
639         /*if(ma->mode & MA_TANGENT_V)
640                 GPU_link(mat, "shade_tangent_v", lv, GPU_attribute(CD_TANGENT, ""), &vn);*/
641         
642         GPU_link(mat, "shade_inp", vn, lv, &inp);
643
644         if(lamp->mode & LA_NO_DIFF) {
645                 GPU_link(mat, "shade_is_no_diffuse", &is);
646         }
647         else if(lamp->type == LA_HEMI) {
648                 GPU_link(mat, "shade_is_hemi", inp, &is);
649         }
650         else {
651                 if(lamp->type == LA_AREA) {
652                         float area[4][4]= {{0.0f}}, areasize= 0.0f;
653
654                         mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_CO;
655                         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),
656                                 GPU_uniform(&areasize), GPU_uniform(&lamp->k), &inp);
657                 }
658
659                 is= inp; /* Lambert */
660
661                 if(!(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS)) {
662                         if(ma->diff_shader==MA_DIFF_ORENNAYAR)
663                                 GPU_link(mat, "shade_diffuse_oren_nayer", inp, vn, lv, view, GPU_uniform(&ma->roughness), &is);
664                         else if(ma->diff_shader==MA_DIFF_TOON)
665                                 GPU_link(mat, "shade_diffuse_toon", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is);
666                         else if(ma->diff_shader==MA_DIFF_MINNAERT)
667                                 GPU_link(mat, "shade_diffuse_minnaert", inp, vn, view, GPU_uniform(&ma->darkness), &is);
668                         else if(ma->diff_shader==MA_DIFF_FRESNEL)
669                                 GPU_link(mat, "shade_diffuse_fresnel", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is);
670                 }
671         }
672
673         if(!(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS))
674                 if(ma->shade_flag & MA_CUBIC)
675                         GPU_link(mat, "shade_cubic", is, &is);
676         
677         i = is;
678         GPU_link(mat, "shade_visifac", i, visifac, shi->refl, &i);
679
680         vn = shi->vn;
681         /*if(ma->mode & MA_TANGENT_VN)
682                 GPU_link(mat, "shade_tangent_v_spec", GPU_attribute(CD_TANGENT, ""), &vn);*/
683
684         /* this replaces if(i > 0.0) conditional until that is supported */
685         // done in shade_visifac now, GPU_link(mat, "mtex_value_clamp_positive", i, &i);
686
687         if((ma->mode & MA_SHADOW) && GPU_lamp_has_shadow_buffer(lamp)) {
688                 if(!(mat->scene->gm.flag & GAME_GLSL_NO_SHADOWS)) {
689                         mat->dynproperty |= DYN_LAMP_PERSMAT;
690
691                         GPU_link(mat, "test_shadowbuf",
692                                 GPU_builtin(GPU_VIEW_POSITION),
693                                 GPU_dynamic_texture(lamp->tex),
694                                 GPU_dynamic_uniform((float*)lamp->dynpersmat),
695                                 GPU_uniform(&lamp->bias), inp, &shadfac);
696                         
697                         if(lamp->mode & LA_ONLYSHADOW) {
698                                 GPU_link(mat, "shade_only_shadow", i, shadfac,
699                                         GPU_dynamic_uniform(&lamp->dynenergy), &shadfac);
700                                 
701                                 if(!(lamp->mode & LA_NO_DIFF))
702                                         GPU_link(mat, "shade_only_shadow_diffuse", shadfac, shi->rgb,
703                                                 shr->diff, &shr->diff);
704
705                                 if(!(lamp->mode & LA_NO_SPEC))
706                                         GPU_link(mat, "shade_only_shadow_specular", shadfac, shi->specrgb,
707                                                 shr->spec, &shr->spec);
708                                 
709                                 add_user_list(&mat->lamps, lamp);
710                                 add_user_list(&lamp->materials, shi->gpumat->ma);
711                                 return;
712                         }
713                         
714                         GPU_link(mat, "math_multiply", i, shadfac, &i);
715                 }
716         }
717         else if((mat->scene->gm.flag & GAME_GLSL_NO_SHADOWS) && (lamp->mode & LA_ONLYSHADOW)) {
718                 add_user_list(&mat->lamps, lamp);
719                 add_user_list(&lamp->materials, shi->gpumat->ma);
720                 return;
721         }
722         else
723                 GPU_link(mat, "set_value", GPU_uniform(&one), &shadfac);
724
725         if(GPU_link_changed(shi->refl) || ma->ref != 0.0f) {
726                 if(!(lamp->mode & LA_NO_DIFF)) {
727                         GPUNodeLink *rgb;
728                         GPU_link(mat, "shade_mul_value", i, GPU_dynamic_uniform(lamp->dyncol), &rgb);
729                         add_to_diffuse(mat, ma, shi, is, rgb, &shr->diff);
730                 }
731         }
732
733         if(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS);
734         else if(!(lamp->mode & LA_NO_SPEC) && !(lamp->mode & LA_ONLYSHADOW) &&
735            (GPU_link_changed(shi->spec) || ma->spec != 0.0f)) {
736                 if(lamp->type == LA_HEMI) {
737                         GPU_link(mat, "shade_hemi_spec", vn, lv, view, GPU_uniform(&ma->spec), shi->har, visifac, &t);
738                         GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), shi->specrgb, &outcol);
739                         GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
740                 }
741                 else {
742                         if(ma->spec_shader==MA_SPEC_PHONG)
743                                 GPU_link(mat, "shade_phong_spec", vn, lv, view, shi->har, &specfac);
744                         else if(ma->spec_shader==MA_SPEC_COOKTORR)
745                                 GPU_link(mat, "shade_cooktorr_spec", vn, lv, view, shi->har, &specfac);
746                         else if(ma->spec_shader==MA_SPEC_BLINN)
747                                 GPU_link(mat, "shade_blinn_spec", vn, lv, view, GPU_uniform(&ma->refrac), shi->har, &specfac);
748                         else if(ma->spec_shader==MA_SPEC_WARDISO)
749                                 GPU_link(mat, "shade_wardiso_spec", vn, lv, view, GPU_uniform(&ma->rms), &specfac);
750                         else
751                                 GPU_link(mat, "shade_toon_spec", vn, lv, view, GPU_uniform(&ma->param[2]), GPU_uniform(&ma->param[3]), &specfac);
752
753                         if(lamp->type==LA_AREA)
754                                 GPU_link(mat, "shade_spec_area_inp", specfac, inp, &specfac);
755
756                         GPU_link(mat, "shade_spec_t", shadfac, shi->spec, visifac, specfac, &t);
757
758                         if(ma->mode & MA_RAMP_SPEC) {
759                                 GPUNodeLink *spec;
760                                 do_specular_ramp(shi, specfac, t, &spec);
761                                 GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), spec, &outcol);
762                                 GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
763                         }
764                         else {
765                                 GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), shi->specrgb, &outcol);
766                                 GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
767                         }
768                 }
769         }
770
771         add_user_list(&mat->lamps, lamp);
772         add_user_list(&lamp->materials, shi->gpumat->ma);
773 }
774
775 static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr)
776 {
777         Base *base;
778         Object *ob;
779         Scene *sce_iter;
780         GPULamp *lamp;
781         
782         for(SETLOOPER(shi->gpumat->scene, sce_iter, base)) {
783                 ob= base->object;
784
785                 if(ob->type==OB_LAMP) {
786                         lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, NULL);
787                         if(lamp)
788                                 shade_one_light(shi, shr, lamp);
789                 }
790
791                 if (ob->transflag & OB_DUPLI) {
792                         DupliObject *dob;
793                         ListBase *lb = object_duplilist(shi->gpumat->scene, ob);
794                         
795                         for(dob=lb->first; dob; dob=dob->next) {
796                                 Object *ob_iter = dob->ob;
797
798                                 if(ob_iter->type==OB_LAMP) {
799                                         copy_m4_m4(ob_iter->obmat, dob->mat);
800
801                                         lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob_iter, ob);
802                                         if(lamp)
803                                                 shade_one_light(shi, shr, lamp);
804                                 }
805                         }
806                         
807                         free_object_duplilist(lb);
808                 }
809         }
810 }
811
812 static void texture_rgb_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg, int blendtype, GPUNodeLink **in)
813 {
814         switch(blendtype) {
815         case MTEX_BLEND:
816                 GPU_link(mat, "mtex_rgb_blend", out, tex, fact, facg, in);
817                 break;
818         case MTEX_MUL:
819                 GPU_link(mat, "mtex_rgb_mul", out, tex, fact, facg, in);
820                 break;
821         case MTEX_SCREEN:
822                 GPU_link(mat, "mtex_rgb_screen", out, tex, fact, facg, in);
823                 break;
824         case MTEX_OVERLAY:
825                 GPU_link(mat, "mtex_rgb_overlay", out, tex, fact, facg, in);
826                 break;
827         case MTEX_SUB:
828                 GPU_link(mat, "mtex_rgb_sub", out, tex, fact, facg, in);
829                 break;
830         case MTEX_ADD:
831                 GPU_link(mat, "mtex_rgb_add", out, tex, fact, facg, in);
832                 break;
833         case MTEX_DIV:
834                 GPU_link(mat, "mtex_rgb_div", out, tex, fact, facg, in);
835                 break;
836         case MTEX_DIFF:
837                 GPU_link(mat, "mtex_rgb_diff", out, tex, fact, facg, in);
838                 break;
839         case MTEX_DARK:
840                 GPU_link(mat, "mtex_rgb_dark", out, tex, fact, facg, in);
841                 break;
842         case MTEX_LIGHT:
843                 GPU_link(mat, "mtex_rgb_light", out, tex, fact, facg, in);
844                 break;
845         case MTEX_BLEND_HUE:
846                 GPU_link(mat, "mtex_rgb_hue", out, tex, fact, facg, in);
847                 break;
848         case MTEX_BLEND_SAT:
849                 GPU_link(mat, "mtex_rgb_sat", out, tex, fact, facg, in);
850                 break;
851         case MTEX_BLEND_VAL:
852                 GPU_link(mat, "mtex_rgb_val", out, tex, fact, facg, in);
853                 break;
854         case MTEX_BLEND_COLOR:
855                 GPU_link(mat, "mtex_rgb_color", out, tex, fact, facg, in);
856                 break;
857         default:
858                 GPU_link(mat, "set_rgb_zero", &in);
859                 break;
860         }
861 }
862
863 static void texture_value_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg, int blendtype, GPUNodeLink **in)
864 {
865         switch(blendtype) {
866         case MTEX_BLEND:
867                 GPU_link(mat, "mtex_value_blend", out, tex, fact, facg, in);
868                 break;
869         case MTEX_MUL:
870                 GPU_link(mat, "mtex_value_mul", out, tex, fact, facg, in);
871                 break;
872         case MTEX_SCREEN:
873                 GPU_link(mat, "mtex_value_screen", out, tex, fact, facg, in);
874                 break;
875         case MTEX_SUB:
876                 GPU_link(mat, "mtex_value_sub", out, tex, fact, facg, in);
877                 break;
878         case MTEX_ADD:
879                 GPU_link(mat, "mtex_value_add", out, tex, fact, facg, in);
880                 break;
881         case MTEX_DIV:
882                 GPU_link(mat, "mtex_value_div", out, tex, fact, facg, in);
883                 break;
884         case MTEX_DIFF:
885                 GPU_link(mat, "mtex_value_diff", out, tex, fact, facg, in);
886                 break;
887         case MTEX_DARK:
888                 GPU_link(mat, "mtex_value_dark", out, tex, fact, facg, in);
889                 break;
890         case MTEX_LIGHT:
891                 GPU_link(mat, "mtex_value_light", out, tex, fact, facg, in);
892                 break;
893         default:
894                 GPU_link(mat, "set_value_zero", &in);
895                 break;
896         }
897 }
898
899 static void do_material_tex(GPUShadeInput *shi)
900 {
901         Material *ma= shi->mat;
902         GPUMaterial *mat= shi->gpumat;
903         MTex *mtex;
904         Tex *tex;
905         GPUNodeLink *texco, *tin, *trgb, *tnor, *tcol, *stencil, *tnorfac;
906         GPUNodeLink *texco_norm, *texco_orco, *texco_object;
907         GPUNodeLink *texco_global, *texco_uv = NULL;
908         GPUNodeLink *newnor, *orn;
909         /*char *lastuvname = NULL;*/ /*UNUSED*/
910         float one = 1.0f, norfac, ofs[3];
911         int tex_nr, rgbnor, talpha;
912         int init_done = 0, iBumpSpacePrev;
913         GPUNodeLink *vNorg, *vNacc, *fPrevMagnitude;
914         int iFirstTimeNMap=1;
915
916         GPU_link(mat, "set_value", GPU_uniform(&one), &stencil);
917
918         GPU_link(mat, "texco_norm", GPU_builtin(GPU_VIEW_NORMAL), &texco_norm);
919         GPU_link(mat, "texco_orco", GPU_attribute(CD_ORCO, ""), &texco_orco);
920         GPU_link(mat, "texco_object", GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
921                 GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
922                 GPU_builtin(GPU_VIEW_POSITION), &texco_object);
923         //GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent);
924         GPU_link(mat, "texco_global", GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
925                 GPU_builtin(GPU_VIEW_POSITION), &texco_global);
926
927         orn= texco_norm;
928
929         /* go over texture slots */
930         for(tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
931                 /* separate tex switching */
932                 if(ma->septex & (1<<tex_nr)) continue;
933                 
934                 if(ma->mtex[tex_nr]) {
935                         mtex= ma->mtex[tex_nr];
936                         
937                         tex= mtex->tex;
938                         if(tex == NULL) continue;
939
940                         /* which coords */
941                         if(mtex->texco==TEXCO_ORCO)
942                                 texco= texco_orco;
943                         else if(mtex->texco==TEXCO_OBJECT)
944                                 texco= texco_object;
945                         else if(mtex->texco==TEXCO_NORM)
946                                 texco= orn;
947                         else if(mtex->texco==TEXCO_TANGENT)
948                                 texco= texco_object;
949                         else if(mtex->texco==TEXCO_GLOB)
950                                 texco= texco_global;
951                         else if(mtex->texco==TEXCO_REFL) {
952                                 GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref);
953                                 texco= shi->ref;
954                         }
955                         else if(mtex->texco==TEXCO_UV) {
956                                 if(1) { //!(texco_uv && strcmp(mtex->uvname, lastuvname) == 0)) {
957                                         GPU_link(mat, "texco_uv", GPU_attribute(CD_MTFACE, mtex->uvname), &texco_uv);
958                                         /*lastuvname = mtex->uvname;*/ /*UNUSED*/
959                                 }
960                                 texco= texco_uv;
961                         }
962                         else
963                                 continue;
964
965                         /* in case of uv, this would just undo a multiplication in texco_uv */
966                         if(mtex->texco != TEXCO_UV)
967                                 GPU_link(mat, "mtex_2d_mapping", texco, &texco);
968
969                         if(mtex->size[0] != 1.0f || mtex->size[1] != 1.0f || mtex->size[2] != 1.0f)
970                                 GPU_link(mat, "mtex_mapping_size", texco, GPU_uniform(mtex->size), &texco);
971
972                         ofs[0] = mtex->ofs[0] + 0.5f - 0.5f*mtex->size[0];
973                         ofs[1] = mtex->ofs[1] + 0.5f - 0.5f*mtex->size[1];
974                         ofs[2] = 0.0f;
975                         if(ofs[0] != 0.0f || ofs[1] != 0.0f || ofs[2] != 0.0f)
976                                 GPU_link(mat, "mtex_mapping_ofs", texco, GPU_uniform(ofs), &texco);
977
978                         talpha = 0;
979                         rgbnor = 0;
980
981                         if(tex && tex->type == TEX_IMAGE && tex->ima) {
982                                 GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser), &tin, &trgb);
983                                 rgbnor= TEX_RGB;
984
985                                 if(tex->imaflag & TEX_USEALPHA)
986                                         talpha= 1;
987                         }
988                         else continue;
989
990                         /* texture output */
991                         if((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
992                                 GPU_link(mat, "mtex_rgbtoint", trgb, &tin);
993                                 rgbnor -= TEX_RGB;
994                         }
995
996                         if(mtex->texflag & MTEX_NEGATIVE) {
997                                 if(rgbnor & TEX_RGB)
998                                         GPU_link(mat, "mtex_rgb_invert", trgb, &trgb);
999                                 else
1000                                         GPU_link(mat, "mtex_value_invert", tin, &tin);
1001                         }
1002
1003                         if(mtex->texflag & MTEX_STENCIL) {
1004                                 if(rgbnor & TEX_RGB)
1005                                         GPU_link(mat, "mtex_rgb_stencil", stencil, trgb, &stencil, &trgb);
1006                                 else
1007                                         GPU_link(mat, "mtex_value_stencil", stencil, tin, &stencil, &tin);
1008                         }
1009
1010                         /* mapping */
1011                         if(mtex->mapto & (MAP_COL+MAP_COLSPEC)) {
1012                                 /* stencil maps on the texture control slider, not texture intensity value */
1013                                 if((rgbnor & TEX_RGB)==0) {
1014                                         GPU_link(mat, "set_rgb", GPU_uniform(&mtex->r), &tcol);
1015                                 }
1016                                 else {
1017                                         GPU_link(mat, "set_rgba", trgb, &tcol);
1018
1019                                         if(mtex->mapto & MAP_ALPHA)
1020                                                 GPU_link(mat, "set_value", stencil, &tin);
1021                                         else if(talpha)
1022                                                 GPU_link(mat, "mtex_alpha_from_col", trgb, &tin);
1023                                         else
1024                                                 GPU_link(mat, "set_value_one", &tin);
1025                                 }
1026
1027                                 if(tex->type==TEX_IMAGE)
1028                                         if(gpu_do_color_management(mat))
1029                                                 GPU_link(mat, "srgb_to_linearrgb", tcol, &tcol);
1030                                 
1031                                 if(mtex->mapto & MAP_COL) {
1032                                         GPUNodeLink *colfac;
1033
1034                                         if(mtex->colfac == 1.0f) colfac = stencil;
1035                                         else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->colfac), stencil, &colfac);
1036
1037                                         texture_rgb_blend(mat, tcol, shi->rgb, tin, colfac, mtex->blendtype, &shi->rgb);
1038                                 }
1039                                 
1040                                 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_COLSPEC)) {
1041                                         GPUNodeLink *colspecfac;
1042
1043                                         if(mtex->colspecfac == 1.0f) colspecfac = stencil;
1044                                         else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->colspecfac), stencil, &colspecfac);
1045
1046                                         texture_rgb_blend(mat, tcol, shi->specrgb, tin, colspecfac, mtex->blendtype, &shi->specrgb);
1047                                 }
1048                         }
1049
1050                         if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_NORM)) {
1051                                 if(tex->type==TEX_IMAGE) {
1052                                         if(tex->imaflag & TEX_NORMALMAP) {
1053                                                 /* normalmap image */
1054                                                 GPU_link(mat, "mtex_normal", texco, GPU_image(tex->ima, &tex->iuser), &tnor );
1055                                                 
1056                                                 if(mtex->norfac < 0.0f)
1057                                                         GPU_link(mat, "mtex_negate_texnormal", tnor, &tnor);
1058
1059                                                 if(mtex->normapspace == MTEX_NSPACE_TANGENT)
1060                                                 {
1061                                                         if(iFirstTimeNMap!=0)
1062                                                         {
1063                                                                 // use unnormalized normal (this is how we bake it - closer to gamedev)
1064                                                                 GPUNodeLink *vNegNorm;
1065                                                                 GPU_link(mat, "vec_math_negate", GPU_builtin(GPU_VIEW_NORMAL), &vNegNorm);
1066                                                                 GPU_link(mat, "mtex_nspace_tangent", GPU_attribute(CD_TANGENT, ""), vNegNorm, tnor, &newnor);
1067                                                                 iFirstTimeNMap = 0;
1068                                                         }
1069                                                         else    // otherwise use accumulated perturbations
1070                                                         {
1071                                                                 GPU_link(mat, "mtex_nspace_tangent", GPU_attribute(CD_TANGENT, ""), shi->vn, tnor, &newnor);
1072                                                         }
1073                                                 }
1074                                                 else
1075                                                         newnor = tnor;
1076                                                 
1077                                                 norfac = MIN2(fabsf(mtex->norfac), 1.0f);
1078                                                 
1079                                                 if(norfac == 1.0f && !GPU_link_changed(stencil)) {
1080                                                         shi->vn = newnor;
1081                                                 }
1082                                                 else {
1083                                                         tnorfac = GPU_uniform(&norfac);
1084         
1085                                                         if(GPU_link_changed(stencil))
1086                                                                 GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac);
1087         
1088                                                         GPU_link(mat, "mtex_blend_normal", tnorfac, shi->vn, newnor, &shi->vn);
1089                                                 }
1090                                                 
1091                                         } else if( mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP)) {
1092                                                 /* ntap bumpmap image */
1093                                                 int iBumpSpace;
1094                                                 float hScale = 0.1f; // compatibility adjustment factor for all bumpspace types
1095                                                 float hScaleTex = 13.0f; // factor for scaling texspace bumps
1096                                                 
1097                                                 GPUNodeLink *surf_pos = GPU_builtin(GPU_VIEW_POSITION);
1098                                                 GPUNodeLink *vR1, *vR2;
1099                                                 GPUNodeLink *dBs, *dBt, *fDet;
1100                                                 
1101                                                 if( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
1102                                                         hScale = hScaleTex;
1103                                                 norfac = hScale * mtex->norfac;
1104                                                 tnorfac = GPU_uniform(&norfac);
1105                                                 
1106                                                 if(GPU_link_changed(stencil))
1107                                                         GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac);
1108                                                 
1109                                                 if( !init_done ) {
1110                                                         // copy shi->vn to vNorg and vNacc, set magnitude to 1
1111                                                         GPU_link(mat, "mtex_bump_normals_init", shi->vn, &vNorg, &vNacc, &fPrevMagnitude);
1112                                                         iBumpSpacePrev = 0;
1113                                                         init_done = 1;
1114                                                 }
1115                                                 
1116                                                 // find current bump space
1117                                                 if( mtex->texflag & MTEX_BUMP_OBJECTSPACE )
1118                                                         iBumpSpace = 1;
1119                                                 else if( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
1120                                                         iBumpSpace = 2;
1121                                                 else
1122                                                         iBumpSpace = 4; // ViewSpace
1123                                                 
1124                                                 // re-initialize if bump space changed
1125                                                 if( iBumpSpacePrev != iBumpSpace ) {
1126                                                         
1127                                                         if( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) 
1128                                                                 GPU_link( mat, "mtex_bump_init_objspace",
1129                                                                                   surf_pos, vNorg, 
1130                                                                           GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_OBJECT_MATRIX),  GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), 
1131                                                                           fPrevMagnitude, vNacc,
1132                                                                                   &fPrevMagnitude, &vNacc, 
1133                                                                           &vR1, &vR2, &fDet );
1134                                                                 
1135                                                         else if( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
1136                                                                 GPU_link( mat, "mtex_bump_init_texturespace",
1137                                                                                   surf_pos, vNorg, 
1138                                                                           fPrevMagnitude, vNacc,
1139                                                                                   &fPrevMagnitude, &vNacc, 
1140                                                                           &vR1, &vR2, &fDet );
1141                                                                 
1142                                                         else
1143                                                                 GPU_link( mat, "mtex_bump_init_viewspace",
1144                                                                                   surf_pos, vNorg, 
1145                                                                           fPrevMagnitude, vNacc,
1146                                                                                   &fPrevMagnitude, &vNacc, 
1147                                                                           &vR1, &vR2, &fDet );
1148                                                         
1149                                                         iBumpSpacePrev = iBumpSpace;
1150                                                 }
1151                                                 
1152                                                 
1153                                                 if( mtex->texflag & MTEX_3TAP_BUMP )
1154                                                         GPU_link( mat, "mtex_bump_tap3", 
1155                                                                   texco, GPU_image(tex->ima, &tex->iuser), tnorfac,
1156                                                                   &dBs, &dBt );
1157                                                 else
1158                                                         GPU_link( mat, "mtex_bump_tap5", 
1159                                                                   texco, GPU_image(tex->ima, &tex->iuser), tnorfac,
1160                                                                   &dBs, &dBt );
1161                                                 
1162                                                 
1163                                                 if( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) {
1164                                                         float ima_x= 512.0f, ima_y= 512.f;              // prevent calling textureSize, glsl 1.3 only
1165                                                         ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, &tex->iuser);
1166                                                         if(ibuf) {
1167                                                                 ima_x= ibuf->x;
1168                                                                 ima_y= ibuf->y;
1169                                                         }
1170                                                         
1171                                                         GPU_link( mat, "mtex_bump_apply_texspace",
1172                                                                   fDet, dBs, dBt, vR1, vR2, 
1173                                                                   GPU_image(tex->ima, &tex->iuser), texco, GPU_uniform(&ima_x), GPU_uniform(&ima_y), vNacc,
1174                                                                   &vNacc, &shi->vn );
1175                                                 } else
1176                                                         GPU_link( mat, "mtex_bump_apply",
1177                                                                   fDet, dBs, dBt, vR1, vR2, vNacc,
1178                                                                   &vNacc, &shi->vn );
1179                                                 
1180                                         }
1181                                 }
1182                                 
1183                                 GPU_link(mat, "vec_math_negate", shi->vn, &orn);
1184                         }
1185
1186                         if((mtex->mapto & MAP_VARS)) {
1187                                 if(rgbnor & TEX_RGB) {
1188                                         if(talpha)
1189                                                 GPU_link(mat, "mtex_alpha_from_col", trgb, &tin);
1190                                         else
1191                                                 GPU_link(mat, "mtex_rgbtoint", trgb, &tin);
1192                                 }
1193
1194                                 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_REF) {
1195                                         GPUNodeLink *difffac;
1196
1197                                         if(mtex->difffac == 1.0f) difffac = stencil;
1198                                         else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->difffac), stencil, &difffac);
1199
1200                                         texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->refl, tin, difffac, mtex->blendtype, &shi->refl);
1201                                         GPU_link(mat, "mtex_value_clamp_positive", shi->refl, &shi->refl);
1202                                 }
1203                                 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_SPEC) {
1204                                         GPUNodeLink *specfac;
1205
1206                                         if(mtex->specfac == 1.0f) specfac = stencil;
1207                                         else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->specfac), stencil, &specfac);
1208
1209                                         texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->spec, tin, specfac, mtex->blendtype, &shi->spec);
1210                                         GPU_link(mat, "mtex_value_clamp_positive", shi->spec, &shi->spec);
1211                                 }
1212                                 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_EMIT) {
1213                                         GPUNodeLink *emitfac;
1214
1215                                         if(mtex->emitfac == 1.0f) emitfac = stencil;
1216                                         else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->emitfac), stencil, &emitfac);
1217
1218                                         texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->emit, tin, emitfac, mtex->blendtype, &shi->emit);
1219                                         GPU_link(mat, "mtex_value_clamp_positive", shi->emit, &shi->emit);
1220                                 }
1221                                 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_HAR) {
1222                                         GPUNodeLink *hardfac;
1223
1224                                         if(mtex->hardfac == 1.0f) hardfac = stencil;
1225                                         else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->hardfac), stencil, &hardfac);
1226
1227                                         GPU_link(mat, "mtex_har_divide", shi->har, &shi->har);
1228                                         texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->har, tin, hardfac, mtex->blendtype, &shi->har);
1229                                         GPU_link(mat, "mtex_har_multiply_clamp", shi->har, &shi->har);
1230                                 }
1231                                 if(mtex->mapto & MAP_ALPHA) {
1232                                         GPUNodeLink *alphafac;
1233
1234                                         if(mtex->alphafac == 1.0f) alphafac = stencil;
1235                                         else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->alphafac), stencil, &alphafac);
1236
1237                                         texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->alpha, tin, alphafac, mtex->blendtype, &shi->alpha);
1238                                         GPU_link(mat, "mtex_value_clamp", shi->alpha, &shi->alpha);
1239                                 }
1240                                 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_AMB) {
1241                                         GPUNodeLink *ambfac;
1242
1243                                         if(mtex->ambfac == 1.0f) ambfac = stencil;
1244                                         else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->ambfac), stencil, &ambfac);
1245
1246                                         texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->amb, tin, ambfac, mtex->blendtype, &shi->amb);
1247                                         GPU_link(mat, "mtex_value_clamp", shi->amb, &shi->amb);
1248                                 }
1249                         }
1250                 }
1251         }
1252 }
1253
1254 void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi)
1255 {
1256         float hard = ma->har;
1257
1258         memset(shi, 0, sizeof(*shi));
1259
1260         shi->gpumat = mat;
1261         shi->mat = ma;
1262
1263         GPU_link(mat, "set_rgb", GPU_uniform(&ma->r), &shi->rgb);
1264         GPU_link(mat, "set_rgb", GPU_uniform(&ma->specr), &shi->specrgb);
1265         GPU_link(mat, "shade_norm", GPU_builtin(GPU_VIEW_NORMAL), &shi->vn);
1266         GPU_link(mat, "set_value", GPU_uniform(&ma->alpha), &shi->alpha);
1267         GPU_link(mat, "set_value", GPU_uniform(&ma->ref), &shi->refl);
1268         GPU_link(mat, "set_value", GPU_uniform(&ma->spec), &shi->spec);
1269         GPU_link(mat, "set_value", GPU_uniform(&ma->emit), &shi->emit);
1270         GPU_link(mat, "set_value", GPU_uniform(&hard), &shi->har);
1271         GPU_link(mat, "set_value", GPU_uniform(&ma->amb), &shi->amb);
1272         GPU_link(mat, "shade_view", GPU_builtin(GPU_VIEW_POSITION), &shi->view);
1273         GPU_link(mat, "vcol_attribute", GPU_attribute(CD_MCOL, ""), &shi->vcol);
1274         if(gpu_do_color_management(mat))
1275                 GPU_link(mat, "srgb_to_linearrgb", shi->vcol, &shi->vcol);
1276         GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref);
1277 }
1278
1279 void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
1280 {
1281         GPUMaterial *mat= shi->gpumat;
1282         GPUNodeLink *emit, *ulinfac, *ulogfac, *mistfac;
1283         Material *ma= shi->mat;
1284         World *world= mat->scene->world;
1285         float linfac, logfac, misttype;
1286
1287         memset(shr, 0, sizeof(*shr));
1288
1289         if(ma->mode & MA_VERTEXCOLP)
1290                 shi->rgb = shi->vcol;
1291
1292         do_material_tex(shi);
1293
1294         if((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP))
1295                 GPU_material_enable_alpha(mat);
1296
1297         if((mat->scene->gm.flag & GAME_GLSL_NO_LIGHTS) || (ma->mode & MA_SHLESS)) {
1298                 shr->combined = shi->rgb;
1299                 shr->alpha = shi->alpha;
1300                 GPU_link(mat, "set_rgb", shi->rgb, &shr->diff);
1301                 GPU_link(mat, "set_rgb_zero", &shr->spec);
1302         }
1303         else {
1304                 if(GPU_link_changed(shi->emit) || ma->emit != 0.0f) {
1305                         if((ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL) {
1306                                 GPU_link(mat, "shade_add", shi->emit, shi->vcol, &emit);
1307                                 GPU_link(mat, "shade_mul", emit, shi->rgb, &shr->diff);
1308                         }
1309                         else
1310                                 GPU_link(mat, "shade_mul_value", shi->emit, shi->rgb, &shr->diff);
1311                 }
1312                 else
1313                         GPU_link(mat, "set_rgb_zero", &shr->diff);
1314
1315                 GPU_link(mat, "set_rgb_zero", &shr->spec);
1316
1317                 material_lights(shi, shr);
1318
1319                 shr->combined = shr->diff;
1320                 shr->alpha = shi->alpha;
1321
1322                 if(world) {
1323                         /* exposure correction */
1324                         if(world->exp!=0.0f || world->range!=1.0f) {
1325                                 linfac= 1.0 + pow((2.0*world->exp + 0.5), -10);
1326                                 logfac= log((linfac-1.0f)/linfac)/world->range;
1327
1328                                 GPU_link(mat, "set_value", GPU_uniform(&linfac), &ulinfac);
1329                                 GPU_link(mat, "set_value", GPU_uniform(&logfac), &ulogfac);
1330
1331                                 GPU_link(mat, "shade_exposure_correct", shr->combined,
1332                                         ulinfac, ulogfac, &shr->combined);
1333                                 GPU_link(mat, "shade_exposure_correct", shr->spec,
1334                                         ulinfac, ulogfac, &shr->spec);
1335                         }
1336
1337                         /* ambient color */
1338                         if(world->ambr!=0.0f || world->ambg!=0.0f || world->ambb!=0.0f) {
1339                                 if(GPU_link_changed(shi->amb) || ma->amb != 0.0f)
1340                                         GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb),
1341                                                 GPU_uniform(&world->ambr), &shr->combined);
1342                         }
1343                 }
1344
1345                 if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shi, &shr->combined);
1346                 if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(shi, &shr->spec);
1347
1348                 if(GPU_link_changed(shi->spec) || ma->spec != 0.0f)
1349                         GPU_link(mat, "shade_add", shr->combined, shr->spec, &shr->combined);
1350         }
1351
1352         GPU_link(mat, "mtex_alpha_to_col", shr->combined, shr->alpha, &shr->combined);
1353
1354         if(ma->shade_flag & MA_OBCOLOR)
1355                 GPU_link(mat, "shade_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined);
1356
1357         if(world && (world->mode & WO_MIST) && !(ma->mode & MA_NOMIST)) {
1358                 misttype = world->mistype;
1359
1360                 GPU_link(mat, "shade_mist_factor", GPU_builtin(GPU_VIEW_POSITION),
1361                         GPU_uniform(&world->miststa), GPU_uniform(&world->mistdist),
1362                         GPU_uniform(&misttype), GPU_uniform(&world->misi), &mistfac);
1363
1364                 GPU_link(mat, "mix_blend", mistfac, shr->combined,
1365                         GPU_uniform(&world->horr), &shr->combined);
1366         }
1367
1368         if(!((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP))) {
1369                 if(world && (GPU_link_changed(shr->alpha) || ma->alpha != 1.0f))
1370                         GPU_link(mat, "shade_world_mix", GPU_uniform(&world->horr),
1371                                 shr->combined, &shr->combined);
1372
1373                 GPU_link(mat, "shade_alpha_opaque", shr->combined, &shr->combined);
1374         }
1375
1376         if(ma->shade_flag & MA_OBCOLOR) {
1377                 mat->obcolalpha = 1;
1378                 GPU_link(mat, "shade_alpha_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined);
1379         }
1380
1381         if(gpu_do_color_management(mat))
1382                 GPU_link(mat, "linearrgb_to_srgb", shr->combined, &shr->combined);
1383 }
1384
1385 static GPUNodeLink *GPU_blender_material(GPUMaterial *mat, Material *ma)
1386 {
1387         GPUShadeInput shi;
1388         GPUShadeResult shr;
1389
1390         GPU_shadeinput_set(mat, ma, &shi);
1391         GPU_shaderesult_set(&shi, &shr);
1392
1393         return shr.combined;
1394 }
1395
1396 GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, int drawtype)
1397 {
1398         GPUMaterial *mat;
1399         GPUNodeLink *outlink;
1400         LinkData *link;
1401
1402         /* find an existing glsl shader that is already compiled */
1403         for(link=ma->gpumaterial.first; link; link=link->next) {
1404                 mat= (GPUMaterial*)link->data;
1405                 if(mat->scene == scene && mat->drawtype == drawtype)
1406                         return link->data;
1407         }
1408
1409         /* in texture draw mode, we need an active texture node */
1410         if(drawtype == OB_TEXTURE && (!ma->use_nodes || !nodeGetActiveTexture(ma->nodetree)))
1411                 return NULL;
1412
1413         /* allocate material */
1414         mat = GPU_material_construct_begin(ma);
1415         mat->scene = scene;
1416         mat->drawtype = drawtype;
1417
1418         if(!(scene->gm.flag & GAME_GLSL_NO_NODES) && ma->nodetree && ma->use_nodes) {
1419                 /* create nodes */
1420                 ntreeGPUMaterialNodes(ma->nodetree, mat);
1421         }
1422         else {
1423                 /* create material */
1424                 outlink = GPU_blender_material(mat, ma);
1425                 GPU_material_output_link(mat, outlink);
1426         }
1427
1428         GPU_material_construct_end(mat);
1429
1430         /* note that even if building the shader fails in some way, we still keep
1431            it to avoid trying to compile again and again, and simple do not use
1432            the actual shader on drawing */
1433
1434         link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
1435         link->data = mat;
1436         BLI_addtail(&ma->gpumaterial, link);
1437
1438         return mat;
1439 }
1440
1441 void GPU_materials_free(void)
1442 {
1443         Object *ob;
1444         Material *ma;
1445         extern Material defmaterial;
1446
1447         for(ma=G.main->mat.first; ma; ma=ma->id.next)
1448                 GPU_material_free(ma);
1449
1450         GPU_material_free(&defmaterial);
1451
1452         for(ob=G.main->object.first; ob; ob=ob->id.next)
1453                 GPU_lamp_free(ob);
1454 }
1455
1456 /* Lamps and shadow buffers */
1457
1458 void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[][4])
1459 {
1460         float mat[4][4];
1461
1462         lamp->lay = lay;
1463         lamp->hide = hide;
1464
1465         copy_m4_m4(mat, obmat);
1466         normalize_m4(mat);
1467
1468         VECCOPY(lamp->vec, mat[2]);
1469         VECCOPY(lamp->co, mat[3]);
1470         copy_m4_m4(lamp->obmat, mat);
1471         invert_m4_m4(lamp->imat, mat);
1472 }
1473
1474 void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
1475 {
1476         lamp->energy = energy;
1477         if(lamp->mode & LA_NEG) lamp->energy= -lamp->energy;
1478
1479         lamp->col[0]= r* lamp->energy;
1480         lamp->col[1]= g* lamp->energy;
1481         lamp->col[2]= b* lamp->energy;
1482 }
1483
1484 static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
1485 {
1486         float temp, angle, pixsize, wsize;
1487
1488         lamp->scene = scene;
1489         lamp->ob = ob;
1490         lamp->par = par;
1491         lamp->la = la;
1492
1493         /* add_render_lamp */
1494         lamp->mode = la->mode;
1495         lamp->type = la->type;
1496
1497         lamp->energy = la->energy;
1498         if(lamp->mode & LA_NEG) lamp->energy= -lamp->energy;
1499
1500         lamp->col[0]= la->r*lamp->energy;
1501         lamp->col[1]= la->g*lamp->energy;
1502         lamp->col[2]= la->b*lamp->energy;
1503
1504         GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat);
1505
1506         lamp->spotsi= la->spotsize;
1507         if(lamp->mode & LA_HALO)
1508                 if(lamp->spotsi > 170.0f)
1509                         lamp->spotsi = 170.0f;
1510         lamp->spotsi= cos(M_PI*lamp->spotsi/360.0);
1511         lamp->spotbl= (1.0f - lamp->spotsi)*la->spotblend;
1512         lamp->k= la->k;
1513
1514         lamp->dist= la->dist;
1515         lamp->falloff_type= la->falloff_type;
1516         lamp->att1= la->att1;
1517         lamp->att2= la->att2;
1518         lamp->curfalloff= la->curfalloff;
1519
1520         /* initshadowbuf */
1521         lamp->bias = 0.02f*la->bias;
1522         lamp->size = la->bufsize;
1523         lamp->d= la->clipsta;
1524         lamp->clipend= la->clipend;
1525
1526         /* arbitrary correction for the fact we do no soft transition */
1527         lamp->bias *= 0.25f;
1528
1529         /* makeshadowbuf */
1530         angle= saacos(lamp->spotsi);
1531         temp= 0.5f*lamp->size*cos(angle)/sin(angle);
1532         pixsize= (lamp->d)/temp;
1533         wsize= pixsize*0.5f*lamp->size;
1534                 
1535         perspective_m4( lamp->winmat,-wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
1536 }
1537
1538 static void gpu_lamp_shadow_free(GPULamp *lamp)
1539 {
1540         if(lamp->tex) {
1541                 GPU_texture_free(lamp->tex);
1542                 lamp->tex= NULL;
1543         }
1544         if(lamp->fb) {
1545                 GPU_framebuffer_free(lamp->fb);
1546                 lamp->fb= NULL;
1547         }
1548 }
1549
1550 GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
1551 {
1552         Lamp *la;
1553         GPULamp *lamp;
1554         LinkData *link;
1555
1556         for(link=ob->gpulamp.first; link; link=link->next) {
1557                 lamp = (GPULamp*)link->data;
1558
1559                 if(lamp->par == par && lamp->scene == scene)
1560                         return link->data;
1561         }
1562
1563         lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
1564
1565         link = MEM_callocN(sizeof(LinkData), "GPULampLink");
1566         link->data = lamp;
1567         BLI_addtail(&ob->gpulamp, link);
1568
1569         la = ob->data;
1570         gpu_lamp_from_blender(scene, ob, par, la, lamp);
1571
1572         if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF)) {
1573                 /* opengl */
1574                 lamp->fb = GPU_framebuffer_create();
1575                 if(!lamp->fb) {
1576                         gpu_lamp_shadow_free(lamp);
1577                         return lamp;
1578                 }
1579
1580                 lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
1581                 if(!lamp->tex) {
1582                         gpu_lamp_shadow_free(lamp);
1583                         return lamp;
1584                 }
1585
1586                 if(!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, NULL)) {
1587                         gpu_lamp_shadow_free(lamp);
1588                         return lamp;
1589                 }
1590
1591                 GPU_framebuffer_restore();
1592         }
1593
1594         return lamp;
1595 }
1596
1597 void GPU_lamp_free(Object *ob)
1598 {
1599         GPULamp *lamp;
1600         LinkData *link;
1601         LinkData *nlink;
1602         Material *ma;
1603
1604         for(link=ob->gpulamp.first; link; link=link->next) {
1605                 lamp = link->data;
1606
1607                 while(lamp->materials.first) {
1608                         nlink = lamp->materials.first;
1609                         ma = nlink->data;
1610                         BLI_freelinkN(&lamp->materials, nlink);
1611
1612                         if(ma->gpumaterial.first)
1613                                 GPU_material_free(ma);
1614                 }
1615
1616                 gpu_lamp_shadow_free(lamp);
1617
1618                 MEM_freeN(lamp);
1619         }
1620
1621         BLI_freelistN(&ob->gpulamp);
1622 }
1623
1624 int GPU_lamp_has_shadow_buffer(GPULamp *lamp)
1625 {
1626         return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) &&
1627                         !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) &&
1628                         lamp->tex && lamp->fb);
1629 }
1630
1631 void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[][4], int *winsize, float winmat[][4])
1632 {
1633         float rangemat[4][4], persmat[4][4];
1634
1635         /* initshadowbuf */
1636         invert_m4_m4(lamp->viewmat, lamp->obmat);
1637         normalize_v3(lamp->viewmat[0]);
1638         normalize_v3(lamp->viewmat[1]);
1639         normalize_v3(lamp->viewmat[2]);
1640
1641         /* makeshadowbuf */
1642         mul_m4_m4m4(persmat, lamp->viewmat, lamp->winmat);
1643
1644         /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */
1645         unit_m4(rangemat);
1646         rangemat[0][0] = 0.5f;
1647         rangemat[1][1] = 0.5f;
1648         rangemat[2][2] = 0.5f;
1649         rangemat[3][0] = 0.5f;
1650         rangemat[3][1] = 0.5f;
1651         rangemat[3][2] = 0.5f;
1652
1653         mul_m4_m4m4(lamp->persmat, persmat, rangemat);
1654
1655         /* opengl */
1656         glDisable(GL_SCISSOR_TEST);
1657         GPU_framebuffer_texture_bind(lamp->fb, lamp->tex);
1658
1659         /* set matrices */
1660         copy_m4_m4(viewmat, lamp->viewmat);
1661         copy_m4_m4(winmat, lamp->winmat);
1662         *winsize = lamp->size;
1663 }
1664
1665 void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
1666 {
1667         GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
1668         GPU_framebuffer_restore();
1669         glEnable(GL_SCISSOR_TEST);
1670 }
1671
1672 int GPU_lamp_shadow_layer(GPULamp *lamp)
1673 {
1674         if(lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER|LA_LAYER_SHADOW)))
1675                 return lamp->lay;
1676         else
1677                 return -1;
1678 }
1679