Gamma/Constrast
Moderator: InsideQC Admins
8 posts
• Page 1 of 1
Gamma/Constrast
Just a look at the different methods of doing gamma, contrast and view blends. I'm having a minor but annoying issue so if I document the process I can also fix it
But if I don't, I'll continue missing something that is eluding me.
My builds have 5 gamma/contrast methods:
1. WinQuake apply the gamma/contrast to the global palette method
2. GLQuake apply the gamma/contrast to the texture before upload method
3. D3DQuake's d3dSetGammaRamp method
4. The hardware gamma method
5. The render a brightness poly over everything method
Gamma
Building the gamma table from WinQuake. It later gets applied to the palette.
Enter Contrast
The gamma/contrast table from JoeQuake:
I'll be stepping through where each of these are done and why as far as the application of the gamma and contrast.
My builds have 5 gamma/contrast methods:
1. WinQuake apply the gamma/contrast to the global palette method
2. GLQuake apply the gamma/contrast to the texture before upload method
3. D3DQuake's d3dSetGammaRamp method
4. The hardware gamma method
5. The render a brightness poly over everything method
Gamma
Building the gamma table from WinQuake. It later gets applied to the palette.
- Code: Select all
void BuildGammaTable (float g) // g = gamma
{
int i, inf;
if (g == 1.0)
{
for (i=0 ; i<256 ; i++)
gammatable[i] = i;
return;
}
for (i=0 ; i<256 ; i++)
{
inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5;
if (inf < 0)
inf = 0;
if (inf > 255)
inf = 255;
gammatable[i] = inf;
}
}
Enter Contrast
The gamma/contrast table from JoeQuake:
- Code: Select all
static void BuildGammaTable2 (float g, float c)
{
int i, inf;
g = bound(0.3, g, 3);
c = bound(1, c, 3);
if (g == 1 && c == 1)
{
for (i=0 ; i<256 ; i++)
gammatable[i] = i;
return;
}
for (i=0 ; i<256 ; i++)
{
inf = 255 * pow((i + 0.5) / 255.5 * c, g) + 0.5;
gammatable[i] = bound(0, inf, 255);
}
}
I'll be stepping through where each of these are done and why as far as the application of the gamma and contrast.
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
don't forget idgamma, which causes people to complain that overbright lighting is bad
Note: I think these two are the same:
3. D3DQuake's d3dSetGammaRamp method
4. The hardware gamma method
The only difference being which API you use; d3d or wgl. But they both affect the video card the same way (lookup table in the DAC i believe.)
Note: I think these two are the same:
3. D3DQuake's d3dSetGammaRamp method
4. The hardware gamma method
The only difference being which API you use; d3d or wgl. But they both affect the video card the same way (lookup table in the DAC i believe.)
- metlslime
- Posts: 316
- Joined: Tue Feb 05, 2008 11:03 pm
View Blends
Combined with the gamma [and contrast] the view blends also affect the palette flashes in WinQuake directly:
There are 4 chsifts -- I'm guessing the C stands for contrast but it could stand for client. Or maybe contents? Maybe something else (?)
Contents: Empty, Water, Lava, Slime, "Void". Void = no clipping outside the map
Damage: Obvious.
Bonus: Item pickups. "bf"
PowerUP: Quad, Pent, Ring, Suit
The cshift constants ... red, green, blue, intensity percent.
Note: Kurok added an extra one for blue when you go underwater.
The lifecycle of the CSHIFT begins in R_Render_View_ right after drawing particles.
Bonus Flash is actually a command sent over the server ...
It is received in CL_ReadFromServer --> CL_ParseServerMessage and added to the command buffer. So it is probably actually processed 1 frame later.
The damage flash is processed the moment it is received from CL_ParseServerMessage
Power up shift is calculated in V_CalcPowerupCShift, which is called by V_UpdatePalette
Funny note, apparently the content blend was meant to be cleared in WinQuake if you pulled up the console ...
It doesn't work.
Probably because SCR_BringDownConsole is never called anywhere in the source and is commented out in cl_main.c
Combined with the gamma [and contrast] the view blends also affect the palette flashes in WinQuake directly:
- Code: Select all
typedef struct
{
int destcolor[3];
int percent; // 0-256
} cshift_t;
#define CSHIFT_CONTENTS 0
#define CSHIFT_DAMAGE 1
#define CSHIFT_BONUS 2
#define CSHIFT_POWERUP 3
#define NUM_CSHIFTS 4
There are 4 chsifts -- I'm guessing the C stands for contrast but it could stand for client. Or maybe contents? Maybe something else (?)
Contents: Empty, Water, Lava, Slime, "Void". Void = no clipping outside the map
Damage: Obvious.
Bonus: Item pickups. "bf"
PowerUP: Quad, Pent, Ring, Suit
The cshift constants ... red, green, blue, intensity percent.
- Code: Select all
cshift_t cshift_empty = { {130,80,50}, 0 };
cshift_t cshift_water = { {130,80,50}, 128 };
cshift_t cshift_slime = { {0,25,5}, 150 };
cshift_t cshift_lava = { {255,80,0}, 150 };
Note: Kurok added an extra one for blue when you go underwater.
- Code: Select all
cshift_t cshift_kwater = { {64,64,128}, 128 }; // Blue water for Kurok
The lifecycle of the CSHIFT begins in R_Render_View_ right after drawing particles.
- Code: Select all
void V_SetContentsColor (int contents)
{
switch (contents)
{
case CONTENTS_EMPTY:
case CONTENTS_SOLID:
cl.cshifts[CSHIFT_CONTENTS] = cshift_empty;
break;
case CONTENTS_LAVA:
cl.cshifts[CSHIFT_CONTENTS] = cshift_lava;
break;
case CONTENTS_SLIME:
cl.cshifts[CSHIFT_CONTENTS] = cshift_slime;
break;
default:
cl.cshifts[CSHIFT_CONTENTS] = cshift_water;
}
}
Bonus Flash is actually a command sent over the server ...
- Code: Select all
void V_BonusFlash_f (void)
{
cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215;
cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186;
cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69;
cl.cshifts[CSHIFT_BONUS].percent = 50;
}
It is received in CL_ReadFromServer --> CL_ParseServerMessage and added to the command buffer. So it is probably actually processed 1 frame later.
The damage flash is processed the moment it is received from CL_ParseServerMessage
- Code: Select all
case svc_damage:
V_ParseDamage ();
break;
Power up shift is calculated in V_CalcPowerupCShift, which is called by V_UpdatePalette
- Code: Select all
/*
=============
V_CalcPowerupCshift
=============
*/
void V_CalcPowerupCshift (void)
{
if (cl.items & IT_QUAD)
{
cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0;
cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255;
cl.cshifts[CSHIFT_POWERUP].percent = 30;
}
else if (cl.items & IT_SUIT)
{
cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;
cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0;
cl.cshifts[CSHIFT_POWERUP].percent = 20;
}
else if (cl.items & IT_INVISIBILITY)
{
cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100;
cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100;
cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100;
cl.cshifts[CSHIFT_POWERUP].percent = 100;
}
else if (cl.items & IT_INVULNERABILITY)
{
cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255;
cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;
cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0;
cl.cshifts[CSHIFT_POWERUP].percent = 30;
}
else
cl.cshifts[CSHIFT_POWERUP].percent = 0;
}
Funny note, apparently the content blend was meant to be cleared in WinQuake if you pulled up the console ...
- Code: Select all
/*
===============
SCR_BringDownConsole
Brings the console down and fades the palettes back to normal
================
*/
void SCR_BringDownConsole (void)
{
int i;
scr_centertime_off = 0;
for (i=0 ; i<20 && scr_conlines != scr_con_current ; i++)
SCR_UpdateScreen ();
cl.cshifts[0].percent = 0; // no area contents palette on next frame
VID_SetPalette (host_basepal);
}
It doesn't work.
Probably because SCR_BringDownConsole is never called anywhere in the source and is commented out in cl_main.c
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
"Colour" (or "Color" for those who didn't flunk math and married the prom queen) I would guess.
I don't bother with the D3D gamma ramp and just use the GDI functions instead. My guess is that the D3D version is just a wrapper around the GDI functions anyway (which may or may not work in windowed modes depending on which page of the documentation you read). It does have the ability to do calibration but I've never felt the need for it.
I don't bother with the D3D gamma ramp and just use the GDI functions instead. My guess is that the D3D version is just a wrapper around the GDI functions anyway (which may or may not work in windowed modes depending on which page of the documentation you read). It does have the ability to do calibration but I've never felt the need for it.
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
metlslime wrote:3. D3DQuake's d3dSetGammaRamp method
4. The hardware gamma method
d3dquake's D3DSetGamma only affects the window itself and not the desktop. I noticed that FTEQW 2770 using the D3D render actually uses hardware and contrast, which looks much better.
mh wrote:"Colour"
Baker -1
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
why d3d's setgammaramps function is better than the windows api:
D3DSGR_NO_CALIBRATION
no stall, no bounds checks, what you send actually goes.
d3d8 only works if its fullscreen. d3d9 works even windowed (affecting the whole screen).
its probably worth creating a d3d9 context just to get ramps working without stalls, even if all rendering is done with opengl.
D3DSGR_NO_CALIBRATION
no stall, no bounds checks, what you send actually goes.
d3d8 only works if its fullscreen. d3d9 works even windowed (affecting the whole screen).
its probably worth creating a d3d9 context just to get ramps working without stalls, even if all rendering is done with opengl.
- Spike
- Posts: 2892
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
Spike wrote:why d3d's setgammaramps function is better than the windows api:
D3DSGR_NO_CALIBRATION
no stall, no bounds checks, what you send actually goes.
d3d8 only works if its fullscreen. d3d9 works even windowed (affecting the whole screen).
its probably worth creating a d3d9 context just to get ramps working without stalls, even if all rendering is done with opengl.
I think I now have the need to use D3D's SGR.
(Although if my theory is correct there should be an API call to disable the crap too).
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
8 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 1 guest