]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/colors.cpp
Initial revision
[taylor/freespace2.git] / src / graphics / colors.cpp
1 /*
2  * $Logfile: /Freespace2/code/Graphics/Colors.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Functions to deal with colors & alphacolors
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:09  root
11  * Initial revision
12  *
13  * 
14  * 7     7/08/99 10:52a Dave
15  * New multiplayer interpolation scheme. Not 100% done yet, but still
16  * better than the old way.
17  * 
18  * 6     1/14/99 12:48a Dave
19  * Todo list bug fixes. Made a pass at putting briefing icons back into
20  * FRED. Sort of works :(
21  * 
22  * 5     12/02/98 5:47p Dave
23  * Put in interface xstr code. Converted barracks screen to new format.
24  * 
25  * 4     11/30/98 5:31p Dave
26  * Fixed up Fred support for software mode.
27  * 
28  * 3     11/30/98 1:07p Dave
29  * 16 bit conversion, first run.
30  * 
31  * 2     10/07/98 10:52a Dave
32  * Initial checkin.
33  * 
34  * 1     10/07/98 10:48a Dave
35  * 
36  * 35    5/19/98 3:32p John
37  * upped alpha colors
38  * 
39  * 34    5/13/98 10:22p John
40  * Added cfile functions to read/write rle compressed blocks of data.
41  * Made palman use it for .clr files.  Made alphacolors calculate on the
42  * fly rather than caching to/from disk.
43  * 
44  * 33    4/30/98 4:53p John
45  * Restructured and cleaned up cfile code.  Added capability to read off
46  * of CD-ROM drive and out of multiple pack files.
47  * 
48  * 32    4/10/98 5:20p John
49  * Changed RGB in lighting structure to be ubytes.  Removed old
50  * not-necessary 24 bpp software stuff.
51  * 
52  * 31    4/09/98 11:04p John
53  * Changed ID's in output files to make more sense.
54  * 
55  * 30    4/01/98 3:05p Adam
56  * Reduced gamma on text.
57  * 
58  * 29    3/29/98 2:36p John
59  * fixed bug with reloading fullscreen colros
60  * 
61  * 28    3/25/98 8:07p John
62  * Restructured software rendering into two modules; One for windowed
63  * debug mode and one for DirectX fullscreen.   
64  * 
65  * 27    3/24/98 4:22p John
66  * fixed warning
67  * 
68  * 26    3/24/98 3:58p John
69  * Put in (hopefully) final gamma setting code.
70  * 
71  * 25    3/10/98 4:18p John
72  * Cleaned up graphics lib.  Took out most unused gr functions.   Made D3D
73  * & Glide have popups and print screen.  Took out all >8bpp software
74  * support.  Made Fred zbuffer.  Made zbuffer allocate dynamically to
75  * support Fred.  Made zbuffering key off of functions rather than one
76  * global variable.
77  * 
78  * 24    2/07/98 7:50p John
79  * Added code so that we can use the old blending type of alphacolors if
80  * we want to.  Made the stars use them.
81  * 
82  * 23    1/13/98 10:20a John
83  * Added code to support "glass" in alphacolors
84  * 
85  * 22    1/02/98 9:10p Lawrance
86  * Big changes to how colors get set on the HUD.
87  * 
88  * 21    12/30/97 4:32p John
89  * 
90  * 20    12/02/97 3:59p John
91  * Added first rev of thruster glow, along with variable levels of
92  * translucency, which retquired some restructing of palman.
93  * 
94  * 19    11/30/97 4:26p John
95  * Added 32-bpp antialiased line.   Took gamma out of alphacolor
96  * calculation.
97  * 
98  * 18    11/29/97 2:06p John
99  * added mode 16-bpp support
100  * 
101  * 17    11/21/97 11:32a John
102  * Added nebulas.   Fixed some warpout bugs.
103  * 
104  * 16    11/14/97 12:30p John
105  * Fixed some DirectX bugs.  Moved the 8-16 xlat tables into Graphics
106  * libs.  Made 16-bpp DirectX modes know what bitmap format they're in.
107  * 
108  * 15    11/05/97 11:20p Lawrance
109  * increase number of alpha colors to 52
110  * 
111  * 14    11/04/97 6:32p Hoffoss
112  * Changes to hotkey screen.  Needed to add new colors for
113  * Color_text_active*.
114  * 
115  * 13    10/31/97 10:47a John
116  * upped clr version to force rebuild after changing palette code.
117  * 
118  * 12    10/14/97 4:50p John
119  * more 16 bpp stuff.
120  * 
121  * 11    10/14/97 8:08a John
122  * added a bunch more 16 bit support
123  * 
124  * 10    10/09/97 5:23p John
125  * Added support for more 16-bpp functions
126  * 
127  * 9     10/03/97 9:10a John
128  * added better antialiased line drawer
129  * 
130  * 8     9/20/97 8:16a John
131  * Made .clr files go into the Cache directory. Replaced cfopen(name,NULL)
132  * to delete a file with cf_delete.
133  * 
134  * 7     9/09/97 10:46a Sandeep
135  * fixed warning level 4
136  * 
137  * 6     7/18/97 12:40p John
138  * cached alphacolors to disk.  Also made cfopen be able to delete a file
139  * by passing NULL for mode.
140  * 
141  * 5     7/16/97 3:07p John
142  * 
143  * 4     6/18/97 12:07p John
144  * fixed some color bugs
145  * 
146  * 3     6/18/97 9:46a John
147  * added first rev of d3d shader.   Made HUD target use medium detail
148  * models.  Took out some color debug messages.
149  * 
150  * 2     6/17/97 7:04p John
151  * added d3d support for gradients.
152  * fixed some color bugs by adding screen signatures instead of watching
153  * flags and palette changes.
154  * 
155  * 1     6/17/97 12:01p John
156  *
157  * $NoKeywords: $
158  */
159
160 #include "pstypes.h"
161 #include "2d.h"
162 #include "grinternal.h"
163 #include "colors.h"
164 #include "palman.h"
165 #include "cfile.h"
166 #include "systemvars.h"
167
168 //#define MAX_ALPHACOLORS 36
169 #define MAX_ALPHACOLORS 72
170
171 alphacolor Alphacolors[MAX_ALPHACOLORS];
172 static int Alphacolors_intited = 0;
173
174 alphacolor * Current_alphacolor = NULL;
175
176
177 void calc_alphacolor_hud_type( alphacolor * ac )
178 {
179 #ifndef HARDWARE_ONLY
180         int i,j;
181         int tr,tg,tb, Sr, Sg, Sb;
182         ubyte * pal;
183         int r, g, b, alpha;
184         float falpha;
185
186         Assert(Alphacolors_intited);
187
188 //      mprintf(( "Calculating alphacolor for %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha ));
189
190         falpha = i2fl(ac->alpha)/255.0f;
191         if ( falpha<0.0f ) falpha = 0.0f; else if ( falpha > 1.0f ) falpha = 1.0f;
192
193         alpha = ac->alpha >> 4;
194         if (alpha < 0 ) alpha = 0; else if (alpha > 15 ) alpha = 15;
195         r = ac->r;
196         if (r < 0 ) r = 0; else if (r > 255 ) r = 255;
197         g = ac->g;
198         if (g < 0 ) g = 0; else if (g > 255 ) g = 255;
199         b = ac->b;
200         if (b < 0 ) b = 0; else if (b > 255 ) b = 255;
201
202         int ii[16];
203
204         for (j=1; j<15; j++ )   {
205
206                 // JAS: Use 1.5/Gamma instead of 1/Gamma because on Adam's
207                 // PC a gamma of 1.2 makes text look good, but his gamma is
208                 // really 1.8.   1.8/1.2 = 1.5
209                 float factor = falpha * (float)pow(i2fl(j)/14.0f, 1.5f/Gr_gamma);
210                 //float factor = i2fl(j)/14.0f;
211
212                 tr = fl2i( i2fl(r) * factor );
213                 tg = fl2i( i2fl(g) * factor );
214                 tb = fl2i( i2fl(b) * factor );
215
216                 ii[j] = tr;
217                 if ( tg > ii[j] )       ii[j] = tg;
218                 if ( tb > ii[j] )       ii[j] = tb;
219         }
220
221         pal = gr_palette;
222
223         int m = r;
224         if ( g > m ) m = g;
225         if ( b > m ) m = b;
226
227         ubyte ri[256], gi[256], bi[256];
228
229         if ( m > 0 )    {
230                 for (i=0; i<256; i++ )  {
231                         ri[i] = ubyte((i*r)/m);
232                         gi[i] = ubyte((i*g)/m);
233                         bi[i] = ubyte((i*b)/m);
234                 }
235         } else {
236                 for (i=0; i<256; i++ )  {
237                         ri[i] = 0;
238                         gi[i] = 0;
239                         bi[i] = 0;
240                 }
241         }
242
243         for (i=0; i<256; i++ )  {
244                 Sr = pal[0];
245                 Sg = pal[1];
246                 Sb = pal[2];
247                 pal += 3;
248
249                 int dst_intensity = Sr;
250                 if ( Sg > dst_intensity ) dst_intensity = Sg;
251                 if ( Sb > dst_intensity ) dst_intensity = Sb;
252
253                 ac->table.lookup[0][i] = (unsigned char)i;
254
255                 for (j=1; j<15; j++ )   {
256
257                         int tmp_i = max( ii[j], dst_intensity );
258
259                         ac->table.lookup[j][i] = (unsigned char)palette_find(ri[tmp_i],gi[tmp_i],bi[tmp_i]);
260                 }
261
262                 float di = (i2fl(Sr)*.30f+i2fl(Sg)*0.60f+i2fl(Sb)*.10f)/255.0f;
263                 float factor = 0.0f + di*0.75f;
264
265                 tr = fl2i( factor*i2fl(r)*falpha );
266                 tg = fl2i( factor*i2fl(g)*falpha );
267                 tb = fl2i( factor*i2fl(b)*falpha );
268
269                 if ( tr > 255 ) tr = 255; else if ( tr < 0 ) tr = 0;
270                 if ( tg > 255 ) tg = 255; else if ( tg < 0 ) tg = 0; 
271                 if ( tb > 255 ) tb = 255; else if ( tb < 0 ) tb = 0;
272
273                 ac->table.lookup[15][i] = (unsigned char)palette_find(tr,tg,tb);
274                 //ac->table.lookup[15][i] = (unsigned char)palette_find(255,0,0);
275
276         }
277 #endif
278 }
279
280 // Old way to calculate alpha colors
281
282 void calc_alphacolor_blend_type( alphacolor * ac )
283 {
284 #ifndef HARDWARE_ONLY
285         int i,j;
286         int tr,tg,tb, Sr, Sg, Sb;
287         int Dr, Dg, Db;
288         ubyte * pal;
289         int r, g, b, alpha;
290
291         Assert(Alphacolors_intited);
292
293 //      mprintf(( "Calculating alphacolor for %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha ));
294
295         alpha = ac->alpha >> 4;
296         if (alpha < 0 ) alpha = 0; else if (alpha > 15 ) alpha = 15;
297         r = ac->r;
298         if (r < 0 ) r = 0; else if (r > 255 ) r = 255;
299         g = ac->g;
300         if (g < 0 ) g = 0; else if (g > 255 ) g = 255;
301         b = ac->b;
302         if (b < 0 ) b = 0; else if (b > 255 ) b = 255;
303
304         int gamma_j1[16];
305
306         for (j=1; j<16; j++ )   {
307                 // JAS: Use 1.5/Gamma instead of 1/Gamma because on Adam's
308                 // PC a gamma of 1.2 makes text look good, but his gamma is
309                 // really 1.8.   1.8/1.2 = 1.5
310                 gamma_j1[j] = (int)((pow(i2fl(j)/15.0f, 1.5f/Gr_gamma)*16.0f) + 0.5);
311         }
312
313         pal = gr_palette;
314
315         for (i=0; i<256; i++ )  {
316                 Sr = pal[0];
317                 Sg = pal[1];
318                 Sb = pal[2];
319                 pal += 3;
320         
321                 Dr = ( Sr*(16-alpha) + (r*alpha) ) >> 4;
322                 Dg = ( Sg*(16-alpha) + (g*alpha) ) >> 4;
323                 Db = ( Sb*(16-alpha) + (b*alpha) ) >> 4;
324
325                 ac->table.lookup[0][i] = (unsigned char)i;
326
327                 for (j=1; j<16; j++ )   {
328
329                         int j1 = gamma_j1[j];
330
331                         tr = ( Sr*(16-j1) + (Dr*j1) ) >> 4;
332                         tg = ( Sg*(16-j1) + (Dg*j1) ) >> 4;
333                         tb = ( Sb*(16-j1) + (Db*j1) ) >> 4;
334
335                         if ( tr > 255 ) tr = 255; else if ( tr < 0 ) tr = 0;
336                         if ( tg > 255 ) tg = 255; else if ( tg < 0 ) tg = 0; 
337                         if ( tb > 255 ) tb = 255; else if ( tb < 0 ) tb = 0;
338
339                         ac->table.lookup[j][i] = (unsigned char)palette_find(tr,tg,tb);
340                 }
341         }
342 #endif
343 }
344
345 void calc_alphacolor( alphacolor * ac )
346 {
347         switch(ac->type)        {
348         case AC_TYPE_HUD:
349                 calc_alphacolor_hud_type(ac);
350                 break;
351         case AC_TYPE_BLEND:
352                 calc_alphacolor_blend_type(ac);
353                 break;
354         default:
355                 Int3();         // Passing an invalid type of alphacolor!
356         }
357 }
358
359 void grx_init_alphacolors()
360 {
361         int i;
362         
363         Alphacolors_intited = 1;
364
365         for (i=0; i<MAX_ALPHACOLORS; i++ )      {
366                 Alphacolors[i].used = 0;
367                 Alphacolors[i].clr = NULL;
368         }
369
370         Current_alphacolor = NULL;
371 }
372
373
374
375 void grx_init_alphacolor( color *clr, int r, int g, int b, int alpha, int type )
376 {
377         int n;
378         alphacolor *ac;
379         
380         if(Game_mode & GM_STANDALONE_SERVER){
381                 return;
382         }
383
384         if (!Alphacolors_intited) return;
385
386         if ( alpha < 0 ) alpha = 0;
387         if ( alpha > 255 ) alpha = 255;
388
389         n = -1;
390         if ( (clr->magic == 0xAC01) && (clr->is_alphacolor) )   {
391                 if ( (clr->alphacolor >= 0) && (clr->alphacolor < MAX_ALPHACOLORS))     {
392                         if ( Alphacolors[clr->alphacolor].used && (Alphacolors[clr->alphacolor].clr==clr) )     {
393                                 n = clr->alphacolor;
394                         }
395                 }
396         }
397
398         int changed = 0;
399
400         if ( n==-1 )    {
401                 for (n=0; n<MAX_ALPHACOLORS; n++ )      {
402                         if (!Alphacolors[n].used) break;
403                 }
404                 if ( n == MAX_ALPHACOLORS )     
405                         Error( LOCATION, "Out of alphacolors!\n" );
406         } else {
407                 changed = 1;
408         }
409
410
411         // Create the alphacolor
412         ac = &Alphacolors[n];
413
414         if ( changed && (ac->r!=r || ac->g!=g || ac->b!=b || ac->alpha!=alpha || ac->type != type ) )   {
415                 // we're changing the color, so delete the old cache file
416                 //mprintf(( "Changing ac from %d,%d,%d,%d to %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha, r, g, b, alpha ));
417                 //ac_delete_cached(ac);
418         }
419
420         ac->used = 1;
421         ac->r = r;
422         ac->g = g;
423         ac->b = b;
424         ac->alpha = alpha;
425         ac->type = type;
426         ac->clr=clr;
427         
428         calc_alphacolor(ac);
429
430         grx_init_color( clr, r, g, b );
431
432         // Link the alphacolor to the color
433         clr->alpha = (unsigned char)alpha;
434         clr->ac_type = (ubyte)type;
435         clr->alphacolor = n;
436         clr->is_alphacolor = 1;
437 }
438
439
440 void grx_get_color( int * r, int * g, int * b )
441 {
442         if (r) *r = gr_screen.current_color.red;
443         if (g) *g = gr_screen.current_color.green;
444         if (b) *b = gr_screen.current_color.blue;
445 }
446
447 void grx_init_color( color * dst, int r, int g, int b )
448 {
449         dst->screen_sig = gr_screen.signature;
450         dst->red = (unsigned char)r;
451         dst->green = (unsigned char)g;
452         dst->blue = (unsigned char)b;
453         dst->alpha = 255;
454         dst->ac_type = AC_TYPE_NONE;
455         dst->is_alphacolor = 0;
456         dst->alphacolor = -1;
457         dst->magic = 0xAC01;
458
459         dst->raw8 = (unsigned char)palette_find( r, g, b );
460 }
461
462 void grx_set_color_fast( color * dst )
463 {
464         if ( dst->magic != 0xAC01 ) return;
465
466         if ( dst->screen_sig != gr_screen.signature )   {
467                 if ( dst->is_alphacolor )       {
468                         grx_init_alphacolor( dst, dst->red, dst->green, dst->blue, dst->alpha, dst->ac_type );
469                 } else {
470                         grx_init_color( dst, dst->red, dst->green, dst->blue );
471                 }
472         }
473
474         gr_screen.current_color = *dst;
475         
476         if ( dst->is_alphacolor )       {
477                 Assert( dst->alphacolor > -1 );
478                 Assert( dst->alphacolor <= MAX_ALPHACOLORS );
479                 Assert( Alphacolors[dst->alphacolor].used );
480
481                 // Current_alphacolor = &Alphacolors[dst->alphacolor];
482                 Current_alphacolor = NULL;
483         } else {
484                 Current_alphacolor = NULL;
485         }
486 }
487
488
489 void grx_set_color( int r, int g, int b )
490 {
491         Assert((r >= 0) && (r < 256));
492         Assert((g >= 0) && (g < 256));
493         Assert((b >= 0) && (b < 256));
494
495 //      if ( r!=0 || g!=0 || b!=0 )     {
496 //              mprintf(( "Setcolor: %d,%d,%d\n", r,g,b ));
497 //      }
498         grx_init_color( &gr_screen.current_color, r, g, b );
499         Current_alphacolor = NULL;
500 }
501
502 void calc_alphacolor_hud_type_old( alphacolor_old * ac )
503 {
504         int i,j;
505         int tr,tg,tb, Sr, Sg, Sb;
506         ubyte * pal;
507         int r, g, b, alpha;
508         float falpha;
509
510         // Assert(Alphacolors_intited);
511
512 //      mprintf(( "Calculating alphacolor for %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha ));
513
514         falpha = i2fl(ac->alpha)/255.0f;
515         if ( falpha<0.0f ) falpha = 0.0f; else if ( falpha > 1.0f ) falpha = 1.0f;
516
517         alpha = ac->alpha >> 4;
518         if (alpha < 0 ) alpha = 0; else if (alpha > 15 ) alpha = 15;
519         r = ac->r;
520         if (r < 0 ) r = 0; else if (r > 255 ) r = 255;
521         g = ac->g;
522         if (g < 0 ) g = 0; else if (g > 255 ) g = 255;
523         b = ac->b;
524         if (b < 0 ) b = 0; else if (b > 255 ) b = 255;
525
526         int ii[16];
527
528         for (j=1; j<15; j++ )   {
529
530                 // JAS: Use 1.5/Gamma instead of 1/Gamma because on Adam's
531                 // PC a gamma of 1.2 makes text look good, but his gamma is
532                 // really 1.8.   1.8/1.2 = 1.5
533                 float factor = falpha * (float)pow(i2fl(j)/14.0f, 1.5f/Gr_gamma);
534                 //float factor = i2fl(j)/14.0f;
535
536                 tr = fl2i( i2fl(r) * factor );
537                 tg = fl2i( i2fl(g) * factor );
538                 tb = fl2i( i2fl(b) * factor );
539
540                 ii[j] = tr;
541                 if ( tg > ii[j] )       ii[j] = tg;
542                 if ( tb > ii[j] )       ii[j] = tb;
543         }
544
545         pal = gr_palette;
546
547         int m = r;
548         if ( g > m ) m = g;
549         if ( b > m ) m = b;
550
551         ubyte ri[256], gi[256], bi[256];
552
553         if ( m > 0 )    {
554                 for (i=0; i<256; i++ )  {
555                         ri[i] = ubyte((i*r)/m);
556                         gi[i] = ubyte((i*g)/m);
557                         bi[i] = ubyte((i*b)/m);
558                 }
559         } else {
560                 for (i=0; i<256; i++ )  {
561                         ri[i] = 0;
562                         gi[i] = 0;
563                         bi[i] = 0;
564                 }
565         }
566
567         for (i=0; i<256; i++ )  {
568                 Sr = pal[0];
569                 Sg = pal[1];
570                 Sb = pal[2];
571                 pal += 3;
572
573                 int dst_intensity = Sr;
574                 if ( Sg > dst_intensity ) dst_intensity = Sg;
575                 if ( Sb > dst_intensity ) dst_intensity = Sb;
576
577                 ac->table.lookup[0][i] = (unsigned char)i;
578
579                 for (j=1; j<15; j++ )   {
580
581                         int tmp_i = max( ii[j], dst_intensity );
582
583                         ac->table.lookup[j][i] = (unsigned char)palette_find(ri[tmp_i],gi[tmp_i],bi[tmp_i]);
584                 }
585
586                 float di = (i2fl(Sr)*.30f+i2fl(Sg)*0.60f+i2fl(Sb)*.10f)/255.0f;
587                 float factor = 0.0f + di*0.75f;
588
589                 tr = fl2i( factor*i2fl(r)*falpha );
590                 tg = fl2i( factor*i2fl(g)*falpha );
591                 tb = fl2i( factor*i2fl(b)*falpha );
592
593                 if ( tr > 255 ) tr = 255; else if ( tr < 0 ) tr = 0;
594                 if ( tg > 255 ) tg = 255; else if ( tg < 0 ) tg = 0; 
595                 if ( tb > 255 ) tb = 255; else if ( tb < 0 ) tb = 0;
596
597                 ac->table.lookup[15][i] = (unsigned char)palette_find(tr,tg,tb);
598                 //ac->table.lookup[15][i] = (unsigned char)palette_find(255,0,0);
599         }
600 }
601
602 void calc_alphacolor_old(alphacolor_old *ac)
603 {
604         Assert(Fred_running);
605         calc_alphacolor_hud_type_old(ac);
606 }