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