2 * $Logfile: /Freespace2/code/Graphics/Colors.cpp $
7 * Functions to deal with colors & alphacolors
10 * Revision 1.1 2002/05/03 03:28:09 root
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.
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 :(
22 * 5 12/02/98 5:47p Dave
23 * Put in interface xstr code. Converted barracks screen to new format.
25 * 4 11/30/98 5:31p Dave
26 * Fixed up Fred support for software mode.
28 * 3 11/30/98 1:07p Dave
29 * 16 bit conversion, first run.
31 * 2 10/07/98 10:52a Dave
34 * 1 10/07/98 10:48a Dave
36 * 35 5/19/98 3:32p John
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.
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.
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.
52 * 31 4/09/98 11:04p John
53 * Changed ID's in output files to make more sense.
55 * 30 4/01/98 3:05p Adam
56 * Reduced gamma on text.
58 * 29 3/29/98 2:36p John
59 * fixed bug with reloading fullscreen colros
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.
65 * 27 3/24/98 4:22p John
68 * 26 3/24/98 3:58p John
69 * Put in (hopefully) final gamma setting code.
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
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.
82 * 23 1/13/98 10:20a John
83 * Added code to support "glass" in alphacolors
85 * 22 1/02/98 9:10p Lawrance
86 * Big changes to how colors get set on the HUD.
88 * 21 12/30/97 4:32p John
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.
94 * 19 11/30/97 4:26p John
95 * Added 32-bpp antialiased line. Took gamma out of alphacolor
98 * 18 11/29/97 2:06p John
99 * added mode 16-bpp support
101 * 17 11/21/97 11:32a John
102 * Added nebulas. Fixed some warpout bugs.
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.
108 * 15 11/05/97 11:20p Lawrance
109 * increase number of alpha colors to 52
111 * 14 11/04/97 6:32p Hoffoss
112 * Changes to hotkey screen. Needed to add new colors for
113 * Color_text_active*.
115 * 13 10/31/97 10:47a John
116 * upped clr version to force rebuild after changing palette code.
118 * 12 10/14/97 4:50p John
121 * 11 10/14/97 8:08a John
122 * added a bunch more 16 bit support
124 * 10 10/09/97 5:23p John
125 * Added support for more 16-bpp functions
127 * 9 10/03/97 9:10a John
128 * added better antialiased line drawer
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.
134 * 7 9/09/97 10:46a Sandeep
135 * fixed warning level 4
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.
141 * 5 7/16/97 3:07p John
143 * 4 6/18/97 12:07p John
144 * fixed some color bugs
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.
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.
155 * 1 6/17/97 12:01p John
162 #include "grinternal.h"
166 #include "systemvars.h"
168 //#define MAX_ALPHACOLORS 36
169 #define MAX_ALPHACOLORS 72
171 alphacolor Alphacolors[MAX_ALPHACOLORS];
172 static int Alphacolors_intited = 0;
174 alphacolor * Current_alphacolor = NULL;
177 void calc_alphacolor_hud_type( alphacolor * ac )
179 #ifndef HARDWARE_ONLY
181 int tr,tg,tb, Sr, Sg, Sb;
186 Assert(Alphacolors_intited);
188 // mprintf(( "Calculating alphacolor for %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha ));
190 falpha = i2fl(ac->alpha)/255.0f;
191 if ( falpha<0.0f ) falpha = 0.0f; else if ( falpha > 1.0f ) falpha = 1.0f;
193 alpha = ac->alpha >> 4;
194 if (alpha < 0 ) alpha = 0; else if (alpha > 15 ) alpha = 15;
196 if (r < 0 ) r = 0; else if (r > 255 ) r = 255;
198 if (g < 0 ) g = 0; else if (g > 255 ) g = 255;
200 if (b < 0 ) b = 0; else if (b > 255 ) b = 255;
204 for (j=1; j<15; j++ ) {
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;
212 tr = fl2i( i2fl(r) * factor );
213 tg = fl2i( i2fl(g) * factor );
214 tb = fl2i( i2fl(b) * factor );
217 if ( tg > ii[j] ) ii[j] = tg;
218 if ( tb > ii[j] ) ii[j] = tb;
227 ubyte ri[256], gi[256], bi[256];
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);
236 for (i=0; i<256; i++ ) {
243 for (i=0; i<256; i++ ) {
249 int dst_intensity = Sr;
250 if ( Sg > dst_intensity ) dst_intensity = Sg;
251 if ( Sb > dst_intensity ) dst_intensity = Sb;
253 ac->table.lookup[0][i] = (unsigned char)i;
255 for (j=1; j<15; j++ ) {
257 int tmp_i = max( ii[j], dst_intensity );
259 ac->table.lookup[j][i] = (unsigned char)palette_find(ri[tmp_i],gi[tmp_i],bi[tmp_i]);
262 float di = (i2fl(Sr)*.30f+i2fl(Sg)*0.60f+i2fl(Sb)*.10f)/255.0f;
263 float factor = 0.0f + di*0.75f;
265 tr = fl2i( factor*i2fl(r)*falpha );
266 tg = fl2i( factor*i2fl(g)*falpha );
267 tb = fl2i( factor*i2fl(b)*falpha );
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;
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);
280 // Old way to calculate alpha colors
282 void calc_alphacolor_blend_type( alphacolor * ac )
284 #ifndef HARDWARE_ONLY
286 int tr,tg,tb, Sr, Sg, Sb;
291 Assert(Alphacolors_intited);
293 // mprintf(( "Calculating alphacolor for %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha ));
295 alpha = ac->alpha >> 4;
296 if (alpha < 0 ) alpha = 0; else if (alpha > 15 ) alpha = 15;
298 if (r < 0 ) r = 0; else if (r > 255 ) r = 255;
300 if (g < 0 ) g = 0; else if (g > 255 ) g = 255;
302 if (b < 0 ) b = 0; else if (b > 255 ) b = 255;
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);
315 for (i=0; i<256; i++ ) {
321 Dr = ( Sr*(16-alpha) + (r*alpha) ) >> 4;
322 Dg = ( Sg*(16-alpha) + (g*alpha) ) >> 4;
323 Db = ( Sb*(16-alpha) + (b*alpha) ) >> 4;
325 ac->table.lookup[0][i] = (unsigned char)i;
327 for (j=1; j<16; j++ ) {
329 int j1 = gamma_j1[j];
331 tr = ( Sr*(16-j1) + (Dr*j1) ) >> 4;
332 tg = ( Sg*(16-j1) + (Dg*j1) ) >> 4;
333 tb = ( Sb*(16-j1) + (Db*j1) ) >> 4;
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;
339 ac->table.lookup[j][i] = (unsigned char)palette_find(tr,tg,tb);
345 void calc_alphacolor( alphacolor * ac )
349 calc_alphacolor_hud_type(ac);
352 calc_alphacolor_blend_type(ac);
355 Int3(); // Passing an invalid type of alphacolor!
359 void grx_init_alphacolors()
363 Alphacolors_intited = 1;
365 for (i=0; i<MAX_ALPHACOLORS; i++ ) {
366 Alphacolors[i].used = 0;
367 Alphacolors[i].clr = NULL;
370 Current_alphacolor = NULL;
375 void grx_init_alphacolor( color *clr, int r, int g, int b, int alpha, int type )
380 if(Game_mode & GM_STANDALONE_SERVER){
384 if (!Alphacolors_intited) return;
386 if ( alpha < 0 ) alpha = 0;
387 if ( alpha > 255 ) alpha = 255;
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) ) {
401 for (n=0; n<MAX_ALPHACOLORS; n++ ) {
402 if (!Alphacolors[n].used) break;
404 if ( n == MAX_ALPHACOLORS )
405 Error( LOCATION, "Out of alphacolors!\n" );
411 // Create the alphacolor
412 ac = &Alphacolors[n];
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);
430 grx_init_color( clr, r, g, b );
432 // Link the alphacolor to the color
433 clr->alpha = (unsigned char)alpha;
434 clr->ac_type = (ubyte)type;
436 clr->is_alphacolor = 1;
440 void grx_get_color( int * r, int * g, int * b )
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;
447 void grx_init_color( color * dst, int r, int g, int b )
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;
454 dst->ac_type = AC_TYPE_NONE;
455 dst->is_alphacolor = 0;
456 dst->alphacolor = -1;
459 dst->raw8 = (unsigned char)palette_find( r, g, b );
462 void grx_set_color_fast( color * dst )
464 if ( dst->magic != 0xAC01 ) return;
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 );
470 grx_init_color( dst, dst->red, dst->green, dst->blue );
474 gr_screen.current_color = *dst;
476 if ( dst->is_alphacolor ) {
477 Assert( dst->alphacolor > -1 );
478 Assert( dst->alphacolor <= MAX_ALPHACOLORS );
479 Assert( Alphacolors[dst->alphacolor].used );
481 // Current_alphacolor = &Alphacolors[dst->alphacolor];
482 Current_alphacolor = NULL;
484 Current_alphacolor = NULL;
489 void grx_set_color( int r, int g, int b )
491 Assert((r >= 0) && (r < 256));
492 Assert((g >= 0) && (g < 256));
493 Assert((b >= 0) && (b < 256));
495 // if ( r!=0 || g!=0 || b!=0 ) {
496 // mprintf(( "Setcolor: %d,%d,%d\n", r,g,b ));
498 grx_init_color( &gr_screen.current_color, r, g, b );
499 Current_alphacolor = NULL;
502 void calc_alphacolor_hud_type_old( alphacolor_old * ac )
505 int tr,tg,tb, Sr, Sg, Sb;
510 // Assert(Alphacolors_intited);
512 // mprintf(( "Calculating alphacolor for %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha ));
514 falpha = i2fl(ac->alpha)/255.0f;
515 if ( falpha<0.0f ) falpha = 0.0f; else if ( falpha > 1.0f ) falpha = 1.0f;
517 alpha = ac->alpha >> 4;
518 if (alpha < 0 ) alpha = 0; else if (alpha > 15 ) alpha = 15;
520 if (r < 0 ) r = 0; else if (r > 255 ) r = 255;
522 if (g < 0 ) g = 0; else if (g > 255 ) g = 255;
524 if (b < 0 ) b = 0; else if (b > 255 ) b = 255;
528 for (j=1; j<15; j++ ) {
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;
536 tr = fl2i( i2fl(r) * factor );
537 tg = fl2i( i2fl(g) * factor );
538 tb = fl2i( i2fl(b) * factor );
541 if ( tg > ii[j] ) ii[j] = tg;
542 if ( tb > ii[j] ) ii[j] = tb;
551 ubyte ri[256], gi[256], bi[256];
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);
560 for (i=0; i<256; i++ ) {
567 for (i=0; i<256; i++ ) {
573 int dst_intensity = Sr;
574 if ( Sg > dst_intensity ) dst_intensity = Sg;
575 if ( Sb > dst_intensity ) dst_intensity = Sb;
577 ac->table.lookup[0][i] = (unsigned char)i;
579 for (j=1; j<15; j++ ) {
581 int tmp_i = max( ii[j], dst_intensity );
583 ac->table.lookup[j][i] = (unsigned char)palette_find(ri[tmp_i],gi[tmp_i],bi[tmp_i]);
586 float di = (i2fl(Sr)*.30f+i2fl(Sg)*0.60f+i2fl(Sb)*.10f)/255.0f;
587 float factor = 0.0f + di*0.75f;
589 tr = fl2i( factor*i2fl(r)*falpha );
590 tg = fl2i( factor*i2fl(g)*falpha );
591 tb = fl2i( factor*i2fl(b)*falpha );
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;
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);
602 void calc_alphacolor_old(alphacolor_old *ac)
604 Assert(Fred_running);
605 calc_alphacolor_hud_type_old(ac);