2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2006 Blender Foundation.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): Brecht Van Lommel.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/gpu/intern/gpu_material.c
38 #include "MEM_guardedalloc.h"
40 #include "DNA_lamp_types.h"
41 #include "DNA_material_types.h"
42 #include "DNA_object_types.h"
43 #include "DNA_scene_types.h"
44 #include "DNA_world_types.h"
47 #include "BLI_blenlib.h"
48 #include "BLI_utildefines.h"
51 #include "BKE_colortools.h"
52 #include "BKE_DerivedMesh.h"
53 #include "BKE_global.h"
54 #include "BKE_image.h"
57 #include "BKE_scene.h"
58 #include "BKE_texture.h"
60 #include "IMB_imbuf_types.h"
62 #include "GPU_extensions.h"
63 #include "GPU_material.h"
65 #include "gpu_codegen.h"
71 typedef enum DynMatProperty {
82 /* for creating the material */
86 /* for binding the material */
88 GPUVertexAttribs attribs;
91 int alpha, obcolalpha;
94 /* for passing uniforms */
95 int viewmatloc, invviewmatloc;
96 int obmatloc, invobmatloc;
97 int obcolloc, obautobumpscaleloc;
108 int type, mode, lay, hide;
110 float dynenergy, dyncol[3];
111 float energy, col[3];
114 float dynco[3], dynvec[3];
119 float spotsi, spotbl, k;
120 float dist, att1, att2;
122 float bias, d, clipend;
126 struct CurveMapping *curfalloff;
131 float dynpersmat[4][4];
141 static GPUMaterial *GPU_material_construct_begin(Material *ma)
143 GPUMaterial *material = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");
150 static void gpu_material_set_attrib_id(GPUMaterial *material)
152 GPUVertexAttribs *attribs;
158 attribs= &material->attribs;
159 pass= material->pass;
161 attribs->totlayer = 0;
165 shader= GPU_pass_shader(pass);
167 attribs->totlayer = 0;
171 /* convert from attribute number to the actual id assigned by opengl,
172 * in case the attrib does not get a valid index back, it was probably
173 * removed by the glsl compiler by dead code elimination */
175 for(a=0, b=0; a<attribs->totlayer; a++) {
176 sprintf(name, "att%d", attribs->layer[a].attribid);
177 attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name);
179 if(attribs->layer[a].glindex >= 0) {
180 attribs->layer[b] = attribs->layer[a];
185 attribs->totlayer = b;
188 static int GPU_material_construct_end(GPUMaterial *material)
190 if (material->outlink) {
191 GPUNodeLink *outlink;
194 outlink = material->outlink;
195 material->pass = GPU_generate_pass(&material->nodes, outlink,
196 &material->attribs, &material->builtins, material->ma->id.name);
201 gpu_material_set_attrib_id(material);
203 shader = GPU_pass_shader(material->pass);
205 if(material->builtins & GPU_VIEW_MATRIX)
206 material->viewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_VIEW_MATRIX));
207 if(material->builtins & GPU_INVERSE_VIEW_MATRIX)
208 material->invviewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_VIEW_MATRIX));
209 if(material->builtins & GPU_OBJECT_MATRIX)
210 material->obmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBJECT_MATRIX));
211 if(material->builtins & GPU_INVERSE_OBJECT_MATRIX)
212 material->invobmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_OBJECT_MATRIX));
213 if(material->builtins & GPU_OBCOLOR)
214 material->obcolloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBCOLOR));
215 if(material->builtins & GPU_AUTO_BUMPSCALE)
216 material->obautobumpscaleloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_AUTO_BUMPSCALE));
223 void GPU_material_free(Material *ma)
226 LinkData *nlink, *mlink, *next;
228 for(link=ma->gpumaterial.first; link; link=link->next) {
229 GPUMaterial *material = link->data;
232 GPU_pass_free(material->pass);
234 for(nlink=material->lamps.first; nlink; nlink=nlink->next) {
235 GPULamp *lamp = nlink->data;
237 for(mlink=lamp->materials.first; mlink; mlink=next) {
239 if(mlink->data == ma)
240 BLI_freelinkN(&lamp->materials, mlink);
244 BLI_freelistN(&material->lamps);
249 BLI_freelistN(&ma->gpumaterial);
252 void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap)
258 /* handle layer lamps */
259 for(nlink=material->lamps.first; nlink; nlink=nlink->next) {
262 if(!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))) {
263 lamp->dynenergy = lamp->energy;
264 copy_v3_v3(lamp->dyncol, lamp->col);
267 lamp->dynenergy = 0.0f;
268 lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f;
272 GPU_pass_bind(material->pass, time, mipmap);
277 void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4], float autobumpscale)
280 GPUShader *shader = GPU_pass_shader(material->pass);
283 float invmat[4][4], col[4];
285 /* handle builtins */
286 if(material->builtins & GPU_VIEW_MATRIX) {
287 GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float*)viewmat);
289 if(material->builtins & GPU_INVERSE_VIEW_MATRIX) {
290 GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv);
292 if(material->builtins & GPU_OBJECT_MATRIX) {
293 GPU_shader_uniform_vector(shader, material->obmatloc, 16, 1, (float*)obmat);
295 if(material->builtins & GPU_INVERSE_OBJECT_MATRIX) {
296 invert_m4_m4(invmat, obmat);
297 GPU_shader_uniform_vector(shader, material->invobmatloc, 16, 1, (float*)invmat);
299 if(material->builtins & GPU_OBCOLOR) {
300 copy_v4_v4(col, obcol);
301 CLAMP(col[3], 0.0f, 1.0f);
302 GPU_shader_uniform_vector(shader, material->obcolloc, 4, 1, col);
304 if(material->builtins & GPU_AUTO_BUMPSCALE) {
305 GPU_shader_uniform_vector(shader, material->obautobumpscaleloc, 1, 1, &autobumpscale);
308 for(nlink=material->lamps.first; nlink; nlink=nlink->next) {
311 if(material->dynproperty & DYN_LAMP_VEC) {
312 copy_v3_v3(lamp->dynvec, lamp->vec);
313 normalize_v3(lamp->dynvec);
314 negate_v3(lamp->dynvec);
315 mul_mat3_m4_v3(viewmat, lamp->dynvec);
318 if(material->dynproperty & DYN_LAMP_CO) {
319 copy_v3_v3(lamp->dynco, lamp->co);
320 mul_m4_v3(viewmat, lamp->dynco);
323 if(material->dynproperty & DYN_LAMP_IMAT)
324 mul_m4_m4m4(lamp->dynimat, viewinv, lamp->imat);
325 if(material->dynproperty & DYN_LAMP_PERSMAT)
326 mul_m4_m4m4(lamp->dynpersmat, viewinv, lamp->persmat);
329 GPU_pass_update_uniforms(material->pass);
333 void GPU_material_unbind(GPUMaterial *material)
335 if (material->pass) {
337 GPU_pass_unbind(material->pass);
341 int GPU_material_bound(GPUMaterial *material)
343 return material->bound;
346 void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
348 *attribs = material->attribs;
351 void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
353 if(!material->outlink)
354 material->outlink= link;
357 void GPU_material_enable_alpha(GPUMaterial *material)
362 GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4])
364 if(material->alpha || (material->obcolalpha && obcol[3] < 1.0f))
365 return GPU_BLEND_ALPHA;
367 return GPU_BLEND_SOLID;
370 void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
372 BLI_addtail(&material->nodes, node);
375 /* Code generation */
377 static int gpu_do_color_management(GPUMaterial *mat)
379 return ((mat->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) &&
380 !((mat->scene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT)));
383 static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **lv, GPUNodeLink **dist)
385 GPUNodeLink *visifac, *inpr;
387 /* from get_lamp_visibility */
388 if(lamp->type==LA_SUN || lamp->type==LA_HEMI) {
389 mat->dynproperty |= DYN_LAMP_VEC;
390 GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), lv, dist, &visifac);
394 mat->dynproperty |= DYN_LAMP_CO;
395 GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), lv, dist, &visifac);
397 if(lamp->type==LA_AREA)
400 switch(lamp->falloff_type)
402 case LA_FALLOFF_CONSTANT:
404 case LA_FALLOFF_INVLINEAR:
405 GPU_link(mat, "lamp_falloff_invlinear", GPU_uniform(&lamp->dist), *dist, &visifac);
407 case LA_FALLOFF_INVSQUARE:
408 GPU_link(mat, "lamp_falloff_invsquare", GPU_uniform(&lamp->dist), *dist, &visifac);
410 case LA_FALLOFF_SLIDERS:
411 GPU_link(mat, "lamp_falloff_sliders", GPU_uniform(&lamp->dist), GPU_uniform(&lamp->att1), GPU_uniform(&lamp->att2), *dist, &visifac);
413 case LA_FALLOFF_CURVE:
418 curvemapping_table_RGBA(lamp->curfalloff, &array, &size);
419 GPU_link(mat, "lamp_falloff_curve", GPU_uniform(&lamp->dist), GPU_texture(size, array), *dist, &visifac);
424 if(lamp->mode & LA_SPHERE)
425 GPU_link(mat, "lamp_visibility_sphere", GPU_uniform(&lamp->dist), *dist, visifac, &visifac);
427 if(lamp->type == LA_SPOT) {
428 if(lamp->mode & LA_SQUARE) {
429 mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_IMAT;
430 GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), GPU_dynamic_uniform((float*)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob), *lv, &inpr);
433 mat->dynproperty |= DYN_LAMP_VEC;
434 GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), *lv, &inpr);
437 GPU_link(mat, "lamp_visibility_spot", GPU_uniform(&lamp->spotsi), GPU_uniform(&lamp->spotbl), inpr, visifac, &visifac);
440 GPU_link(mat, "lamp_visibility_clamp", visifac, &visifac);
447 static void area_lamp_vectors(LampRen *lar)
449 float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac;
451 /* make it smaller, so area light can be multisampled */
452 multifac= 1.0f/sqrt((float)lar->ray_totsamp);
457 lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
458 lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
459 lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2];
462 lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
463 lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
464 lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2];
467 lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
468 lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
469 lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2];
472 lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
473 lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
474 lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2];
475 /* only for correction button size, matrix size works on energy */
476 lar->areasize= lar->dist*lar->dist/(4.0*xsize*ysize);
480 static void ramp_blend(GPUMaterial *mat, GPUNodeLink *fac, GPUNodeLink *col1, GPUNodeLink *col2, int type, GPUNodeLink **outcol)
482 static const char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub",
483 "mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light",
484 "mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat",
485 "mix_val", "mix_color", "mix_soft", "mix_linear"};
487 GPU_link(mat, names[type], fac, col1, col2, outcol);
490 static void do_colorband_blend(GPUMaterial *mat, ColorBand *coba, GPUNodeLink *fac, float rampfac, int type, GPUNodeLink *incol, GPUNodeLink **outcol)
492 GPUNodeLink *tmp, *alpha, *col;
497 colorband_table_RGBA(coba, &array, &size);
498 GPU_link(mat, "valtorgb", fac, GPU_texture(size, array), &col, &tmp);
500 /* use alpha in fac */
501 GPU_link(mat, "mtex_alpha_from_col", col, &alpha);
502 GPU_link(mat, "math_multiply", alpha, GPU_uniform(&rampfac), &fac);
504 /* blending method */
505 ramp_blend(mat, fac, incol, col, type, outcol);
508 static void ramp_diffuse_result(GPUShadeInput *shi, GPUNodeLink **diff)
510 Material *ma= shi->mat;
511 GPUMaterial *mat= shi->gpumat;
514 if(!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS)) {
516 if(ma->rampin_col==MA_RAMP_IN_RESULT) {
517 GPU_link(mat, "ramp_rgbtobw", *diff, &fac);
519 /* colorband + blend */
520 do_colorband_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, *diff, diff);
526 static void add_to_diffuse(GPUMaterial *mat, Material *ma, GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *rgb, GPUNodeLink **diff)
528 GPUNodeLink *fac, *tmp, *addcol;
530 if(!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS) &&
531 ma->ramp_col && (ma->mode & MA_RAMP_COL)) {
532 /* MA_RAMP_IN_RESULT is exceptional */
533 if(ma->rampin_col==MA_RAMP_IN_RESULT) {
538 switch(ma->rampin_col) {
539 case MA_RAMP_IN_ENERGY:
540 GPU_link(mat, "ramp_rgbtobw", rgb, &fac);
542 case MA_RAMP_IN_SHADER:
546 GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
549 GPU_link(mat, "set_value_zero", &fac);
553 /* colorband + blend */
554 do_colorband_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, shi->rgb, &addcol);
561 GPU_link(mat, "shade_madd_clamped", *diff, rgb, addcol, diff);
564 static void ramp_spec_result(GPUShadeInput *shi, GPUNodeLink **spec)
566 Material *ma= shi->mat;
567 GPUMaterial *mat= shi->gpumat;
570 if(!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS) &&
571 ma->ramp_spec && ma->rampin_spec==MA_RAMP_IN_RESULT) {
572 GPU_link(mat, "ramp_rgbtobw", *spec, &fac);
574 /* colorband + blend */
575 do_colorband_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec);
579 static void do_specular_ramp(GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *t, GPUNodeLink **spec)
581 Material *ma= shi->mat;
582 GPUMaterial *mat= shi->gpumat;
583 GPUNodeLink *fac, *tmp;
585 *spec = shi->specrgb;
587 /* MA_RAMP_IN_RESULT is exception */
588 if(ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) {
591 switch(ma->rampin_spec) {
592 case MA_RAMP_IN_ENERGY:
595 case MA_RAMP_IN_SHADER:
599 GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
602 GPU_link(mat, "set_value_zero", &fac);
606 /* colorband + blend */
607 do_colorband_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec);
611 static void add_user_list(ListBase *list, void *data)
613 LinkData *link = MEM_callocN(sizeof(LinkData), "GPULinkData");
615 BLI_addtail(list, link);
618 static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *lamp)
620 Material *ma= shi->mat;
621 GPUMaterial *mat= shi->gpumat;
622 GPUNodeLink *lv, *dist, *visifac, *is, *inp, *i, *vn, *view;
623 GPUNodeLink *outcol, *specfac, *t, *shadfac= NULL;
626 if((lamp->mode & LA_ONLYSHADOW) && !(ma->mode & MA_SHADOW))
632 visifac= lamp_get_visibility(mat, lamp, &lv, &dist);
634 /*if(ma->mode & MA_TANGENT_V)
635 GPU_link(mat, "shade_tangent_v", lv, GPU_attribute(CD_TANGENT, ""), &vn);*/
637 GPU_link(mat, "shade_inp", vn, lv, &inp);
639 if(lamp->mode & LA_NO_DIFF) {
640 GPU_link(mat, "shade_is_no_diffuse", &is);
642 else if(lamp->type == LA_HEMI) {
643 GPU_link(mat, "shade_is_hemi", inp, &is);
646 if(lamp->type == LA_AREA) {
647 float area[4][4]= {{0.0f}}, areasize= 0.0f;
649 mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_CO;
650 GPU_link(mat, "shade_inp_area", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), vn, GPU_uniform((float*)area),
651 GPU_uniform(&areasize), GPU_uniform(&lamp->k), &inp);
654 is= inp; /* Lambert */
656 if(!(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS)) {
657 if(ma->diff_shader==MA_DIFF_ORENNAYAR)
658 GPU_link(mat, "shade_diffuse_oren_nayer", inp, vn, lv, view, GPU_uniform(&ma->roughness), &is);
659 else if(ma->diff_shader==MA_DIFF_TOON)
660 GPU_link(mat, "shade_diffuse_toon", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is);
661 else if(ma->diff_shader==MA_DIFF_MINNAERT)
662 GPU_link(mat, "shade_diffuse_minnaert", inp, vn, view, GPU_uniform(&ma->darkness), &is);
663 else if(ma->diff_shader==MA_DIFF_FRESNEL)
664 GPU_link(mat, "shade_diffuse_fresnel", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is);
668 if(!(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS))
669 if(ma->shade_flag & MA_CUBIC)
670 GPU_link(mat, "shade_cubic", is, &is);
673 GPU_link(mat, "shade_visifac", i, visifac, shi->refl, &i);
676 /*if(ma->mode & MA_TANGENT_VN)
677 GPU_link(mat, "shade_tangent_v_spec", GPU_attribute(CD_TANGENT, ""), &vn);*/
679 /* this replaces if(i > 0.0) conditional until that is supported */
680 // done in shade_visifac now, GPU_link(mat, "mtex_value_clamp_positive", i, &i);
682 if((ma->mode & MA_SHADOW) && GPU_lamp_has_shadow_buffer(lamp)) {
683 if(!(mat->scene->gm.flag & GAME_GLSL_NO_SHADOWS)) {
684 mat->dynproperty |= DYN_LAMP_PERSMAT;
686 GPU_link(mat, "test_shadowbuf",
687 GPU_builtin(GPU_VIEW_POSITION),
688 GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
689 GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
690 GPU_uniform(&lamp->bias), inp, &shadfac);
692 if(lamp->mode & LA_ONLYSHADOW) {
693 GPU_link(mat, "shade_only_shadow", i, shadfac,
694 GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob), &shadfac);
696 if(!(lamp->mode & LA_NO_DIFF))
697 GPU_link(mat, "shade_only_shadow_diffuse", shadfac, shi->rgb,
698 shr->diff, &shr->diff);
700 if(!(lamp->mode & LA_NO_SPEC))
701 GPU_link(mat, "shade_only_shadow_specular", shadfac, shi->specrgb,
702 shr->spec, &shr->spec);
704 add_user_list(&mat->lamps, lamp);
705 add_user_list(&lamp->materials, shi->gpumat->ma);
709 GPU_link(mat, "math_multiply", i, shadfac, &i);
712 else if((mat->scene->gm.flag & GAME_GLSL_NO_SHADOWS) && (lamp->mode & LA_ONLYSHADOW)) {
713 add_user_list(&mat->lamps, lamp);
714 add_user_list(&lamp->materials, shi->gpumat->ma);
718 GPU_link(mat, "set_value", GPU_uniform(&one), &shadfac);
720 if(GPU_link_changed(shi->refl) || ma->ref != 0.0f) {
721 if(!(lamp->mode & LA_NO_DIFF)) {
723 GPU_link(mat, "shade_mul_value", i, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), &rgb);
724 add_to_diffuse(mat, ma, shi, is, rgb, &shr->diff);
728 if(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS);
729 else if(!(lamp->mode & LA_NO_SPEC) && !(lamp->mode & LA_ONLYSHADOW) &&
730 (GPU_link_changed(shi->spec) || ma->spec != 0.0f)) {
731 if(lamp->type == LA_HEMI) {
732 GPU_link(mat, "shade_hemi_spec", vn, lv, view, GPU_uniform(&ma->spec), shi->har, visifac, &t);
733 GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), shi->specrgb, &outcol);
734 GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
737 if(ma->spec_shader==MA_SPEC_PHONG)
738 GPU_link(mat, "shade_phong_spec", vn, lv, view, shi->har, &specfac);
739 else if(ma->spec_shader==MA_SPEC_COOKTORR)
740 GPU_link(mat, "shade_cooktorr_spec", vn, lv, view, shi->har, &specfac);
741 else if(ma->spec_shader==MA_SPEC_BLINN)
742 GPU_link(mat, "shade_blinn_spec", vn, lv, view, GPU_uniform(&ma->refrac), shi->har, &specfac);
743 else if(ma->spec_shader==MA_SPEC_WARDISO)
744 GPU_link(mat, "shade_wardiso_spec", vn, lv, view, GPU_uniform(&ma->rms), &specfac);
746 GPU_link(mat, "shade_toon_spec", vn, lv, view, GPU_uniform(&ma->param[2]), GPU_uniform(&ma->param[3]), &specfac);
748 if(lamp->type==LA_AREA)
749 GPU_link(mat, "shade_spec_area_inp", specfac, inp, &specfac);
751 GPU_link(mat, "shade_spec_t", shadfac, shi->spec, visifac, specfac, &t);
753 if(ma->mode & MA_RAMP_SPEC) {
755 do_specular_ramp(shi, specfac, t, &spec);
756 GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), spec, &outcol);
757 GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
760 GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), shi->specrgb, &outcol);
761 GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
766 add_user_list(&mat->lamps, lamp);
767 add_user_list(&lamp->materials, shi->gpumat->ma);
770 static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr)
777 for(SETLOOPER(shi->gpumat->scene, sce_iter, base)) {
780 if(ob->type==OB_LAMP) {
781 lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, NULL);
783 shade_one_light(shi, shr, lamp);
786 if (ob->transflag & OB_DUPLI) {
788 ListBase *lb = object_duplilist(shi->gpumat->scene, ob);
790 for(dob=lb->first; dob; dob=dob->next) {
791 Object *ob_iter = dob->ob;
793 if(ob_iter->type==OB_LAMP) {
794 copy_m4_m4(ob_iter->obmat, dob->mat);
796 lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob_iter, ob);
798 shade_one_light(shi, shr, lamp);
802 free_object_duplilist(lb);
807 static void texture_rgb_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg, int blendtype, GPUNodeLink **in)
811 GPU_link(mat, "mtex_rgb_blend", out, tex, fact, facg, in);
814 GPU_link(mat, "mtex_rgb_mul", out, tex, fact, facg, in);
817 GPU_link(mat, "mtex_rgb_screen", out, tex, fact, facg, in);
820 GPU_link(mat, "mtex_rgb_overlay", out, tex, fact, facg, in);
823 GPU_link(mat, "mtex_rgb_sub", out, tex, fact, facg, in);
826 GPU_link(mat, "mtex_rgb_add", out, tex, fact, facg, in);
829 GPU_link(mat, "mtex_rgb_div", out, tex, fact, facg, in);
832 GPU_link(mat, "mtex_rgb_diff", out, tex, fact, facg, in);
835 GPU_link(mat, "mtex_rgb_dark", out, tex, fact, facg, in);
838 GPU_link(mat, "mtex_rgb_light", out, tex, fact, facg, in);
841 GPU_link(mat, "mtex_rgb_hue", out, tex, fact, facg, in);
844 GPU_link(mat, "mtex_rgb_sat", out, tex, fact, facg, in);
847 GPU_link(mat, "mtex_rgb_val", out, tex, fact, facg, in);
849 case MTEX_BLEND_COLOR:
850 GPU_link(mat, "mtex_rgb_color", out, tex, fact, facg, in);
853 GPU_link(mat, "set_rgb_zero", &in);
858 static void texture_value_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg, int blendtype, GPUNodeLink **in)
862 GPU_link(mat, "mtex_value_blend", out, tex, fact, facg, in);
865 GPU_link(mat, "mtex_value_mul", out, tex, fact, facg, in);
868 GPU_link(mat, "mtex_value_screen", out, tex, fact, facg, in);
871 GPU_link(mat, "mtex_value_sub", out, tex, fact, facg, in);
874 GPU_link(mat, "mtex_value_add", out, tex, fact, facg, in);
877 GPU_link(mat, "mtex_value_div", out, tex, fact, facg, in);
880 GPU_link(mat, "mtex_value_diff", out, tex, fact, facg, in);
883 GPU_link(mat, "mtex_value_dark", out, tex, fact, facg, in);
886 GPU_link(mat, "mtex_value_light", out, tex, fact, facg, in);
889 GPU_link(mat, "set_value_zero", &in);
894 static void do_material_tex(GPUShadeInput *shi)
896 Material *ma= shi->mat;
897 GPUMaterial *mat= shi->gpumat;
900 GPUNodeLink *texco, *tin, *trgb, *tnor, *tcol, *stencil, *tnorfac;
901 GPUNodeLink *texco_norm, *texco_orco, *texco_object;
902 GPUNodeLink *texco_global, *texco_uv = NULL;
903 GPUNodeLink *newnor, *orn;
904 /*char *lastuvname = NULL;*/ /*UNUSED*/
905 float one = 1.0f, norfac, ofs[3];
906 int tex_nr, rgbnor, talpha;
907 int init_done = 0, iBumpSpacePrev = 0; /* Not necessary, quiting gcc warning. */
908 GPUNodeLink *vNorg, *vNacc, *fPrevMagnitude;
909 int iFirstTimeNMap=1;
910 int found_deriv_map = 0;
912 GPU_link(mat, "set_value", GPU_uniform(&one), &stencil);
914 GPU_link(mat, "texco_norm", GPU_builtin(GPU_VIEW_NORMAL), &texco_norm);
915 GPU_link(mat, "texco_orco", GPU_attribute(CD_ORCO, ""), &texco_orco);
916 GPU_link(mat, "texco_object", GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
917 GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
918 GPU_builtin(GPU_VIEW_POSITION), &texco_object);
919 //GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent);
920 GPU_link(mat, "texco_global", GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
921 GPU_builtin(GPU_VIEW_POSITION), &texco_global);
925 /* go over texture slots */
926 for(tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
927 /* separate tex switching */
928 if(ma->septex & (1<<tex_nr)) continue;
930 if(ma->mtex[tex_nr]) {
931 mtex= ma->mtex[tex_nr];
934 if(tex == NULL) continue;
937 if(mtex->texco==TEXCO_ORCO)
939 else if(mtex->texco==TEXCO_OBJECT)
941 else if(mtex->texco==TEXCO_NORM)
943 else if(mtex->texco==TEXCO_TANGENT)
945 else if(mtex->texco==TEXCO_GLOB)
947 else if(mtex->texco==TEXCO_REFL) {
948 GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref);
951 else if(mtex->texco==TEXCO_UV) {
952 if(1) { //!(texco_uv && strcmp(mtex->uvname, lastuvname) == 0)) {
953 GPU_link(mat, "texco_uv", GPU_attribute(CD_MTFACE, mtex->uvname), &texco_uv);
954 /*lastuvname = mtex->uvname;*/ /*UNUSED*/
961 /* in case of uv, this would just undo a multiplication in texco_uv */
962 if(mtex->texco != TEXCO_UV)
963 GPU_link(mat, "mtex_2d_mapping", texco, &texco);
965 if(mtex->size[0] != 1.0f || mtex->size[1] != 1.0f || mtex->size[2] != 1.0f)
966 GPU_link(mat, "mtex_mapping_size", texco, GPU_uniform(mtex->size), &texco);
968 ofs[0] = mtex->ofs[0] + 0.5f - 0.5f*mtex->size[0];
969 ofs[1] = mtex->ofs[1] + 0.5f - 0.5f*mtex->size[1];
971 if(ofs[0] != 0.0f || ofs[1] != 0.0f || ofs[2] != 0.0f)
972 GPU_link(mat, "mtex_mapping_ofs", texco, GPU_uniform(ofs), &texco);
977 if(tex && tex->type == TEX_IMAGE && tex->ima) {
978 GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser), &tin, &trgb);
981 if(tex->imaflag & TEX_USEALPHA)
987 if((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
988 GPU_link(mat, "mtex_rgbtoint", trgb, &tin);
992 if(mtex->texflag & MTEX_NEGATIVE) {
994 GPU_link(mat, "mtex_rgb_invert", trgb, &trgb);
996 GPU_link(mat, "mtex_value_invert", tin, &tin);
999 if(mtex->texflag & MTEX_STENCIL) {
1000 if(rgbnor & TEX_RGB)
1001 GPU_link(mat, "mtex_rgb_stencil", stencil, trgb, &stencil, &trgb);
1003 GPU_link(mat, "mtex_value_stencil", stencil, tin, &stencil, &tin);
1007 if(mtex->mapto & (MAP_COL+MAP_COLSPEC)) {
1008 /* stencil maps on the texture control slider, not texture intensity value */
1009 if((rgbnor & TEX_RGB)==0) {
1010 GPU_link(mat, "set_rgb", GPU_uniform(&mtex->r), &tcol);
1013 GPU_link(mat, "set_rgba", trgb, &tcol);
1015 if(mtex->mapto & MAP_ALPHA)
1016 GPU_link(mat, "set_value", stencil, &tin);
1018 GPU_link(mat, "mtex_alpha_from_col", trgb, &tin);
1020 GPU_link(mat, "set_value_one", &tin);
1023 if(tex->type==TEX_IMAGE)
1024 if(gpu_do_color_management(mat))
1025 GPU_link(mat, "srgb_to_linearrgb", tcol, &tcol);
1027 if(mtex->mapto & MAP_COL) {
1028 GPUNodeLink *colfac;
1030 if(mtex->colfac == 1.0f) colfac = stencil;
1031 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->colfac), stencil, &colfac);
1033 texture_rgb_blend(mat, tcol, shi->rgb, tin, colfac, mtex->blendtype, &shi->rgb);
1036 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_COLSPEC)) {
1037 GPUNodeLink *colspecfac;
1039 if(mtex->colspecfac == 1.0f) colspecfac = stencil;
1040 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->colspecfac), stencil, &colspecfac);
1042 texture_rgb_blend(mat, tcol, shi->specrgb, tin, colspecfac, mtex->blendtype, &shi->specrgb);
1046 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_NORM)) {
1047 if(tex->type==TEX_IMAGE) {
1048 found_deriv_map = tex->imaflag & TEX_DERIVATIVEMAP;
1050 if(tex->imaflag & TEX_NORMALMAP) {
1051 /* normalmap image */
1052 GPU_link(mat, "mtex_normal", texco, GPU_image(tex->ima, &tex->iuser), &tnor );
1054 if(mtex->norfac < 0.0f)
1055 GPU_link(mat, "mtex_negate_texnormal", tnor, &tnor);
1057 if(mtex->normapspace == MTEX_NSPACE_TANGENT)
1059 if(iFirstTimeNMap!=0)
1061 // use unnormalized normal (this is how we bake it - closer to gamedev)
1062 GPUNodeLink *vNegNorm;
1063 GPU_link(mat, "vec_math_negate", GPU_builtin(GPU_VIEW_NORMAL), &vNegNorm);
1064 GPU_link(mat, "mtex_nspace_tangent", GPU_attribute(CD_TANGENT, ""), vNegNorm, tnor, &newnor);
1067 else // otherwise use accumulated perturbations
1069 GPU_link(mat, "mtex_nspace_tangent", GPU_attribute(CD_TANGENT, ""), shi->vn, tnor, &newnor);
1075 norfac = MIN2(fabsf(mtex->norfac), 1.0f);
1077 if(norfac == 1.0f && !GPU_link_changed(stencil)) {
1081 tnorfac = GPU_uniform(&norfac);
1083 if(GPU_link_changed(stencil))
1084 GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac);
1086 GPU_link(mat, "mtex_blend_normal", tnorfac, shi->vn, newnor, &shi->vn);
1089 } else if( (mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP)) || found_deriv_map) {
1090 /* ntap bumpmap image */
1095 float imag_tspace_dimension_x = 1024.0f; // only used for texture space variant
1096 float aspect = 1.0f;
1098 GPUNodeLink *surf_pos = GPU_builtin(GPU_VIEW_POSITION);
1099 GPUNodeLink *vR1, *vR2;
1100 GPUNodeLink *dBs, *dBt, *fDet;
1102 hScale = 0.1; // compatibility adjustment factor for all bumpspace types
1103 if( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
1104 hScale = 13.0f; // factor for scaling texspace bumps
1105 else if(found_deriv_map!=0)
1108 // resolve texture resolution
1109 if( (mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map ) {
1110 ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, &tex->iuser);
1111 ima_x= 512.0f; ima_y= 512.f; // prevent calling textureSize, glsl 1.3 only
1115 aspect = ((float) ima_y) / ima_x;
1119 // The negate on norfac is done because the
1120 // normal in the renderer points inward which corresponds
1121 // to inverting the bump map. Should this ever change
1122 // this negate must be removed.
1123 norfac = -hScale * mtex->norfac;
1124 if(found_deriv_map) norfac /= sqrtf(ima_x*ima_y);
1126 tnorfac = GPU_uniform(&norfac);
1129 GPU_link(mat, "math_multiply", tnorfac, GPU_builtin(GPU_AUTO_BUMPSCALE), &tnorfac);
1131 if(GPU_link_changed(stencil))
1132 GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac);
1135 // copy shi->vn to vNorg and vNacc, set magnitude to 1
1136 GPU_link(mat, "mtex_bump_normals_init", shi->vn, &vNorg, &vNacc, &fPrevMagnitude);
1141 // find current bump space
1142 if( mtex->texflag & MTEX_BUMP_OBJECTSPACE )
1144 else if( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
1147 iBumpSpace = 4; // ViewSpace
1149 // re-initialize if bump space changed
1150 if( iBumpSpacePrev != iBumpSpace ) {
1152 if( mtex->texflag & MTEX_BUMP_OBJECTSPACE )
1153 GPU_link( mat, "mtex_bump_init_objspace",
1155 GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
1156 fPrevMagnitude, vNacc,
1157 &fPrevMagnitude, &vNacc,
1158 &vR1, &vR2, &fDet );
1160 else if( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
1161 GPU_link( mat, "mtex_bump_init_texturespace",
1163 fPrevMagnitude, vNacc,
1164 &fPrevMagnitude, &vNacc,
1165 &vR1, &vR2, &fDet );
1168 GPU_link( mat, "mtex_bump_init_viewspace",
1170 fPrevMagnitude, vNacc,
1171 &fPrevMagnitude, &vNacc,
1172 &vR1, &vR2, &fDet );
1174 iBumpSpacePrev = iBumpSpace;
1178 if(found_deriv_map) {
1179 GPU_link( mat, "mtex_bump_deriv",
1180 texco, GPU_image(tex->ima, &tex->iuser), GPU_uniform(&ima_x), GPU_uniform(&ima_y), tnorfac,
1183 else if( mtex->texflag & MTEX_3TAP_BUMP )
1184 GPU_link( mat, "mtex_bump_tap3",
1185 texco, GPU_image(tex->ima, &tex->iuser), tnorfac,
1188 GPU_link( mat, "mtex_bump_tap5",
1189 texco, GPU_image(tex->ima, &tex->iuser), tnorfac,
1193 if( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) {
1194 float imag_tspace_dimension_y = aspect*imag_tspace_dimension_x;
1195 GPU_link( mat, "mtex_bump_apply_texspace",
1196 fDet, dBs, dBt, vR1, vR2,
1197 GPU_image(tex->ima, &tex->iuser), texco,
1198 GPU_uniform(&imag_tspace_dimension_x), GPU_uniform(&imag_tspace_dimension_y), vNacc,
1201 GPU_link( mat, "mtex_bump_apply",
1202 fDet, dBs, dBt, vR1, vR2, vNacc,
1208 GPU_link(mat, "vec_math_negate", shi->vn, &orn);
1211 if((mtex->mapto & MAP_VARS)) {
1212 if(rgbnor & TEX_RGB) {
1214 GPU_link(mat, "mtex_alpha_from_col", trgb, &tin);
1216 GPU_link(mat, "mtex_rgbtoint", trgb, &tin);
1219 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_REF) {
1220 GPUNodeLink *difffac;
1222 if(mtex->difffac == 1.0f) difffac = stencil;
1223 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->difffac), stencil, &difffac);
1225 texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->refl, tin, difffac, mtex->blendtype, &shi->refl);
1226 GPU_link(mat, "mtex_value_clamp_positive", shi->refl, &shi->refl);
1228 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_SPEC) {
1229 GPUNodeLink *specfac;
1231 if(mtex->specfac == 1.0f) specfac = stencil;
1232 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->specfac), stencil, &specfac);
1234 texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->spec, tin, specfac, mtex->blendtype, &shi->spec);
1235 GPU_link(mat, "mtex_value_clamp_positive", shi->spec, &shi->spec);
1237 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_EMIT) {
1238 GPUNodeLink *emitfac;
1240 if(mtex->emitfac == 1.0f) emitfac = stencil;
1241 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->emitfac), stencil, &emitfac);
1243 texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->emit, tin, emitfac, mtex->blendtype, &shi->emit);
1244 GPU_link(mat, "mtex_value_clamp_positive", shi->emit, &shi->emit);
1246 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_HAR) {
1247 GPUNodeLink *hardfac;
1249 if(mtex->hardfac == 1.0f) hardfac = stencil;
1250 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->hardfac), stencil, &hardfac);
1252 GPU_link(mat, "mtex_har_divide", shi->har, &shi->har);
1253 texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->har, tin, hardfac, mtex->blendtype, &shi->har);
1254 GPU_link(mat, "mtex_har_multiply_clamp", shi->har, &shi->har);
1256 if(mtex->mapto & MAP_ALPHA) {
1257 GPUNodeLink *alphafac;
1259 if(mtex->alphafac == 1.0f) alphafac = stencil;
1260 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->alphafac), stencil, &alphafac);
1262 texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->alpha, tin, alphafac, mtex->blendtype, &shi->alpha);
1263 GPU_link(mat, "mtex_value_clamp", shi->alpha, &shi->alpha);
1265 if(!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_AMB) {
1266 GPUNodeLink *ambfac;
1268 if(mtex->ambfac == 1.0f) ambfac = stencil;
1269 else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->ambfac), stencil, &ambfac);
1271 texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->amb, tin, ambfac, mtex->blendtype, &shi->amb);
1272 GPU_link(mat, "mtex_value_clamp", shi->amb, &shi->amb);
1279 void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi)
1281 float hard = ma->har;
1283 memset(shi, 0, sizeof(*shi));
1288 GPU_link(mat, "set_rgb", GPU_uniform(&ma->r), &shi->rgb);
1289 GPU_link(mat, "set_rgb", GPU_uniform(&ma->specr), &shi->specrgb);
1290 GPU_link(mat, "shade_norm", GPU_builtin(GPU_VIEW_NORMAL), &shi->vn);
1291 GPU_link(mat, "set_value", GPU_uniform(&ma->alpha), &shi->alpha);
1292 GPU_link(mat, "set_value", GPU_uniform(&ma->ref), &shi->refl);
1293 GPU_link(mat, "set_value", GPU_uniform(&ma->spec), &shi->spec);
1294 GPU_link(mat, "set_value", GPU_uniform(&ma->emit), &shi->emit);
1295 GPU_link(mat, "set_value", GPU_uniform(&hard), &shi->har);
1296 GPU_link(mat, "set_value", GPU_uniform(&ma->amb), &shi->amb);
1297 GPU_link(mat, "shade_view", GPU_builtin(GPU_VIEW_POSITION), &shi->view);
1298 GPU_link(mat, "vcol_attribute", GPU_attribute(CD_MCOL, ""), &shi->vcol);
1299 if(gpu_do_color_management(mat))
1300 GPU_link(mat, "srgb_to_linearrgb", shi->vcol, &shi->vcol);
1301 GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref);
1304 void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
1306 GPUMaterial *mat= shi->gpumat;
1307 GPUNodeLink *emit, *ulinfac, *ulogfac, *mistfac;
1308 Material *ma= shi->mat;
1309 World *world= mat->scene->world;
1310 float linfac, logfac, misttype;
1312 memset(shr, 0, sizeof(*shr));
1314 if(ma->mode & MA_VERTEXCOLP)
1315 shi->rgb = shi->vcol;
1317 do_material_tex(shi);
1319 if((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP))
1320 GPU_material_enable_alpha(mat);
1322 if((mat->scene->gm.flag & GAME_GLSL_NO_LIGHTS) || (ma->mode & MA_SHLESS)) {
1323 shr->combined = shi->rgb;
1324 shr->alpha = shi->alpha;
1325 GPU_link(mat, "set_rgb", shi->rgb, &shr->diff);
1326 GPU_link(mat, "set_rgb_zero", &shr->spec);
1329 if(GPU_link_changed(shi->emit) || ma->emit != 0.0f) {
1330 if((ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL) {
1331 GPU_link(mat, "shade_add", shi->emit, shi->vcol, &emit);
1332 GPU_link(mat, "shade_mul", emit, shi->rgb, &shr->diff);
1335 GPU_link(mat, "shade_mul_value", shi->emit, shi->rgb, &shr->diff);
1338 GPU_link(mat, "set_rgb_zero", &shr->diff);
1340 GPU_link(mat, "set_rgb_zero", &shr->spec);
1342 material_lights(shi, shr);
1344 shr->combined = shr->diff;
1345 shr->alpha = shi->alpha;
1348 /* exposure correction */
1349 if(world->exp!=0.0f || world->range!=1.0f) {
1350 linfac= 1.0f + powf((2.0f*world->exp + 0.5f), -10);
1351 logfac= logf((linfac-1.0f)/linfac)/world->range;
1353 GPU_link(mat, "set_value", GPU_uniform(&linfac), &ulinfac);
1354 GPU_link(mat, "set_value", GPU_uniform(&logfac), &ulogfac);
1356 GPU_link(mat, "shade_exposure_correct", shr->combined,
1357 ulinfac, ulogfac, &shr->combined);
1358 GPU_link(mat, "shade_exposure_correct", shr->spec,
1359 ulinfac, ulogfac, &shr->spec);
1363 if(world->ambr!=0.0f || world->ambg!=0.0f || world->ambb!=0.0f) {
1364 if(GPU_link_changed(shi->amb) || ma->amb != 0.0f)
1365 GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb),
1366 GPU_uniform(&world->ambr), &shr->combined);
1370 if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shi, &shr->combined);
1371 if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(shi, &shr->spec);
1373 if(GPU_link_changed(shi->spec) || ma->spec != 0.0f)
1374 GPU_link(mat, "shade_add", shr->combined, shr->spec, &shr->combined);
1377 GPU_link(mat, "mtex_alpha_to_col", shr->combined, shr->alpha, &shr->combined);
1379 if(ma->shade_flag & MA_OBCOLOR)
1380 GPU_link(mat, "shade_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined);
1382 if(world && (world->mode & WO_MIST) && !(ma->mode & MA_NOMIST)) {
1383 misttype = world->mistype;
1385 GPU_link(mat, "shade_mist_factor", GPU_builtin(GPU_VIEW_POSITION),
1386 GPU_uniform(&world->miststa), GPU_uniform(&world->mistdist),
1387 GPU_uniform(&misttype), GPU_uniform(&world->misi), &mistfac);
1389 GPU_link(mat, "mix_blend", mistfac, shr->combined,
1390 GPU_uniform(&world->horr), &shr->combined);
1393 if(!((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP))) {
1394 if(world && (GPU_link_changed(shr->alpha) || ma->alpha != 1.0f))
1395 GPU_link(mat, "shade_world_mix", GPU_uniform(&world->horr),
1396 shr->combined, &shr->combined);
1398 GPU_link(mat, "shade_alpha_opaque", shr->combined, &shr->combined);
1401 if(ma->shade_flag & MA_OBCOLOR) {
1402 mat->obcolalpha = 1;
1403 GPU_link(mat, "shade_alpha_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined);
1407 static GPUNodeLink *GPU_blender_material(GPUMaterial *mat, Material *ma)
1412 GPU_shadeinput_set(mat, ma, &shi);
1413 GPU_shaderesult_set(&shi, &shr);
1415 return shr.combined;
1418 GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma)
1421 GPUNodeLink *outlink;
1424 for(link=ma->gpumaterial.first; link; link=link->next)
1425 if(((GPUMaterial*)link->data)->scene == scene)
1428 /* allocate material */
1429 mat = GPU_material_construct_begin(ma);
1432 if(!(scene->gm.flag & GAME_GLSL_NO_NODES) && ma->nodetree && ma->use_nodes) {
1434 ntreeGPUMaterialNodes(ma->nodetree, mat);
1437 /* create material */
1438 outlink = GPU_blender_material(mat, ma);
1439 GPU_material_output_link(mat, outlink);
1442 if(!scene_use_new_shading_nodes(scene)) {
1443 if(gpu_do_color_management(mat))
1445 GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink);
1449 GPU_material_construct_end(mat);
1451 /* note that even if building the shader fails in some way, we still keep
1452 it to avoid trying to compile again and again, and simple do not use
1453 the actual shader on drawing */
1455 link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
1457 BLI_addtail(&ma->gpumaterial, link);
1462 void GPU_materials_free(void)
1466 extern Material defmaterial;
1468 for(ma=G.main->mat.first; ma; ma=ma->id.next)
1469 GPU_material_free(ma);
1471 GPU_material_free(&defmaterial);
1473 for(ob=G.main->object.first; ob; ob=ob->id.next)
1477 /* Lamps and shadow buffers */
1479 void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[][4])
1486 copy_m4_m4(mat, obmat);
1489 copy_v3_v3(lamp->vec, mat[2]);
1490 copy_v3_v3(lamp->co, mat[3]);
1491 copy_m4_m4(lamp->obmat, mat);
1492 invert_m4_m4(lamp->imat, mat);
1495 void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
1497 lamp->energy = energy;
1498 if(lamp->mode & LA_NEG) lamp->energy= -lamp->energy;
1500 lamp->col[0]= r* lamp->energy;
1501 lamp->col[1]= g* lamp->energy;
1502 lamp->col[2]= b* lamp->energy;
1505 static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
1507 float temp, angle, pixsize, wsize;
1509 lamp->scene = scene;
1514 /* add_render_lamp */
1515 lamp->mode = la->mode;
1516 lamp->type = la->type;
1518 lamp->energy = la->energy;
1519 if(lamp->mode & LA_NEG) lamp->energy= -lamp->energy;
1521 lamp->col[0]= la->r*lamp->energy;
1522 lamp->col[1]= la->g*lamp->energy;
1523 lamp->col[2]= la->b*lamp->energy;
1525 GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat);
1527 lamp->spotsi= la->spotsize;
1528 if(lamp->mode & LA_HALO)
1529 if(lamp->spotsi > 170.0f)
1530 lamp->spotsi = 170.0f;
1531 lamp->spotsi= cosf((float)M_PI*lamp->spotsi/360.0f);
1532 lamp->spotbl= (1.0f - lamp->spotsi)*la->spotblend;
1535 lamp->dist= la->dist;
1536 lamp->falloff_type= la->falloff_type;
1537 lamp->att1= la->att1;
1538 lamp->att2= la->att2;
1539 lamp->curfalloff= la->curfalloff;
1542 lamp->bias = 0.02f*la->bias;
1543 lamp->size = la->bufsize;
1544 lamp->d= la->clipsta;
1545 lamp->clipend= la->clipend;
1547 /* arbitrary correction for the fact we do no soft transition */
1548 lamp->bias *= 0.25f;
1551 angle= saacos(lamp->spotsi);
1552 temp= 0.5f*lamp->size*cosf(angle)/sinf(angle);
1553 pixsize= (lamp->d)/temp;
1554 wsize= pixsize*0.5f*lamp->size;
1556 perspective_m4( lamp->winmat,-wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
1559 static void gpu_lamp_shadow_free(GPULamp *lamp)
1562 GPU_texture_free(lamp->tex);
1566 GPU_framebuffer_free(lamp->fb);
1571 GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
1577 for(link=ob->gpulamp.first; link; link=link->next) {
1578 lamp = (GPULamp*)link->data;
1580 if(lamp->par == par && lamp->scene == scene)
1584 lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
1586 link = MEM_callocN(sizeof(LinkData), "GPULampLink");
1588 BLI_addtail(&ob->gpulamp, link);
1591 gpu_lamp_from_blender(scene, ob, par, la, lamp);
1593 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF)) {
1595 lamp->fb = GPU_framebuffer_create();
1597 gpu_lamp_shadow_free(lamp);
1601 lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
1603 gpu_lamp_shadow_free(lamp);
1607 if(!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, NULL)) {
1608 gpu_lamp_shadow_free(lamp);
1612 GPU_framebuffer_restore();
1618 void GPU_lamp_free(Object *ob)
1625 for(link=ob->gpulamp.first; link; link=link->next) {
1628 while(lamp->materials.first) {
1629 nlink = lamp->materials.first;
1631 BLI_freelinkN(&lamp->materials, nlink);
1633 if(ma->gpumaterial.first)
1634 GPU_material_free(ma);
1637 gpu_lamp_shadow_free(lamp);
1642 BLI_freelistN(&ob->gpulamp);
1645 int GPU_lamp_has_shadow_buffer(GPULamp *lamp)
1647 return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) &&
1648 !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) &&
1649 lamp->tex && lamp->fb);
1652 void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[][4], int *winsize, float winmat[][4])
1654 float rangemat[4][4], persmat[4][4];
1657 invert_m4_m4(lamp->viewmat, lamp->obmat);
1658 normalize_v3(lamp->viewmat[0]);
1659 normalize_v3(lamp->viewmat[1]);
1660 normalize_v3(lamp->viewmat[2]);
1663 mul_m4_m4m4(persmat, lamp->viewmat, lamp->winmat);
1665 /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */
1667 rangemat[0][0] = 0.5f;
1668 rangemat[1][1] = 0.5f;
1669 rangemat[2][2] = 0.5f;
1670 rangemat[3][0] = 0.5f;
1671 rangemat[3][1] = 0.5f;
1672 rangemat[3][2] = 0.5f;
1674 mul_m4_m4m4(lamp->persmat, persmat, rangemat);
1677 glDisable(GL_SCISSOR_TEST);
1678 GPU_framebuffer_texture_bind(lamp->fb, lamp->tex,
1679 GPU_texture_opengl_width(lamp->tex), GPU_texture_opengl_height(lamp->tex));
1682 copy_m4_m4(viewmat, lamp->viewmat);
1683 copy_m4_m4(winmat, lamp->winmat);
1684 *winsize = lamp->size;
1687 void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
1689 GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
1690 GPU_framebuffer_restore();
1691 glEnable(GL_SCISSOR_TEST);
1694 int GPU_lamp_shadow_layer(GPULamp *lamp)
1696 if(lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER|LA_LAYER_SHADOW)))
1702 /* export the GLSL shader */
1704 GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
1708 GPUDynamicType dynamictype;
1709 GPUDataType datatype;
1711 { GPU_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWMAT, GPU_DATA_16F },
1712 { GPU_INVERSE_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWIMAT, GPU_DATA_16F },
1713 { GPU_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_MAT, GPU_DATA_16F },
1714 { GPU_INVERSE_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_IMAT, GPU_DATA_16F },
1715 { GPU_OBCOLOR, GPU_DYNAMIC_OBJECT_COLOR, GPU_DATA_4F },
1716 { GPU_AUTO_BUMPSCALE, GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE, GPU_DATA_1F },
1720 GPUShaderExport *shader = NULL;
1724 GPUInputUniform *uniform;
1725 GPUInputAttribute *attribute;
1727 int i, liblen, fraglen;
1729 if(!GPU_glsl_support())
1732 mat = GPU_material_from_blender(scene, ma);
1733 pass = (mat)? mat->pass: NULL;
1735 if(pass && pass->fragmentcode && pass->vertexcode) {
1736 shader = MEM_callocN(sizeof(GPUShaderExport), "GPUShaderExport");
1738 for(input = pass->inputs.first; input; input = input->next) {
1739 uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
1742 /* image sampler uniform */
1743 uniform->type = GPU_DYNAMIC_SAMPLER_2DIMAGE;
1744 uniform->datatype = GPU_DATA_1I;
1745 uniform->image = input->ima;
1746 uniform->texnumber = input->texid;
1747 BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
1749 else if(input->tex) {
1750 /* generated buffer */
1751 uniform->texnumber = input->texid;
1752 uniform->datatype = GPU_DATA_1I;
1753 BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
1755 switch(input->textype) {
1757 uniform->type = GPU_DYNAMIC_SAMPLER_2DSHADOW;
1758 uniform->lamp = input->dynamicdata;
1761 if(GPU_texture_opengl_bindcode(input->tex)) {
1762 uniform->type = GPU_DYNAMIC_SAMPLER_2DBUFFER;
1763 glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
1764 glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(input->tex));
1765 uniform->texsize = GPU_texture_opengl_width(input->tex) * GPU_texture_opengl_height(input->tex);
1766 uniform->texpixels = MEM_mallocN(uniform->texsize*4, "RGBApixels");
1767 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, uniform->texpixels);
1768 glBindTexture(GL_TEXTURE_2D, lastbindcode);
1774 uniform->type = input->dynamictype;
1775 BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
1776 switch(input->type) {
1778 uniform->datatype = GPU_DATA_1F;
1781 uniform->datatype = GPU_DATA_2F;
1784 uniform->datatype = GPU_DATA_3F;
1787 uniform->datatype = GPU_DATA_4F;
1790 uniform->datatype = GPU_DATA_9F;
1793 uniform->datatype = GPU_DATA_16F;
1797 if(uniform->type >= GPU_DYNAMIC_LAMP_FIRST && uniform->type <= GPU_DYNAMIC_LAMP_LAST)
1798 uniform->lamp = input->dynamicdata;
1801 if(uniform->type != GPU_DYNAMIC_NONE)
1802 BLI_addtail(&shader->uniforms, uniform);
1807 /* process builtin uniform */
1808 for(i=0; builtins[i].gputype; i++) {
1809 if(mat->builtins & builtins[i].gputype) {
1810 uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
1811 uniform->type = builtins[i].dynamictype;
1812 uniform->datatype = builtins[i].datatype;
1813 BLI_strncpy(uniform->varname, GPU_builtin_name(builtins[i].gputype), sizeof(uniform->varname));
1814 BLI_addtail(&shader->uniforms, uniform);
1818 // now link fragement shader with library shader
1819 // TBD: remove the function that are not used in the main function
1820 liblen = (pass->libcode) ? strlen(pass->libcode) : 0;
1821 fraglen = strlen(pass->fragmentcode);
1822 shader->fragment = (char *)MEM_mallocN(liblen+fraglen+1, "GPUFragShader");
1824 memcpy(shader->fragment, pass->libcode, liblen);
1825 memcpy(&shader->fragment[liblen], pass->fragmentcode, fraglen);
1826 shader->fragment[liblen+fraglen] = 0;
1828 // export the attribute
1829 for(i=0; i<mat->attribs.totlayer; i++) {
1830 attribute = MEM_callocN(sizeof(GPUInputAttribute), "GPUInputAttribute");
1831 attribute->type = mat->attribs.layer[i].type;
1832 attribute->number = mat->attribs.layer[i].glindex;
1833 BLI_snprintf(attribute->varname, sizeof(attribute->varname), "att%d", mat->attribs.layer[i].attribid);
1835 switch(attribute->type) {
1837 attribute->datatype = GPU_DATA_4F;
1840 attribute->datatype = GPU_DATA_2F;
1841 attribute->name = mat->attribs.layer[i].name;
1844 attribute->datatype = GPU_DATA_4UB;
1845 attribute->name = mat->attribs.layer[i].name;
1848 attribute->datatype = GPU_DATA_3F;
1852 if(attribute->datatype != GPU_DATA_NONE)
1853 BLI_addtail(&shader->attributes, attribute);
1855 MEM_freeN(attribute);
1858 // export the vertex shader
1859 shader->vertex = BLI_strdup(pass->vertexcode);
1865 void GPU_free_shader_export(GPUShaderExport *shader)
1867 GPUInputUniform *uniform;
1872 for(uniform = shader->uniforms.first; uniform; uniform=uniform->next)
1873 if(uniform->texpixels)
1874 MEM_freeN(uniform->texpixels);
1876 BLI_freelistN(&shader->uniforms);
1877 BLI_freelistN(&shader->attributes);
1880 MEM_freeN(shader->vertex);
1881 if(shader->fragment)
1882 MEM_freeN(shader->fragment);