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