Merge with -r 22620:23107.
[blender.git] / source / blender / gpu / intern / gpu_draw.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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2005 Blender Foundation.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): Brecht Van Lommel.
29  *
30  * ***** END GPL LICENSE BLOCK *****
31  */
32
33 #include <string.h>
34
35 #include "GL/glew.h"
36
37 #include "DNA_image_types.h"
38 #include "DNA_lamp_types.h"
39 #include "DNA_material_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_modifier_types.h"
42 #include "DNA_node_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_scene_types.h"
45 #include "DNA_smoke_types.h"
46 #include "DNA_userdef_types.h"
47 #include "DNA_view3d_types.h"
48
49 #include "MEM_guardedalloc.h"
50
51 #include "IMB_imbuf.h"
52 #include "IMB_imbuf_types.h"
53
54 #include "BKE_bmfont.h"
55 #include "BKE_global.h"
56 #include "BKE_image.h"
57 #include "BKE_main.h"
58 #include "BKE_material.h"
59 #include "BKE_node.h"
60 #include "BKE_object.h"
61 #include "BKE_utildefines.h"
62
63 #include "GPU_extensions.h"
64 #include "GPU_material.h"
65 #include "GPU_draw.h"
66
67 #include "smoke_API.h"
68
69 /* These are some obscure rendering functions shared between the
70  * game engine and the blender, in this module to avoid duplicaten
71  * and abstract them away from the rest a bit */
72
73 /* Text Rendering */
74
75 static void gpu_mcol(unsigned int ucol)
76 {
77         /* mcol order is swapped */
78         char *cp= (char *)&ucol;
79         glColor3ub(cp[3], cp[2], cp[1]);
80 }
81
82 void GPU_render_text(MTFace *tface, int mode,
83         const char *textstr, int textlen, unsigned int *col,
84         float *v1, float *v2, float *v3, float *v4, int glattrib)
85 {
86         if ((mode & TF_BMFONT) && (textlen>0) && tface->tpage) {
87                 Image* ima = (Image*)tface->tpage;
88                 int index, character;
89                 float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
90                 float advance_tab;
91                 
92                 /* multiline */
93                 float line_start= 0.0f, line_height;
94                 
95                 if (v4)
96                         line_height= MAX4(v1[1], v2[1], v3[1], v4[2]) - MIN4(v1[1], v2[1], v3[1], v4[2]);
97                 else
98                         line_height= MAX3(v1[1], v2[1], v3[1]) - MIN3(v1[1], v2[1], v3[1]);
99                 line_height *= 1.2; /* could be an option? */
100                 /* end multiline */
101
102                 
103                 /* color has been set */
104                 if (tface->mode & TF_OBCOL)
105                         col= NULL;
106                 else if (!col)
107                         glColor3f(1.0f, 1.0f, 1.0f);
108
109                 glPushMatrix();
110                 
111                 /* get the tab width */
112                 matrixGlyph((ImBuf *)ima->ibufs.first, ' ', & centerx, &centery,
113                         &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
114                 
115                 advance_tab= advance * 4; /* tab width could also be an option */
116                 
117                 
118                 for (index = 0; index < textlen; index++) {
119                         float uv[4][2];
120
121                         // lets calculate offset stuff
122                         character = textstr[index];
123                         
124                         if (character=='\n') {
125                                 glTranslatef(line_start, -line_height, 0.0);
126                                 line_start = 0.0f;
127                                 continue;
128                         }
129                         else if (character=='\t') {
130                                 glTranslatef(advance_tab, 0.0, 0.0);
131                                 line_start -= advance_tab; /* so we can go back to the start of the line */
132                                 continue;
133                                 
134                         }
135                         
136                         // space starts at offset 1
137                         // character = character - ' ' + 1;
138                         matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, &centery,
139                                 &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
140
141                         uv[0][0] = (tface->uv[0][0] - centerx) * sizex + transx;
142                         uv[0][1] = (tface->uv[0][1] - centery) * sizey + transy;
143                         uv[1][0] = (tface->uv[1][0] - centerx) * sizex + transx;
144                         uv[1][1] = (tface->uv[1][1] - centery) * sizey + transy;
145                         uv[2][0] = (tface->uv[2][0] - centerx) * sizex + transx;
146                         uv[2][1] = (tface->uv[2][1] - centery) * sizey + transy;
147                         
148                         glBegin(GL_POLYGON);
149                         if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[0]);
150                         else glTexCoord2fv(uv[0]);
151                         if(col) gpu_mcol(col[0]);
152                         glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
153                         
154                         if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[1]);
155                         else glTexCoord2fv(uv[1]);
156                         if(col) gpu_mcol(col[1]);
157                         glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]);
158
159                         if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[2]);
160                         else glTexCoord2fv(uv[2]);
161                         if(col) gpu_mcol(col[2]);
162                         glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
163
164                         if(v4) {
165                                 uv[3][0] = (tface->uv[3][0] - centerx) * sizex + transx;
166                                 uv[3][1] = (tface->uv[3][1] - centery) * sizey + transy;
167
168                                 if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[3]);
169                                 else glTexCoord2fv(uv[3]);
170                                 if(col) gpu_mcol(col[3]);
171                                 glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]);
172                         }
173                         glEnd();
174
175                         glTranslatef(advance, 0.0, 0.0);
176                         line_start -= advance; /* so we can go back to the start of the line */
177                 }
178                 glPopMatrix();
179         }
180 }
181
182 /* Checking powers of two for images since opengl 1.x requires it */
183
184 static int is_pow2(int num)
185 {
186         /* (n&(n-1)) zeros the least significant bit of n */
187         return ((num)&(num-1))==0;
188 }
189
190 static int smaller_pow2(int num)
191 {
192         while (!is_pow2(num))
193                 num= num&(num-1);
194
195         return num;     
196 }
197
198 static int is_pow2_limit(int num)
199 {
200         /* take texture clamping into account */
201
202         /* XXX: texturepaint not global!
203            if (G.f & G_TEXTUREPAINT)
204            return 1;*/
205
206         if (U.glreslimit != 0 && num > U.glreslimit)
207                 return 0;
208
209         return ((num)&(num-1))==0;
210 }
211
212 static int smaller_pow2_limit(int num)
213 {
214         /* XXX: texturepaint not global!
215            if (G.f & G_TEXTUREPAINT)
216            return 1;*/
217         
218         /* take texture clamping into account */
219         if (U.glreslimit != 0 && num > U.glreslimit)
220                 return U.glreslimit;
221
222         return smaller_pow2(num);
223 }
224
225 /* Current OpenGL state caching for GPU_set_tpage */
226
227 static struct GPUTextureState {
228         int curtile, tile;
229         int curtilemode, tilemode;
230         int curtileXRep, tileXRep;
231         int curtileYRep, tileYRep;
232         Image *ima, *curima;
233
234         int domipmap, linearmipmap;
235
236         int alphamode;
237         MTFace *lasttface;
238 } GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, -1, NULL};
239
240 /* Mipmap settings */
241
242 void GPU_set_mipmap(int mipmap)
243 {
244         if (GTS.domipmap != (mipmap != 0)) {
245                 GPU_free_images();
246                 GTS.domipmap = mipmap != 0;
247         }
248 }
249
250 void GPU_set_linear_mipmap(int linear)
251 {
252         if (GTS.linearmipmap != (linear != 0)) {
253                 GPU_free_images();
254                 GTS.linearmipmap = linear != 0;
255         }
256 }
257
258 static int gpu_get_mipmap(void)
259 {
260         return GTS.domipmap;
261 }
262
263 static GLenum gpu_get_mipmap_filter(int mag)
264 {
265         /* linearmipmap is off by default *when mipmapping is off,
266          * use unfiltered display */
267         if(mag) {
268                 if(GTS.linearmipmap || GTS.domipmap)
269                         return GL_LINEAR;
270                 else
271                         return GL_NEAREST;
272         }
273         else {
274                 if(GTS.linearmipmap)
275                         return GL_LINEAR_MIPMAP_LINEAR;
276                 else if(GTS.domipmap)
277                         return GL_LINEAR_MIPMAP_NEAREST;
278                 else
279                         return GL_NEAREST;
280         }
281 }
282
283 /* Set OpenGL state for an MTFace */
284
285 static void gpu_make_repbind(Image *ima)
286 {
287         ImBuf *ibuf;
288         
289         ibuf = BKE_image_get_ibuf(ima, NULL);
290         if(ibuf==NULL)
291                 return;
292
293         if(ima->repbind) {
294                 glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
295                 MEM_freeN(ima->repbind);
296                 ima->repbind= 0;
297                 ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
298         }
299
300         ima->totbind= ima->xrep*ima->yrep;
301
302         if(ima->totbind>1)
303                 ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind");
304 }
305
306 static void gpu_clear_tpage()
307 {
308         if(GTS.lasttface==0)
309                 return;
310         
311         GTS.lasttface= 0;
312         GTS.curtile= 0;
313         GTS.curima= 0;
314         if(GTS.curtilemode!=0) {
315                 glMatrixMode(GL_TEXTURE);
316                 glLoadIdentity();
317                 glMatrixMode(GL_MODELVIEW);
318         }
319         GTS.curtilemode= 0;
320         GTS.curtileXRep=0;
321         GTS.curtileYRep=0;
322         GTS.alphamode= -1;
323         
324         glDisable(GL_BLEND);
325         glDisable(GL_TEXTURE_2D);
326         glDisable(GL_TEXTURE_GEN_S);
327         glDisable(GL_TEXTURE_GEN_T);
328         glDisable(GL_ALPHA_TEST);
329 }
330
331 static void gpu_set_blend_mode(GPUBlendMode blendmode)
332 {
333         if(blendmode == GPU_BLEND_SOLID) {
334                 glDisable(GL_BLEND);
335                 glDisable(GL_ALPHA_TEST);
336                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
337         }
338         else if(blendmode==GPU_BLEND_ADD) {
339                 glEnable(GL_BLEND);
340                 glBlendFunc(GL_ONE, GL_ONE);
341                 glDisable(GL_ALPHA_TEST);
342         }
343         else if(blendmode==GPU_BLEND_ALPHA) {
344                 glEnable(GL_BLEND);
345                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
346                 
347                 /* if U.glalphaclip == 1.0, some cards go bonkers...
348                  * turn off alpha test in this case */
349
350                 /* added after 2.45 to clip alpha */
351                 if(U.glalphaclip == 1.0) {
352                         glDisable(GL_ALPHA_TEST);
353                 }
354                 else {
355                         glEnable(GL_ALPHA_TEST);
356                         glAlphaFunc(GL_GREATER, U.glalphaclip);
357                 }
358         }
359         else if(blendmode==GPU_BLEND_CLIP) {
360                 glDisable(GL_BLEND); 
361                 glEnable(GL_ALPHA_TEST);
362                 glAlphaFunc(GL_GREATER, 0.5f);
363         }
364 }
365
366 static void gpu_verify_alpha_mode(MTFace *tface)
367 {
368         /* verify alpha blending modes */
369         if(GTS.alphamode == tface->transp)
370                 return;
371
372         gpu_set_blend_mode(tface->transp);
373         GTS.alphamode= tface->transp;
374 }
375
376 static void gpu_verify_reflection(Image *ima)
377 {
378         if (ima && (ima->flag & IMA_REFLECT)) {
379                 /* enable reflection mapping */
380                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
381                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
382
383                 glEnable(GL_TEXTURE_GEN_S);
384                 glEnable(GL_TEXTURE_GEN_T);
385         }
386         else {
387                 /* disable reflection mapping */
388                 glDisable(GL_TEXTURE_GEN_S);
389                 glDisable(GL_TEXTURE_GEN_T);
390         }
391 }
392
393 int GPU_verify_image(Image *ima, int tftile, int tfmode, int compare, int mipmap)
394 {
395         ImBuf *ibuf = NULL;
396         unsigned int *bind = NULL;
397         int rectw, recth, tpx=0, tpy=0, y;
398         unsigned int *rectrow, *tilerectrow;
399         unsigned int *tilerect= NULL, *scalerect= NULL, *rect= NULL;
400         short texwindx, texwindy, texwinsx, texwinsy;
401
402         /* initialize tile mode and number of repeats */
403         GTS.ima = ima;
404         GTS.tilemode= (ima && (ima->tpageflag & (IMA_TILES|IMA_TWINANIM)));
405         GTS.tileXRep = 0;
406         GTS.tileYRep = 0;
407
408         /* setting current tile according to frame */
409         if(ima && (ima->tpageflag & IMA_TWINANIM))
410                 GTS.tile= ima->lastframe;
411         else
412                 GTS.tile= tftile;
413
414         GTS.tile = MAX2(0, GTS.tile);
415
416         if(ima) {
417                 GTS.tileXRep = ima->xrep;
418                 GTS.tileYRep = ima->yrep;
419         }
420
421         /* if same image & tile, we're done */
422         if(compare && ima == GTS.curima && GTS.curtile == GTS.tile &&
423            GTS.tilemode == GTS.curtilemode && GTS.curtileXRep == GTS.tileXRep &&
424            GTS.curtileYRep == GTS.tileYRep)
425                 return (ima!=0);
426
427         /* if tiling mode or repeat changed, change texture matrix to fit */
428         if(GTS.tilemode!=GTS.curtilemode || GTS.curtileXRep!=GTS.tileXRep ||
429            GTS.curtileYRep != GTS.tileYRep) {
430
431                 glMatrixMode(GL_TEXTURE);
432                 glLoadIdentity();
433
434                 if(ima && (ima->tpageflag & IMA_TILES))
435                         glScalef(ima->xrep, ima->yrep, 1.0);
436
437                 glMatrixMode(GL_MODELVIEW);
438         }
439
440         /* check if we have a valid image */
441         if(ima==NULL || ima->ok==0)
442                 return 0;
443
444         /* check if we have a valid image buffer */
445         ibuf= BKE_image_get_ibuf(ima, NULL);
446
447         if(ibuf==NULL)
448                 return 0;
449
450         /* ensure we have a char buffer and not only float */
451         if ((ibuf->rect==NULL) && ibuf->rect_float)
452                 IMB_rect_from_float(ibuf);
453
454         if(GTS.tilemode) {
455                 /* tiled mode */
456                 if(ima->repbind==0) gpu_make_repbind(ima);
457                 if(GTS.tile>=ima->totbind) GTS.tile= 0;
458                 
459                 /* this happens when you change repeat buttons */
460                 if(ima->repbind) bind= &ima->repbind[GTS.tile];
461                 else bind= &ima->bindcode;
462                 
463                 if(*bind==0) {
464                         
465                         texwindx= ibuf->x/ima->xrep;
466                         texwindy= ibuf->y/ima->yrep;
467                         
468                         if(GTS.tile>=ima->xrep*ima->yrep)
469                                 GTS.tile= ima->xrep*ima->yrep-1;
470         
471                         texwinsy= GTS.tile / ima->xrep;
472                         texwinsx= GTS.tile - texwinsy*ima->xrep;
473         
474                         texwinsx*= texwindx;
475                         texwinsy*= texwindy;
476         
477                         tpx= texwindx;
478                         tpy= texwindy;
479
480                         rect= ibuf->rect + texwinsy*ibuf->x + texwinsx;
481                 }
482         }
483         else {
484                 /* regular image mode */
485                 bind= &ima->bindcode;
486                 
487                 if(*bind==0) {
488                         tpx= ibuf->x;
489                         tpy= ibuf->y;
490                         rect= ibuf->rect;
491                 }
492         }
493
494         if(*bind != 0) {
495                 /* enable opengl drawing with textures */
496                 glBindTexture(GL_TEXTURE_2D, *bind);
497                 return *bind;
498         }
499
500         rectw = tpx;
501         recth = tpy;
502
503         /* for tiles, copy only part of image into buffer */
504         if (GTS.tilemode) {
505                 tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
506
507                 for (y=0; y<recth; y++) {
508                         rectrow= &rect[y*ibuf->x];
509                         tilerectrow= &tilerect[y*rectw];
510                                 
511                         memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow));
512                 }
513                         
514                 rect= tilerect;
515         }
516
517         /* scale if not a power of two */
518         if (!mipmap && (!is_pow2_limit(rectw) || !is_pow2_limit(recth))) {
519                 rectw= smaller_pow2_limit(rectw);
520                 recth= smaller_pow2_limit(recth);
521                 
522                 scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect");
523                 gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
524                 rect= scalerect;
525         }
526
527         /* create image */
528         glGenTextures(1, (GLuint *)bind);
529         glBindTexture( GL_TEXTURE_2D, *bind);
530
531         if (!(gpu_get_mipmap() && mipmap)) {
532                 glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA,  rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
533                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
534                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
535         }
536         else {
537                 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
538                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
539                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
540
541                 ima->tpageflag |= IMA_MIPMAP_COMPLETE;
542         }
543
544         /* set to modulate with vertex color */
545         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
546                 
547         /* clean up */
548         if (tilerect)
549                 MEM_freeN(tilerect);
550         if (scalerect)
551                 MEM_freeN(scalerect);
552
553         return *bind;
554 }
555
556 static void gpu_verify_repeat(Image *ima)
557 {
558         /* set either clamp or repeat in X/Y */
559         if (ima->tpageflag & IMA_CLAMP_U)
560            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
561         else
562                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
563
564         if (ima->tpageflag & IMA_CLAMP_V)
565                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
566         else
567                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
568 }
569
570 int GPU_set_tpage(MTFace *tface, int mipmap)
571 {
572         Image *ima;
573         
574         /* check if we need to clear the state */
575         if(tface==0) {
576                 gpu_clear_tpage();
577                 return 0;
578         }
579
580         ima= tface->tpage;
581         GTS.lasttface= tface;
582
583         gpu_verify_alpha_mode(tface);
584         gpu_verify_reflection(ima);
585
586         if(GPU_verify_image(ima, tface->tile, tface->mode, 1, mipmap)) {
587                 GTS.curtile= GTS.tile;
588                 GTS.curima= GTS.ima;
589                 GTS.curtilemode= GTS.tilemode;
590                 GTS.curtileXRep = GTS.tileXRep;
591                 GTS.curtileYRep = GTS.tileYRep;
592
593                 glEnable(GL_TEXTURE_2D);
594         }
595         else {
596                 glDisable(GL_TEXTURE_2D);
597                 
598                 GTS.curtile= 0;
599                 GTS.curima= 0;
600                 GTS.curtilemode= 0;
601                 GTS.curtileXRep = 0;
602                 GTS.curtileYRep = 0;
603
604                 return 0;
605         }
606         
607         gpu_verify_repeat(ima);
608         
609         /* Did this get lost in the image recode? */
610         /* tag_image_time(ima);*/
611
612         return 1;
613 }
614
615 /* these two functions are called on entering and exiting texture paint mode,
616    temporary disabling/enabling mipmapping on all images for quick texture
617    updates with glTexSubImage2D. images that didn't change don't have to be
618    re-uploaded to OpenGL */
619 void GPU_paint_set_mipmap(int mipmap)
620 {
621         Image* ima;
622         
623         if(!GTS.domipmap)
624                 return;
625
626         if(mipmap) {
627                 for(ima=G.main->image.first; ima; ima=ima->id.next) {
628                         if(ima->bindcode) {
629                                 if(ima->tpageflag & IMA_MIPMAP_COMPLETE) {
630                                         glBindTexture(GL_TEXTURE_2D, ima->bindcode);
631                                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
632                                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
633                                 }
634                                 else
635                                         GPU_free_image(ima);
636                         }
637                 }
638
639         }
640         else {
641                 for(ima=G.main->image.first; ima; ima=ima->id.next) {
642                         if(ima->bindcode) {
643                                 glBindTexture(GL_TEXTURE_2D, ima->bindcode);
644                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
645                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
646                         }
647                 }
648         }
649 }
650
651 void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap)
652 {
653         ImBuf *ibuf;
654         
655         ibuf = BKE_image_get_ibuf(ima, NULL);
656         
657         if (ima->repbind || (gpu_get_mipmap() && mipmap) || !ima->bindcode || !ibuf ||
658                 (!is_pow2(ibuf->x) || !is_pow2(ibuf->y)) ||
659                 (w == 0) || (h == 0)) {
660                 /* these cases require full reload still */
661                 GPU_free_image(ima);
662         }
663         else {
664                 /* for the special case, we can do a partial update
665                  * which is much quicker for painting */
666                 GLint row_length, skip_pixels, skip_rows;
667
668                 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
669                 glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels);
670                 glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows);
671
672                 if ((ibuf->rect==NULL) && ibuf->rect_float)
673                         IMB_rect_from_float(ibuf);
674
675                 glBindTexture(GL_TEXTURE_2D, ima->bindcode);
676
677                 glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x);
678                 glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
679                 glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
680
681                 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
682                         GL_UNSIGNED_BYTE, ibuf->rect);
683
684                 glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
685                 glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
686                 glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
687
688                 if(ima->tpageflag & IMA_MIPMAP_COMPLETE)
689                         ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
690         }
691 }
692
693 void GPU_update_images_framechange(void)
694 {
695         Image *ima;
696         
697         for(ima=G.main->image.first; ima; ima=ima->id.next) {
698                 if(ima->tpageflag & IMA_TWINANIM) {
699                         if(ima->twend >= ima->xrep*ima->yrep)
700                                 ima->twend= ima->xrep*ima->yrep-1;
701                 
702                         /* check: is bindcode not in the array? free. (to do) */
703                         
704                         ima->lastframe++;
705                         if(ima->lastframe > ima->twend)
706                                 ima->lastframe= ima->twsta;
707                 }
708         }
709 }
710
711 int GPU_update_image_time(Image *ima, double time)
712 {
713         int     inc = 0;
714         float   diff;
715         int     newframe;
716
717         if (!ima)
718                 return 0;
719
720         if (ima->lastupdate<0)
721                 ima->lastupdate = 0;
722
723         if (ima->lastupdate>time)
724                 ima->lastupdate=(float)time;
725
726         if(ima->tpageflag & IMA_TWINANIM) {
727                 if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
728                 
729                 /* check: is the bindcode not in the array? Then free. (still to do) */
730                 
731                 diff = (float)(time-ima->lastupdate);
732                 inc = (int)(diff*(float)ima->animspeed);
733
734                 ima->lastupdate+=((float)inc/(float)ima->animspeed);
735
736                 newframe = ima->lastframe+inc;
737
738                 if(newframe > (int)ima->twend) {
739                         if(ima->twend-ima->twsta != 0)
740                                 newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta);
741                         else
742                                 newframe = ima->twsta;
743                 }
744
745                 ima->lastframe = newframe;
746         }
747
748         return inc;
749 }
750
751
752 void GPU_free_smoke(SmokeModifierData *smd)
753 {
754         if(smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain)
755         {
756                 if(smd->domain->tex)
757                         GPU_texture_free(smd->domain->tex);
758                 smd->domain->tex = NULL;
759
760                 if(smd->domain->tex_shadow)
761                         GPU_texture_free(smd->domain->tex_shadow);
762                 smd->domain->tex_shadow = NULL;
763         }
764 }
765
766 void GPU_create_smoke(SmokeModifierData *smd, int highres)
767 {
768         if(smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain && !smd->domain->tex && !highres)
769                 smd->domain->tex = GPU_texture_create_3D(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2], smoke_get_density(smd->domain->fluid));
770         else if(smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain && !smd->domain->tex && highres)
771                 smd->domain->tex = GPU_texture_create_3D(smd->domain->res_wt[0], smd->domain->res_wt[1], smd->domain->res_wt[2], smoke_turbulence_get_density(smd->domain->wt));
772
773         smd->domain->tex_shadow = GPU_texture_create_3D(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2], smd->domain->shadow);
774 }
775
776 void GPU_free_image(Image *ima)
777 {
778         /* free regular image binding */
779         if(ima->bindcode) {
780                 glDeleteTextures(1, (GLuint *)&ima->bindcode);
781                 ima->bindcode= 0;
782                 ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
783         }
784
785         /* free glsl image binding */
786         if(ima->gputexture) {
787                 GPU_texture_free(ima->gputexture);
788                 ima->gputexture= NULL;
789         }
790
791         /* free repeated image binding */
792         if(ima->repbind) {
793                 glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
794         
795                 MEM_freeN(ima->repbind);
796                 ima->repbind= NULL;
797                 ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
798         }
799 }
800
801 void GPU_free_images(void)
802 {
803         Image* ima;
804
805         if(G.main)
806                 for(ima=G.main->image.first; ima; ima=ima->id.next)
807                         GPU_free_image(ima);
808 }
809
810 /* OpenGL Materials */
811
812 #define FIXEDMAT        8
813
814 /* OpenGL state caching for materials */
815
816 static struct GPUMaterialState {
817         float (*matbuf)[2][4];
818         float matbuf_fixed[FIXEDMAT][2][4];
819         int totmat;
820
821         Material **gmatbuf;
822         Material *gmatbuf_fixed[FIXEDMAT];
823         Material *gboundmat;
824         Object *gob;
825         Scene *gscene;
826         int glay;
827         float (*gviewmat)[4];
828         float (*gviewinv)[4];
829
830         GPUBlendMode *blendmode;
831         GPUBlendMode blendmode_fixed[FIXEDMAT];
832         int alphapass;
833
834         int lastmatnr, lastretval;
835         GPUBlendMode lastblendmode;
836 } GMS = {NULL};
837
838 Material *gpu_active_node_material(Material *ma)
839 {
840         if(ma && ma->use_nodes && ma->nodetree) {
841                 bNode *node= nodeGetActiveID(ma->nodetree, ID_MA);
842
843                 if(node)
844                         return (Material *)node->id;
845                 else
846                         return NULL;
847         }
848
849         return ma;
850 }
851
852 void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, int glsl, int *do_alpha_pass)
853 {
854         extern Material defmaterial; /* from material.c */
855         Material *ma;
856         GPUMaterial *gpumat;
857         GPUBlendMode blendmode;
858         int a;
859         
860         /* initialize state */
861         memset(&GMS, 0, sizeof(GMS));
862         GMS.lastmatnr = -1;
863         GMS.lastretval = -1;
864         GMS.lastblendmode = GPU_BLEND_SOLID;
865
866         GMS.gob = ob;
867         GMS.gscene = scene;
868         GMS.totmat= ob->totcol+1; /* materials start from 1, default material is 0 */
869         GMS.glay= v3d->lay;
870         GMS.gviewmat= rv3d->viewmat;
871         GMS.gviewinv= rv3d->viewinv;
872
873         GMS.alphapass = (v3d && v3d->transp);
874         if(do_alpha_pass)
875                 *do_alpha_pass = 0;
876         
877         if(GMS.totmat > FIXEDMAT) {
878                 GMS.matbuf= MEM_callocN(sizeof(*GMS.matbuf)*GMS.totmat, "GMS.matbuf");
879                 GMS.gmatbuf= MEM_callocN(sizeof(*GMS.gmatbuf)*GMS.totmat, "GMS.matbuf");
880                 GMS.blendmode= MEM_callocN(sizeof(*GMS.blendmode)*GMS.totmat, "GMS.matbuf");
881         }
882         else {
883                 GMS.matbuf= GMS.matbuf_fixed;
884                 GMS.gmatbuf= GMS.gmatbuf_fixed;
885                 GMS.blendmode= GMS.blendmode_fixed;
886         }
887
888         /* no materials assigned? */
889         if(ob->totcol==0) {
890                 GMS.matbuf[0][0][0]= (defmaterial.ref+defmaterial.emit)*defmaterial.r;
891                 GMS.matbuf[0][0][1]= (defmaterial.ref+defmaterial.emit)*defmaterial.g;
892                 GMS.matbuf[0][0][2]= (defmaterial.ref+defmaterial.emit)*defmaterial.b;
893                 GMS.matbuf[0][0][3]= 1.0;
894
895                 GMS.matbuf[0][1][0]= defmaterial.spec*defmaterial.specr;
896                 GMS.matbuf[0][1][1]= defmaterial.spec*defmaterial.specg;
897                 GMS.matbuf[0][1][2]= defmaterial.spec*defmaterial.specb;
898                 GMS.matbuf[0][1][3]= 1.0;
899                 
900                 /* do material 1 too, for displists! */
901                 QUATCOPY(GMS.matbuf[1][0], GMS.matbuf[0][0]);
902                 QUATCOPY(GMS.matbuf[1][1], GMS.matbuf[0][1]);
903
904                 if(glsl) {
905                         GMS.gmatbuf[0]= &defmaterial;
906                         GPU_material_from_blender(GMS.gscene, &defmaterial);
907                 }
908
909                 GMS.blendmode[0]= GPU_BLEND_SOLID;
910         }
911         
912         /* setup materials */
913         for(a=1; a<=ob->totcol; a++) {
914                 /* find a suitable material */
915                 ma= give_current_material(ob, a);
916                 if(!glsl) ma= gpu_active_node_material(ma);
917                 if(ma==NULL) ma= &defmaterial;
918
919                 /* create glsl material if requested */
920                 gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL;
921
922                 if(gpumat) {
923                         /* do glsl only if creating it succeed, else fallback */
924                         GMS.gmatbuf[a]= ma;
925                         blendmode = GPU_material_blend_mode(gpumat, ob->col);
926                 }
927                 else {
928                         /* fixed function opengl materials */
929                         if (ma->mode & MA_SHLESS) {
930                                 GMS.matbuf[a][0][0]= ma->r;
931                                 GMS.matbuf[a][0][1]= ma->g;
932                                 GMS.matbuf[a][0][2]= ma->b;
933                         } else {
934                                 GMS.matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r;
935                                 GMS.matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g;
936                                 GMS.matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b;
937
938                                 GMS.matbuf[a][1][0]= ma->spec*ma->specr;
939                                 GMS.matbuf[a][1][1]= ma->spec*ma->specg;
940                                 GMS.matbuf[a][1][2]= ma->spec*ma->specb;
941                                 GMS.matbuf[a][1][3]= 1.0;
942                         }
943
944                         blendmode = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
945                         if(do_alpha_pass && GMS.alphapass)
946                                 GMS.matbuf[a][0][3]= ma->alpha;
947                         else
948                                 GMS.matbuf[a][0][3]= 1.0f;
949                 }
950
951                 /* setting do_alpha_pass = 1 indicates this object needs to be
952                  * drawn in a second alpha pass for improved blending */
953                 if(do_alpha_pass) {
954                         GMS.blendmode[a]= blendmode;
955                         if(ELEM(blendmode, GPU_BLEND_ALPHA, GPU_BLEND_ADD) && !GMS.alphapass)
956                                 *do_alpha_pass= 1;
957                 }
958         }
959
960         /* let's start with a clean state */
961         GPU_disable_material();
962 }
963
964 int GPU_enable_material(int nr, void *attribs)
965 {
966         extern Material defmaterial; /* from material.c */
967         GPUVertexAttribs *gattribs = attribs;
968         GPUMaterial *gpumat;
969         GPUBlendMode blendmode;
970
971         /* no GPU_begin_object_materials, use default material */
972         if(!GMS.matbuf) {
973                 float diff[4], spec[4];
974
975                 memset(&GMS, 0, sizeof(GMS));
976
977                 diff[0]= (defmaterial.ref+defmaterial.emit)*defmaterial.r;
978                 diff[1]= (defmaterial.ref+defmaterial.emit)*defmaterial.g;
979                 diff[2]= (defmaterial.ref+defmaterial.emit)*defmaterial.b;
980                 diff[3]= 1.0;
981
982                 spec[0]= defmaterial.spec*defmaterial.specr;
983                 spec[1]= defmaterial.spec*defmaterial.specg;
984                 spec[2]= defmaterial.spec*defmaterial.specb;
985                 spec[3]= 1.0;
986
987                 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff);
988                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
989
990                 return 0;
991         }
992
993         /* prevent index to use un-initialized array items */
994         if(nr>=GMS.totmat)
995                 nr= 0;
996
997         if(gattribs)
998                 memset(gattribs, 0, sizeof(*gattribs));
999
1000         /* keep current material */
1001         if(nr==GMS.lastmatnr)
1002                 return GMS.lastretval;
1003
1004         /* unbind glsl material */
1005         if(GMS.gboundmat) {
1006                 if(GMS.alphapass) glDepthMask(0);
1007                 GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
1008                 GMS.gboundmat= NULL;
1009         }
1010
1011         /* draw materials with alpha in alpha pass */
1012         GMS.lastmatnr = nr;
1013         GMS.lastretval = ELEM(GMS.blendmode[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP);
1014         if(GMS.alphapass)
1015                 GMS.lastretval = !GMS.lastretval;
1016
1017         if(GMS.lastretval) {
1018                 if(gattribs && GMS.gmatbuf[nr]) {
1019                         /* bind glsl material and get attributes */
1020                         Material *mat = GMS.gmatbuf[nr];
1021
1022                         gpumat = GPU_material_from_blender(GMS.gscene, mat);
1023                         GPU_material_vertex_attributes(gpumat, gattribs);
1024                         GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT));
1025                         GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gviewinv, GMS.gob->col);
1026                         GMS.gboundmat= mat;
1027
1028                         if(GMS.alphapass) glDepthMask(1);
1029                 }
1030                 else {
1031                         /* or do fixed function opengl material */
1032                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, GMS.matbuf[nr][0]);
1033                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, GMS.matbuf[nr][1]);
1034                 }
1035
1036                 /* set (alpha) blending mode */
1037                 blendmode = (GMS.alphapass)? GPU_BLEND_ALPHA: GPU_BLEND_SOLID;
1038                 GPU_set_material_blend_mode(blendmode);
1039         }
1040
1041         return GMS.lastretval;
1042 }
1043
1044 void GPU_set_material_blend_mode(int blendmode)
1045 {
1046         if(GMS.lastblendmode == blendmode)
1047                 return;
1048         
1049         gpu_set_blend_mode(blendmode);
1050         GMS.lastblendmode = blendmode;
1051 }
1052
1053 int GPU_get_material_blend_mode(void)
1054 {
1055         return GMS.lastblendmode;
1056 }
1057
1058 void GPU_disable_material(void)
1059 {
1060         GMS.lastmatnr= -1;
1061         GMS.lastretval= 1;
1062
1063         if(GMS.gboundmat) {
1064                 if(GMS.alphapass) glDepthMask(0);
1065                 GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
1066                 GMS.gboundmat= NULL;
1067         }
1068
1069         GPU_set_material_blend_mode(GPU_BLEND_SOLID);
1070 }
1071
1072 void GPU_end_object_materials(void)
1073 {
1074         GPU_disable_material();
1075
1076         if(GMS.matbuf && GMS.matbuf != GMS.matbuf_fixed) {
1077                 MEM_freeN(GMS.matbuf);
1078                 MEM_freeN(GMS.gmatbuf);
1079                 MEM_freeN(GMS.blendmode);
1080         }
1081
1082         GMS.matbuf= NULL;
1083         GMS.gmatbuf= NULL;
1084         GMS.blendmode= NULL;
1085 }
1086
1087 /* Lights */
1088
1089 int GPU_default_lights(void)
1090 {
1091         int a, count = 0;
1092         
1093         /* initialize */
1094         if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) {
1095                 U.light[0].flag= 1;
1096                 U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9;
1097                 U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8;
1098                 U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5;
1099                 U.light[0].spec[3]= 1.0;
1100                 
1101                 U.light[1].flag= 0;
1102                 U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1;
1103                 U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8;
1104                 U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5;
1105                 U.light[1].spec[3]= 1.0;
1106         
1107                 U.light[2].flag= 0;
1108                 U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2;
1109                 U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4;
1110                 U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3;
1111                 U.light[2].spec[3]= 1.0;
1112         }
1113
1114         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
1115
1116         glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec); 
1117         glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col); 
1118         glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec); 
1119
1120         glLightfv(GL_LIGHT1, GL_POSITION, U.light[1].vec); 
1121         glLightfv(GL_LIGHT1, GL_DIFFUSE, U.light[1].col); 
1122         glLightfv(GL_LIGHT1, GL_SPECULAR, U.light[1].spec); 
1123
1124         glLightfv(GL_LIGHT2, GL_POSITION, U.light[2].vec); 
1125         glLightfv(GL_LIGHT2, GL_DIFFUSE, U.light[2].col); 
1126         glLightfv(GL_LIGHT2, GL_SPECULAR, U.light[2].spec); 
1127
1128         for(a=0; a<8; a++) {
1129                 if(a<3) {
1130                         if(U.light[a].flag) {
1131                                 glEnable(GL_LIGHT0+a);
1132                                 count++;
1133                         }
1134                         else
1135                                 glDisable(GL_LIGHT0+a);
1136                         
1137                         // clear stuff from other opengl lamp usage
1138                         glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0);
1139                         glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0);
1140                         glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0);
1141                 }
1142                 else
1143                         glDisable(GL_LIGHT0+a);
1144         }
1145         
1146         glDisable(GL_LIGHTING);
1147
1148         glDisable(GL_COLOR_MATERIAL);
1149
1150         return count;
1151 }
1152
1153 int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4], int ortho)
1154 {
1155         Base *base;
1156         Lamp *la;
1157         int count;
1158         float position[4], direction[4], energy[4];
1159         
1160         /* disable all lights */
1161         for(count=0; count<8; count++)
1162                 glDisable(GL_LIGHT0+count);
1163         
1164         /* view direction for specular is not compute correct by default in
1165          * opengl, so we set the settings ourselfs */
1166         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (ortho)? GL_FALSE: GL_TRUE);
1167
1168         count= 0;
1169         
1170         for(base=scene->base.first; base; base=base->next) {
1171                 if(base->object->type!=OB_LAMP)
1172                         continue;
1173
1174                 if(!(base->lay & lay) || !(base->lay & ob->lay))
1175                         continue;
1176
1177                 la= base->object->data;
1178                 
1179                 /* setup lamp transform */
1180                 glPushMatrix();
1181                 glLoadMatrixf((float *)viewmat);
1182                 
1183                 where_is_object_simul(scene, base->object);
1184                 
1185                 if(la->type==LA_SUN) {
1186                         /* sun lamp */
1187                         VECCOPY(direction, base->object->obmat[2]);
1188                         direction[3]= 0.0;
1189
1190                         glLightfv(GL_LIGHT0+count, GL_POSITION, direction); 
1191                 }
1192                 else {
1193                         /* other lamps with attenuation */
1194                         VECCOPY(position, base->object->obmat[3]);
1195                         position[3]= 1.0f;
1196
1197                         glLightfv(GL_LIGHT0+count, GL_POSITION, position); 
1198                         glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0);
1199                         glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist);
1200                         glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist));
1201                         
1202                         if(la->type==LA_SPOT) {
1203                                 /* spot lamp */
1204                                 direction[0]= -base->object->obmat[2][0];
1205                                 direction[1]= -base->object->obmat[2][1];
1206                                 direction[2]= -base->object->obmat[2][2];
1207                                 glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, direction);
1208                                 glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0);
1209                                 glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0*la->spotblend);
1210                         }
1211                         else
1212                                 glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0);
1213                 }
1214                 
1215                 /* setup energy */
1216                 energy[0]= la->energy*la->r;
1217                 energy[1]= la->energy*la->g;
1218                 energy[2]= la->energy*la->b;
1219                 energy[3]= 1.0;
1220
1221                 glLightfv(GL_LIGHT0+count, GL_DIFFUSE, energy); 
1222                 glLightfv(GL_LIGHT0+count, GL_SPECULAR, energy);
1223                 glEnable(GL_LIGHT0+count);
1224                 
1225                 glPopMatrix();                                  
1226                 
1227                 count++;
1228                 if(count==8)
1229                         break;
1230         }
1231
1232         return count;
1233 }
1234
1235 /* Default OpenGL State */
1236
1237 void GPU_state_init(void)
1238 {
1239         /* also called when doing opengl rendering and in the game engine */
1240         float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 };
1241         float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
1242         float mat_shininess[] = { 35.0 };
1243         int a, x, y;
1244         GLubyte pat[32*32];
1245         const GLubyte *patc= pat;
1246         
1247         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
1248         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
1249         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
1250         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
1251
1252         GPU_default_lights();
1253         
1254         glDepthFunc(GL_LEQUAL);
1255         /* scaling matrices */
1256         glEnable(GL_NORMALIZE);
1257
1258         glShadeModel(GL_FLAT);
1259
1260         glDisable(GL_ALPHA_TEST);
1261         glDisable(GL_BLEND);
1262         glDisable(GL_DEPTH_TEST);
1263         glDisable(GL_FOG);
1264         glDisable(GL_LIGHTING);
1265         glDisable(GL_LOGIC_OP);
1266         glDisable(GL_STENCIL_TEST);
1267         glDisable(GL_TEXTURE_1D);
1268         glDisable(GL_TEXTURE_2D);
1269
1270         /* default on, disable/enable should be local per function */
1271         glEnableClientState(GL_VERTEX_ARRAY);
1272         glEnableClientState(GL_NORMAL_ARRAY);
1273         
1274         glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
1275         glPixelTransferi(GL_RED_SCALE, 1);
1276         glPixelTransferi(GL_RED_BIAS, 0);
1277         glPixelTransferi(GL_GREEN_SCALE, 1);
1278         glPixelTransferi(GL_GREEN_BIAS, 0);
1279         glPixelTransferi(GL_BLUE_SCALE, 1);
1280         glPixelTransferi(GL_BLUE_BIAS, 0);
1281         glPixelTransferi(GL_ALPHA_SCALE, 1);
1282         glPixelTransferi(GL_ALPHA_BIAS, 0);
1283         
1284         glPixelTransferi(GL_DEPTH_BIAS, 0);
1285         glPixelTransferi(GL_DEPTH_SCALE, 1);
1286         glDepthRange(0.0, 1.0);
1287         
1288         a= 0;
1289         for(x=0; x<32; x++) {
1290                 for(y=0; y<4; y++) {
1291                         if( (x) & 1) pat[a++]= 0x88;
1292                         else pat[a++]= 0x22;
1293                 }
1294         }
1295         
1296         glPolygonStipple(patc);
1297
1298         glMatrixMode(GL_TEXTURE);
1299         glLoadIdentity();
1300         glMatrixMode(GL_MODELVIEW);
1301
1302         glFrontFace(GL_CCW);
1303         glCullFace(GL_BACK);
1304         glDisable(GL_CULL_FACE);
1305 }
1306