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