View previous topic :: View next topic |
Author |
Message |
Baker

Joined: 14 Mar 2006 Posts: 1538
|
Posted: Wed Jul 14, 2010 6:52 pm Post subject: 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.
Code: | 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: | 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. _________________ Tomorrow Never Dies. I feel this Tomorrow knocking on the door ... |
|
Back to top |
|
 |
metlslime
Joined: 05 Feb 2008 Posts: 177
|
Posted: Wed Jul 14, 2010 8:17 pm Post subject: |
|
|
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.) |
|
Back to top |
|
 |
Spike
Joined: 05 Nov 2004 Posts: 944 Location: UK
|
Posted: Wed Jul 14, 2010 8:22 pm Post subject: |
|
|
yeah, setgammaramp is hardware gamma, but the d3d one has less down sides _________________ What's a signature? |
|
Back to top |
|
 |
Baker

Joined: 14 Mar 2006 Posts: 1538
|
Posted: Wed Jul 14, 2010 8:29 pm Post subject: |
|
|
View Blends
Combined with the gamma [and contrast] the view blends also affect the palette flashes in WinQuake directly:
Code: | 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: | 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: | 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: | 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: | 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: | case svc_damage:
V_ParseDamage ();
break; |
Power up shift is calculated in V_CalcPowerupCShift, which is called by V_UpdatePalette
Code: | /*
=============
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: | /*
===============
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  _________________ Tomorrow Never Dies. I feel this Tomorrow knocking on the door ... |
|
Back to top |
|
 |
mh

Joined: 12 Jan 2008 Posts: 909
|
Posted: Wed Jul 14, 2010 8:55 pm Post subject: |
|
|
"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. _________________ DirectQ Engine - New release 1.8.666a, 9th August 2010
MHQuake Blog (General)
Direct3D 8 Quake Engines |
|
Back to top |
|
 |
Baker

Joined: 14 Mar 2006 Posts: 1538
|
Posted: Wed Jul 14, 2010 9:03 pm Post subject: |
|
|
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.
Baker -1 _________________ Tomorrow Never Dies. I feel this Tomorrow knocking on the door ... |
|
Back to top |
|
 |
Spike
Joined: 05 Nov 2004 Posts: 944 Location: UK
|
Posted: Wed Jul 14, 2010 9:29 pm Post subject: |
|
|
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. _________________ What's a signature? |
|
Back to top |
|
 |
mh

Joined: 12 Jan 2008 Posts: 909
|
Posted: Wed Jul 14, 2010 9:35 pm Post subject: |
|
|
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). _________________ DirectQ Engine - New release 1.8.666a, 9th August 2010
MHQuake Blog (General)
Direct3D 8 Quake Engines |
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2004 phpBB Group
|