2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/Graphics/Colors.cpp $
15 * Functions to deal with colors & alphacolors
18 * Revision 1.3 2002/06/09 04:41:17 relnev
19 * added copyright header
21 * Revision 1.2 2002/05/07 03:16:45 theoddone33
22 * The Great Newline Fix
24 * Revision 1.1.1.1 2002/05/03 03:28:09 root
28 * 7 7/08/99 10:52a Dave
29 * New multiplayer interpolation scheme. Not 100% done yet, but still
30 * better than the old way.
32 * 6 1/14/99 12:48a Dave
33 * Todo list bug fixes. Made a pass at putting briefing icons back into
34 * FRED. Sort of works :(
36 * 5 12/02/98 5:47p Dave
37 * Put in interface xstr code. Converted barracks screen to new format.
39 * 4 11/30/98 5:31p Dave
40 * Fixed up Fred support for software mode.
42 * 3 11/30/98 1:07p Dave
43 * 16 bit conversion, first run.
45 * 2 10/07/98 10:52a Dave
48 * 1 10/07/98 10:48a Dave
50 * 35 5/19/98 3:32p John
53 * 34 5/13/98 10:22p John
54 * Added cfile functions to read/write rle compressed blocks of data.
55 * Made palman use it for .clr files. Made alphacolors calculate on the
56 * fly rather than caching to/from disk.
58 * 33 4/30/98 4:53p John
59 * Restructured and cleaned up cfile code. Added capability to read off
60 * of CD-ROM drive and out of multiple pack files.
62 * 32 4/10/98 5:20p John
63 * Changed RGB in lighting structure to be ubytes. Removed old
64 * not-necessary 24 bpp software stuff.
66 * 31 4/09/98 11:04p John
67 * Changed ID's in output files to make more sense.
69 * 30 4/01/98 3:05p Adam
70 * Reduced gamma on text.
72 * 29 3/29/98 2:36p John
73 * fixed bug with reloading fullscreen colros
75 * 28 3/25/98 8:07p John
76 * Restructured software rendering into two modules; One for windowed
77 * debug mode and one for DirectX fullscreen.
79 * 27 3/24/98 4:22p John
82 * 26 3/24/98 3:58p John
83 * Put in (hopefully) final gamma setting code.
85 * 25 3/10/98 4:18p John
86 * Cleaned up graphics lib. Took out most unused gr functions. Made D3D
87 * & Glide have popups and print screen. Took out all >8bpp software
88 * support. Made Fred zbuffer. Made zbuffer allocate dynamically to
89 * support Fred. Made zbuffering key off of functions rather than one
92 * 24 2/07/98 7:50p John
93 * Added code so that we can use the old blending type of alphacolors if
94 * we want to. Made the stars use them.
96 * 23 1/13/98 10:20a John
97 * Added code to support "glass" in alphacolors
99 * 22 1/02/98 9:10p Lawrance
100 * Big changes to how colors get set on the HUD.
102 * 21 12/30/97 4:32p John
104 * 20 12/02/97 3:59p John
105 * Added first rev of thruster glow, along with variable levels of
106 * translucency, which retquired some restructing of palman.
108 * 19 11/30/97 4:26p John
109 * Added 32-bpp antialiased line. Took gamma out of alphacolor
112 * 18 11/29/97 2:06p John
113 * added mode 16-bpp support
115 * 17 11/21/97 11:32a John
116 * Added nebulas. Fixed some warpout bugs.
118 * 16 11/14/97 12:30p John
119 * Fixed some DirectX bugs. Moved the 8-16 xlat tables into Graphics
120 * libs. Made 16-bpp DirectX modes know what bitmap format they're in.
122 * 15 11/05/97 11:20p Lawrance
123 * increase number of alpha colors to 52
125 * 14 11/04/97 6:32p Hoffoss
126 * Changes to hotkey screen. Needed to add new colors for
127 * Color_text_active*.
129 * 13 10/31/97 10:47a John
130 * upped clr version to force rebuild after changing palette code.
132 * 12 10/14/97 4:50p John
135 * 11 10/14/97 8:08a John
136 * added a bunch more 16 bit support
138 * 10 10/09/97 5:23p John
139 * Added support for more 16-bpp functions
141 * 9 10/03/97 9:10a John
142 * added better antialiased line drawer
144 * 8 9/20/97 8:16a John
145 * Made .clr files go into the Cache directory. Replaced cfopen(name,NULL)
146 * to delete a file with cf_delete.
148 * 7 9/09/97 10:46a Sandeep
149 * fixed warning level 4
151 * 6 7/18/97 12:40p John
152 * cached alphacolors to disk. Also made cfopen be able to delete a file
153 * by passing NULL for mode.
155 * 5 7/16/97 3:07p John
157 * 4 6/18/97 12:07p John
158 * fixed some color bugs
160 * 3 6/18/97 9:46a John
161 * added first rev of d3d shader. Made HUD target use medium detail
162 * models. Took out some color debug messages.
164 * 2 6/17/97 7:04p John
165 * added d3d support for gradients.
166 * fixed some color bugs by adding screen signatures instead of watching
167 * flags and palette changes.
169 * 1 6/17/97 12:01p John
176 #include "grinternal.h"
180 #include "systemvars.h"
182 //#define MAX_ALPHACOLORS 36
183 #define MAX_ALPHACOLORS 72
185 alphacolor Alphacolors[MAX_ALPHACOLORS];
186 static int Alphacolors_intited = 0;
188 alphacolor * Current_alphacolor = NULL;
191 void calc_alphacolor_hud_type( alphacolor * ac )
193 #ifndef HARDWARE_ONLY
195 int tr,tg,tb, Sr, Sg, Sb;
200 SDL_assert(Alphacolors_intited);
202 // mprintf(( "Calculating alphacolor for %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha ));
204 falpha = i2fl(ac->alpha)/255.0f;
205 if ( falpha<0.0f ) falpha = 0.0f; else if ( falpha > 1.0f ) falpha = 1.0f;
207 alpha = ac->alpha >> 4;
208 if (alpha < 0 ) alpha = 0; else if (alpha > 15 ) alpha = 15;
210 if (r < 0 ) r = 0; else if (r > 255 ) r = 255;
212 if (g < 0 ) g = 0; else if (g > 255 ) g = 255;
214 if (b < 0 ) b = 0; else if (b > 255 ) b = 255;
218 for (j=1; j<15; j++ ) {
220 // JAS: Use 1.5/Gamma instead of 1/Gamma because on Adam's
221 // PC a gamma of 1.2 makes text look good, but his gamma is
222 // really 1.8. 1.8/1.2 = 1.5
223 float factor = falpha * (float)pow(i2fl(j)/14.0f, 1.5f/Gr_gamma);
224 //float factor = i2fl(j)/14.0f;
226 tr = fl2i( i2fl(r) * factor );
227 tg = fl2i( i2fl(g) * factor );
228 tb = fl2i( i2fl(b) * factor );
231 if ( tg > ii[j] ) ii[j] = tg;
232 if ( tb > ii[j] ) ii[j] = tb;
241 ubyte ri[256], gi[256], bi[256];
244 for (i=0; i<256; i++ ) {
245 ri[i] = ubyte((i*r)/m);
246 gi[i] = ubyte((i*g)/m);
247 bi[i] = ubyte((i*b)/m);
250 for (i=0; i<256; i++ ) {
257 for (i=0; i<256; i++ ) {
263 int dst_intensity = Sr;
264 if ( Sg > dst_intensity ) dst_intensity = Sg;
265 if ( Sb > dst_intensity ) dst_intensity = Sb;
267 ac->table.lookup[0][i] = (unsigned char)i;
269 for (j=1; j<15; j++ ) {
271 int tmp_i = max( ii[j], dst_intensity );
273 ac->table.lookup[j][i] = (unsigned char)palette_find(ri[tmp_i],gi[tmp_i],bi[tmp_i]);
276 float di = (i2fl(Sr)*.30f+i2fl(Sg)*0.60f+i2fl(Sb)*.10f)/255.0f;
277 float factor = 0.0f + di*0.75f;
279 tr = fl2i( factor*i2fl(r)*falpha );
280 tg = fl2i( factor*i2fl(g)*falpha );
281 tb = fl2i( factor*i2fl(b)*falpha );
283 if ( tr > 255 ) tr = 255; else if ( tr < 0 ) tr = 0;
284 if ( tg > 255 ) tg = 255; else if ( tg < 0 ) tg = 0;
285 if ( tb > 255 ) tb = 255; else if ( tb < 0 ) tb = 0;
287 ac->table.lookup[15][i] = (unsigned char)palette_find(tr,tg,tb);
288 //ac->table.lookup[15][i] = (unsigned char)palette_find(255,0,0);
294 // Old way to calculate alpha colors
296 void calc_alphacolor_blend_type( alphacolor * ac )
298 #ifndef HARDWARE_ONLY
300 int tr,tg,tb, Sr, Sg, Sb;
305 SDL_assert(Alphacolors_intited);
307 // mprintf(( "Calculating alphacolor for %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha ));
309 alpha = ac->alpha >> 4;
310 if (alpha < 0 ) alpha = 0; else if (alpha > 15 ) alpha = 15;
312 if (r < 0 ) r = 0; else if (r > 255 ) r = 255;
314 if (g < 0 ) g = 0; else if (g > 255 ) g = 255;
316 if (b < 0 ) b = 0; else if (b > 255 ) b = 255;
320 for (j=1; j<16; j++ ) {
321 // JAS: Use 1.5/Gamma instead of 1/Gamma because on Adam's
322 // PC a gamma of 1.2 makes text look good, but his gamma is
323 // really 1.8. 1.8/1.2 = 1.5
324 gamma_j1[j] = (int)((pow(i2fl(j)/15.0f, 1.5f/Gr_gamma)*16.0f) + 0.5);
329 for (i=0; i<256; i++ ) {
335 Dr = ( Sr*(16-alpha) + (r*alpha) ) >> 4;
336 Dg = ( Sg*(16-alpha) + (g*alpha) ) >> 4;
337 Db = ( Sb*(16-alpha) + (b*alpha) ) >> 4;
339 ac->table.lookup[0][i] = (unsigned char)i;
341 for (j=1; j<16; j++ ) {
343 int j1 = gamma_j1[j];
345 tr = ( Sr*(16-j1) + (Dr*j1) ) >> 4;
346 tg = ( Sg*(16-j1) + (Dg*j1) ) >> 4;
347 tb = ( Sb*(16-j1) + (Db*j1) ) >> 4;
349 if ( tr > 255 ) tr = 255; else if ( tr < 0 ) tr = 0;
350 if ( tg > 255 ) tg = 255; else if ( tg < 0 ) tg = 0;
351 if ( tb > 255 ) tb = 255; else if ( tb < 0 ) tb = 0;
353 ac->table.lookup[j][i] = (unsigned char)palette_find(tr,tg,tb);
359 void calc_alphacolor( alphacolor * ac )
363 calc_alphacolor_hud_type(ac);
366 calc_alphacolor_blend_type(ac);
369 Int3(); // Passing an invalid type of alphacolor!
373 void grx_init_alphacolors()
377 Alphacolors_intited = 1;
379 for (i=0; i<MAX_ALPHACOLORS; i++ ) {
380 Alphacolors[i].used = 0;
381 Alphacolors[i].clr = NULL;
384 Current_alphacolor = NULL;
389 void grx_init_alphacolor( color *clr, int r, int g, int b, int alpha, int type )
394 if(Game_mode & GM_STANDALONE_SERVER){
398 if (!Alphacolors_intited) return;
400 if ( alpha < 0 ) alpha = 0;
401 if ( alpha > 255 ) alpha = 255;
404 if ( (clr->magic == 0xAC01) && (clr->is_alphacolor) ) {
405 if ( (clr->alphacolor >= 0) && (clr->alphacolor < MAX_ALPHACOLORS)) {
406 if ( Alphacolors[clr->alphacolor].used && (Alphacolors[clr->alphacolor].clr==clr) ) {
415 for (n=0; n<MAX_ALPHACOLORS; n++ ) {
416 if (!Alphacolors[n].used) break;
418 if ( n == MAX_ALPHACOLORS )
419 Error( LOCATION, "Out of alphacolors!\n" );
425 // Create the alphacolor
426 ac = &Alphacolors[n];
428 if ( changed && (ac->r!=r || ac->g!=g || ac->b!=b || ac->alpha!=alpha || ac->type != type ) ) {
429 // we're changing the color, so delete the old cache file
430 //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 ));
431 //ac_delete_cached(ac);
444 grx_init_color( clr, r, g, b );
446 // Link the alphacolor to the color
447 clr->alpha = (unsigned char)alpha;
448 clr->ac_type = (ubyte)type;
450 clr->is_alphacolor = 1;
454 void grx_get_color( int * r, int * g, int * b )
456 if (r) *r = gr_screen.current_color.red;
457 if (g) *g = gr_screen.current_color.green;
458 if (b) *b = gr_screen.current_color.blue;
461 void grx_init_color( color * dst, int r, int g, int b )
463 dst->screen_sig = gr_screen.signature;
464 dst->red = (unsigned char)r;
465 dst->green = (unsigned char)g;
466 dst->blue = (unsigned char)b;
468 dst->ac_type = AC_TYPE_NONE;
469 dst->is_alphacolor = 0;
470 dst->alphacolor = -1;
473 dst->raw8 = (unsigned char)palette_find( r, g, b );
476 void grx_set_color_fast( color * dst )
478 if ( dst->magic != 0xAC01 ) return;
480 if ( dst->screen_sig != gr_screen.signature ) {
481 if ( dst->is_alphacolor ) {
482 grx_init_alphacolor( dst, dst->red, dst->green, dst->blue, dst->alpha, dst->ac_type );
484 grx_init_color( dst, dst->red, dst->green, dst->blue );
488 gr_screen.current_color = *dst;
490 if ( dst->is_alphacolor ) {
491 SDL_assert( dst->alphacolor > -1 );
492 SDL_assert( dst->alphacolor <= MAX_ALPHACOLORS );
493 SDL_assert( Alphacolors[dst->alphacolor].used );
495 // Current_alphacolor = &Alphacolors[dst->alphacolor];
496 Current_alphacolor = NULL;
498 Current_alphacolor = NULL;
503 void grx_set_color( int r, int g, int b )
505 SDL_assert((r >= 0) && (r < 256));
506 SDL_assert((g >= 0) && (g < 256));
507 SDL_assert((b >= 0) && (b < 256));
509 // if ( r!=0 || g!=0 || b!=0 ) {
510 // mprintf(( "Setcolor: %d,%d,%d\n", r,g,b ));
512 grx_init_color( &gr_screen.current_color, r, g, b );
513 Current_alphacolor = NULL;
516 void calc_alphacolor_hud_type_old( alphacolor_old * ac )
519 int tr,tg,tb, Sr, Sg, Sb;
524 // SDL_assert(Alphacolors_intited);
526 // mprintf(( "Calculating alphacolor for %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha ));
528 falpha = i2fl(ac->alpha)/255.0f;
529 if ( falpha<0.0f ) falpha = 0.0f; else if ( falpha > 1.0f ) falpha = 1.0f;
531 alpha = ac->alpha >> 4;
532 if (alpha < 0 ) alpha = 0; else if (alpha > 15 ) alpha = 15;
534 if (r < 0 ) r = 0; else if (r > 255 ) r = 255;
536 if (g < 0 ) g = 0; else if (g > 255 ) g = 255;
538 if (b < 0 ) b = 0; else if (b > 255 ) b = 255;
542 for (j=1; j<15; j++ ) {
544 // JAS: Use 1.5/Gamma instead of 1/Gamma because on Adam's
545 // PC a gamma of 1.2 makes text look good, but his gamma is
546 // really 1.8. 1.8/1.2 = 1.5
547 float factor = falpha * (float)pow(i2fl(j)/14.0f, 1.5f/Gr_gamma);
548 //float factor = i2fl(j)/14.0f;
550 tr = fl2i( i2fl(r) * factor );
551 tg = fl2i( i2fl(g) * factor );
552 tb = fl2i( i2fl(b) * factor );
555 if ( tg > ii[j] ) ii[j] = tg;
556 if ( tb > ii[j] ) ii[j] = tb;
565 ubyte ri[256], gi[256], bi[256];
568 for (i=0; i<256; i++ ) {
569 ri[i] = ubyte((i*r)/m);
570 gi[i] = ubyte((i*g)/m);
571 bi[i] = ubyte((i*b)/m);
574 for (i=0; i<256; i++ ) {
581 for (i=0; i<256; i++ ) {
587 int dst_intensity = Sr;
588 if ( Sg > dst_intensity ) dst_intensity = Sg;
589 if ( Sb > dst_intensity ) dst_intensity = Sb;
591 ac->table.lookup[0][i] = (unsigned char)i;
593 for (j=1; j<15; j++ ) {
595 int tmp_i = max( ii[j], dst_intensity );
597 ac->table.lookup[j][i] = (unsigned char)palette_find(ri[tmp_i],gi[tmp_i],bi[tmp_i]);
600 float di = (i2fl(Sr)*.30f+i2fl(Sg)*0.60f+i2fl(Sb)*.10f)/255.0f;
601 float factor = 0.0f + di*0.75f;
603 tr = fl2i( factor*i2fl(r)*falpha );
604 tg = fl2i( factor*i2fl(g)*falpha );
605 tb = fl2i( factor*i2fl(b)*falpha );
607 if ( tr > 255 ) tr = 255; else if ( tr < 0 ) tr = 0;
608 if ( tg > 255 ) tg = 255; else if ( tg < 0 ) tg = 0;
609 if ( tb > 255 ) tb = 255; else if ( tb < 0 ) tb = 0;
611 ac->table.lookup[15][i] = (unsigned char)palette_find(tr,tg,tb);
612 //ac->table.lookup[15][i] = (unsigned char)palette_find(255,0,0);
616 void calc_alphacolor_old(alphacolor_old *ac)
618 SDL_assert(Fred_running);
619 calc_alphacolor_hud_type_old(ac);