Load palette from console
Moderator: InsideQC Admins
16 posts
• Page 1 of 2 • 1, 2
Load palette from console
Lately I've been using GIMP and fimg to tweak the palette just to see what happens. The idea is to change the ambiance. For example, rebalance dark colors toward blue and light colors toward yellow, like sunlight and shadow. Another example- make the palette mostly desaturated for a '300' or 'Sin City' look.
This tutorial allows different palette lmp files to be loaded in the console, "loadpalette mypal" will load mypal.lmp. It's simple but will need adjustment for your particular engine.
What I'm not sure of... should there be a way to load a colormap lmp?
EDIT: Removed ifdef around Q_snprintfz per discussion below.
In r_main.c:
EDIT: Add regenerate colormap. This will greatly improve lighting quality for your new palette. Add the following code above loadpalette, it is indeed adapted from qlumpy.
In R_LoadPalette, Add this above Vid_SetPalette
If you want to add a palette field to the worldspawn, add a check for it in CL_ParseEntityLump.
A further step might be remipping textures using the new palette. So far I haven't noticed anything horrible enough to warrant this intensive step.
This tutorial allows different palette lmp files to be loaded in the console, "loadpalette mypal" will load mypal.lmp. It's simple but will need adjustment for your particular engine.
What I'm not sure of... should there be a way to load a colormap lmp?
EDIT: Removed ifdef around Q_snprintfz per discussion below.
In r_main.c:
- Code: Select all
extern byte *host_basepal;
/*
===============
R_LoadPalette
===============
*/
void R_LoadPalette (char *name) //qbism - load a palette lmp
{
loadedfile_t *fileinfo;
char pathname[MAX_QPATH];
Q_snprintfz (pathname, sizeof(pathname), "gfx/%s.lmp", name);
fileinfo = COM_LoadHunkFile (pathname);
if (!fileinfo)
{
Con_Printf("Palette not found.\n");
return;
}
Q_memcpy (host_basepal, fileinfo->data, 768);
VID_SetPalette (host_basepal);
}
/*
===============
R_LoadPalette_f
===============
*/
void R_LoadPalette_f (void) //qbism - load an alternate palette
{
if (Cmd_Argc() != 2)
{
Con_Printf ("loadpalette <name> : load a color palette\n");
return;
}
R_LoadPalette(Cmd_Argv(1));
}
EDIT: Add regenerate colormap. This will greatly improve lighting quality for your new palette. Add the following code above loadpalette, it is indeed adapted from qlumpy.
- Code: Select all
/*
=============================================================================
COLORMAP GRABBING
=============================================================================
*/
/*
===============
BestColor - qbism- from qlumpy
===============
*/
byte BestColor (int r, int g, int b, int start, int stop)
{
int i;
int dr, dg, db;
int bestdistortion, distortion;
int bestcolor;
byte *pal;
//
// let any color go to 0 as a last resort
//
bestdistortion = ( (int)r*r + (int)g*g + (int)b*b )*2;
bestcolor = 0;
pal = host_basepal + start*3;
for (i=start ; i<= stop ; i++)
{
dr = r - (int)pal[0];
dg = g - (int)pal[1];
db = b - (int)pal[2];
pal += 3;
distortion = dr*dr + dg*dg + db*db;
if (distortion < bestdistortion)
{
if (!distortion)
return i; // perfect match
bestdistortion = distortion;
bestcolor = i;
}
}
return bestcolor;
}
/*
==============
GrabColormap - qbism- from qlumpy
filename COLORMAP levels fullbrights
the first map is an identiy 0-255
the final map is all black except for the fullbrights
the remaining maps are evenly spread
fullbright colors start at the top of the palette.
==============
*/
void GrabColormap (void)
{
int levels, brights;
int l, c;
float frac, red, green, blue;
byte *colmap;
colmap = host_colormap;
levels = 32;
brights = 256;
// identity lump
for (l=0 ; l<256 ; l++)
*colmap++ = l;
// shaded levels
for (l=1;l<levels;l++)
{
frac = 1.0 - (float)l/(levels-1);
for (c=0 ; c<256-brights ; c++)
{
red = host_basepal[c*3];
green = host_basepal[c*3+1];
blue = host_basepal[c*3+2];
red = (int)(red*frac+0.5);
green = (int)(green*frac+0.5);
blue = (int)(blue*frac+0.5);
//
// note: 254 instead of 255 because 255 is the transparent color, and we
// don't want anything remapping to that
//
*colmap++ = BestColor(red,green,blue, 0, 254);
}
for ( ; c<256 ; c++)
*colmap++ = c;
}
*colmap++ = brights;
}
In R_LoadPalette, Add this above Vid_SetPalette
- Code: Select all
GrabColormap();
If you want to add a palette field to the worldspawn, add a check for it in CL_ParseEntityLump.
A further step might be remipping textures using the new palette. So far I haven't noticed anything horrible enough to warrant this intensive step.
Last edited by qbism on Wed Apr 06, 2011 4:59 pm, edited 3 times in total.
-
qbism - Posts: 1236
- Joined: Thu Nov 04, 2004 5:51 am
Re: Load palette from console
qbism wrote:should there be a way to load a colormap lmp?
Sure, but with today's awesome CPUs above 300mhz you can just generate it on the fly - no excuse for that now.
Check the qlumpy source in qtools_gpl.tar.gz for that, and have fun adapting it and throwing cvars in there for it.
The biggest problem are mipmaps - either regenerate those as well or deal with pixely artifacts from anti-aliased pixels meant for the former palette.
i should not be here
- leileilol
- Posts: 2783
- Joined: Fri Oct 15, 2004 3:23 am
This could be used to attach to models too correct? Like load a palette for a certain model?
This is a pretty good Tutorial!
This is a pretty good Tutorial!
-

Mexicouger - Posts: 514
- Joined: Sat May 01, 2010 10:12 pm
Mexicouger wrote:This could be used to attach to models too correct? Like load a palette for a certain model?
Nope, it replaces the global palette.
F. A. Špork, an enlightened nobleman and a great patron of art, had a stately Baroque spa complex built on the banks of the River Labe.
- Sajt
- Posts: 1215
- Joined: Sat Oct 16, 2004 3:39 am
Re: Load palette from console
qbism wrote:#ifdef __linux__
sprintf (pathname, sizeof(pathname), "gfx/%s.lmp\0", name);
#else
Q_snprintfz (pathname, sizeof(pathname), "gfx/%s.lmp\0", name);
#endif
I'm curious, why does Linux need special treatment there?
- andrewj
- Posts: 133
- Joined: Mon Aug 30, 2010 3:29 pm
- Location: Australia
because someone forgot to #define Q_snprintfz snprintf for linux.
of course, if you try compiling the code, the linux version will crash due to seeing an int where it expected a string, because its got sprintf instead of snprintf. so mneh.
note that windows' _snprintf function is not compatible with linux/bsd's snprintf as it doesn't guarentee null termination. I think the return values are different too, but those are rarely used.
of course, if you try compiling the code, the linux version will crash due to seeing an int where it expected a string, because its got sprintf instead of snprintf. so mneh.
note that windows' _snprintf function is not compatible with linux/bsd's snprintf as it doesn't guarentee null termination. I think the return values are different too, but those are rarely used.
- Spike
- Posts: 2892
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
Spike wrote:because someone forgot to #define Q_snprintfz snprintf for linux.
of course, if you try compiling the code, the linux version will crash due to seeing an int where it expected a string, because its got sprintf instead of snprintf. so mneh.
note that windows' _snprintf function is not compatible with linux/bsd's snprintf as it doesn't guarentee null termination. I think the return values are different too, but those are rarely used.
Which is probably why Q_snprintfz is used for non-Linux in this code (which won't compile either as Q_snprintfz doesn't exist in stock ID Quake, but that's beside the point). Maybe the question should be "why does non-Linux need special treatment there?" instead?
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
Regarding Q_snprintfz, I should have mentioned that, but good explanation above. MicroSoft's _snprintf does not guarantee null termintation as gcc's snprintf does.
I haven't tried to compile this in Linux, the #ifdef is patterned after similar (ancient) parts of the source. But it would probably be better to deal with that in the definition of Q_snprintfz instead of every single time it's called. If that's even possible. Currently I've been using mingw which includes gcc . I don't know if gcc in Linux would have the same behavior. If it did, that #ifdef could be removed.
I haven't tried to compile this in Linux, the #ifdef is patterned after similar (ancient) parts of the source. But it would probably be better to deal with that in the definition of Q_snprintfz instead of every single time it's called. If that's even possible. Currently I've been using mingw which includes gcc . I don't know if gcc in Linux would have the same behavior. If it did, that #ifdef could be removed.
Hadn't thought of that, but noticed it when the colors stray too far from original.leileilol wrote:The biggest problem are mipmaps - either regenerate those as well or deal with pixely artifacts from anti-aliased pixels meant for the former palette.
-
qbism - Posts: 1236
- Joined: Thu Nov 04, 2004 5:51 am
Very interesting tutorial.
Should be ...
You can kill the #ifdef and kill the "\0" ... Q_snprintfz is platform neutral and null terminates so the Linux #ifdef is unnecessary and Q_snprintfz null terminates so adding a "\0" to the string is not only redundant, but is actually entirely unhelpful because if the resulting string length > sizeof(pathname) it would be truncated from the result anyway (!!).
#ifdef __linux__
sprintf (pathname, sizeof(pathname), "gfx/%s.lmp\0", name);
#else
Q_snprintfz (pathname, sizeof(pathname), "gfx/%s.lmp\0", name);
#endif
Should be ...
Q_snprintfz (pathname, sizeof(pathname), "gfx/%s.lmp", name);
You can kill the #ifdef and kill the "\0" ... Q_snprintfz is platform neutral and null terminates so the Linux #ifdef is unnecessary and Q_snprintfz null terminates so adding a "\0" to the string is not only redundant, but is actually entirely unhelpful because if the resulting string length > sizeof(pathname) it would be truncated from the result anyway (!!).
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Baker wrote:You can kill the #ifdef and kill the "\0" ... Q_snprintfz is platform neutral and null terminates so the Linux #ifdef is unnecessary and Q_snprintfz null terminates so adding a "\0" to the string is not only redundant, but is actually entirely unhelpful because if the resulting string length > sizeof(pathname) it would be truncated from the result anyway (!!).
Actually, the \0 doesn't make a difference. It's baffling that someone would put it in there.
F. A. Špork, an enlightened nobleman and a great patron of art, had a stately Baroque spa complex built on the banks of the River Labe.
- Sajt
- Posts: 1215
- Joined: Sat Oct 16, 2004 3:39 am
16 posts
• Page 1 of 2 • 1, 2
Return to Programming Tutorials
Who is online
Users browsing this forum: No registered users and 1 guest
