New gamma correction implementation using glsl. Enabled by default on OpenGL2. Disable with -noglslgamma.

Avoids general bugginess of hardware gamma, doesn't affect the whole screen in windowed mode like HW gamma. Should fix http://sourceforge.net/p/quakespasm/bugs/5/

git-svn-id: svn+ssh://svn.code.sf.net/p/quakespasm/code/trunk@1157 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
ewasylishen 2015-01-26 20:18:45 +00:00
parent 85879bab2c
commit b85b510e7d
4 changed files with 172 additions and 4 deletions

View file

@ -103,6 +103,140 @@ cvar_t gl_zfix = {"gl_zfix", "0", CVAR_NONE}; // QuakeSpasm z-fighting fix
qboolean r_drawflat_cheatsafe, r_fullbright_cheatsafe, r_lightmap_cheatsafe, r_drawworld_cheatsafe; //johnfitz
//==============================================================================
//
// GLSL GAMMA CORRECTION
//
//==============================================================================
static GLuint r_gamma_texture;
static GLuint r_gamma_program;
// uniforms used in gamma shader
static GLuint gammaLoc;
static GLuint textureLoc;
/*
=============
GLSLGamma_DeleteTexture
=============
*/
void GLSLGamma_DeleteTexture (void)
{
glDeleteTextures (1, &r_gamma_texture);
r_gamma_texture = 0;
r_gamma_program = 0; // deleted in R_DeleteShaders
}
/*
=============
GLSLGamma_CreateShaders
=============
*/
static void GLSLGamma_CreateShaders (void)
{
const GLchar *vertSource = \
"#version 110\n"
"\n"
"void main(void) {\n"
" gl_Position = vec4(gl_Vertex.xy, 0.0, 1.0);\n"
" gl_TexCoord[0] = gl_MultiTexCoord0;\n"
"}\n";
const GLchar *fragSource = \
"#version 110\n"
"\n"
"uniform sampler2D GammaTexture;\n"
"uniform float GammaValue;\n"
"\n"
"void main(void) {\n"
" vec4 frag = texture2D(GammaTexture, gl_TexCoord[0].xy);\n"
" gl_FragColor = vec4(pow(frag.rgb, vec3(GammaValue)), 1.0);\n"
"}\n";
if (!gl_glsl_gamma_able)
return;
r_gamma_program = GL_CreateProgram (vertSource, fragSource, 0, NULL);
// get uniform locations
gammaLoc = GL_GetUniformLocation (&r_gamma_program, "GammaValue");
textureLoc = GL_GetUniformLocation (&r_gamma_program, "GammaTexture");
}
/*
=============
GLSLGamma_GammaCorrect
=============
*/
void GLSLGamma_GammaCorrect (void)
{
if (!gl_glsl_gamma_able)
return;
if (vid_gamma.value == 1)
return;
// create render-to-texture texture if needed
if (!r_gamma_texture)
{
glGenTextures (1, &r_gamma_texture);
glBindTexture (GL_TEXTURE_2D, r_gamma_texture);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, glwidth, glheight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
// create shader if needed
if (!r_gamma_program)
{
GLSLGamma_CreateShaders ();
if (!r_gamma_program)
{
Sys_Error("GLSLGamma_CreateShaders failed");
}
}
// copy the framebuffer to the texture
GL_DisableMultitexture();
glBindTexture (GL_TEXTURE_2D, r_gamma_texture);
glCopyTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, glx, gly, glwidth, glheight);
glClear (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
// draw the texture back to the framebuffer with a fragment shader
GL_UseProgramFunc (r_gamma_program);
GL_Uniform1fFunc (gammaLoc, vid_gamma.value);
GL_Uniform1iFunc (textureLoc, 0); // use texture unit 0
glDisable (GL_ALPHA_TEST);
glDisable (GL_DEPTH_TEST);
glViewport (glx, gly, glwidth, glheight);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0, 1, 1, 0, -99999, 99999);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glBegin (GL_QUADS);
glTexCoord2f (0, 0);
glVertex2f (-1, -1);
glTexCoord2f (1, 0);
glVertex2f (1, -1);
glTexCoord2f (1, 1);
glVertex2f (1, 1);
glTexCoord2f (0, 1);
glVertex2f (-1, 1);
glEnd ();
GL_UseProgramFunc (0);
// clear cached binding
GL_Bind (notexture);
}
/*
=================
R_CullBox -- johnfitz -- replaced with new function from lordhavoc

View file

@ -1077,6 +1077,8 @@ void SCR_UpdateScreen (void)
V_UpdateBlend (); //johnfitz -- V_UpdatePalette cleaned up and renamed
GLSLGamma_GammaCorrect ();
GL_EndRendering ();
}

View file

@ -102,6 +102,7 @@ qboolean gl_texture_NPOT = false; //ericw
qboolean gl_vbo_able = false; //ericw
qboolean gl_glsl_able = false; //ericw
GLint gl_max_texture_units = 0; //ericw
qboolean gl_glsl_gamma_able = false; //ericw
PFNGLMULTITEXCOORD2FARBPROC GL_MTexCoord2fFunc = NULL; //johnfitz
PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc = NULL; //johnfitz
@ -177,6 +178,9 @@ VID_Gamma_SetGamma -- apply gamma correction
*/
static void VID_Gamma_SetGamma (void)
{
if (gl_glsl_gamma_able)
return;
if (draw_context && gammaworks)
{
float value;
@ -213,6 +217,9 @@ VID_Gamma_Restore -- restore system gamma
*/
static void VID_Gamma_Restore (void)
{
if (gl_glsl_gamma_able)
return;
if (draw_context && gammaworks)
{
#if defined(USE_SDL2)
@ -252,6 +259,9 @@ VID_Gamma_f -- callback when the cvar changes
*/
static void VID_Gamma_f (cvar_t *var)
{
if (gl_glsl_gamma_able)
return;
#if USE_GAMMA_RAMPS
int i;
@ -273,6 +283,12 @@ VID_Gamma_Init -- call on init
*/
static void VID_Gamma_Init (void)
{
Cvar_RegisterVariable (&vid_gamma);
Cvar_SetCallback (&vid_gamma, VID_Gamma_f);
if (gl_glsl_gamma_able)
return;
#if defined(USE_SDL2)
# if USE_GAMMA_RAMPS
gammaworks = (SDL_GetWindowGammaRamp(draw_context, vid_sysgamma_red, vid_sysgamma_green, vid_sysgamma_blue) == 0);
@ -293,9 +309,6 @@ static void VID_Gamma_Init (void)
if (!gammaworks)
Con_SafePrintf("gamma adjustment not available\n");
Cvar_RegisterVariable (&vid_gamma);
Cvar_SetCallback (&vid_gamma, VID_Gamma_f);
}
/*
@ -683,6 +696,8 @@ static void VID_Restart (void)
// memory leak.
TexMgr_DeleteTextureObjects ();
GLSLGamma_DeleteTexture ();
R_DeleteShaders ();
//
// set new mode
@ -1096,6 +1111,19 @@ static void GL_CheckExtensions (void)
{
Con_Warning ("OpenGL version < 2, GLSL not available\n");
}
// GLSL gamma
//
if (COM_CheckParm("-noglslgamma"))
Con_Warning ("GLSL gamma disabled at command line\n");
else if (gl_glsl_able && gl_texture_NPOT)
{
gl_glsl_gamma_able = true;
}
else
{
Con_Warning ("GLSL gamma not available, using hardware gamma\n");
}
}
/*
@ -1168,7 +1196,6 @@ static void GL_Init (void)
}
//johnfitz
R_DeleteShaders ();
GLAlias_CreateShaders ();
GL_ClearBufferBindings ();
}

View file

@ -222,6 +222,7 @@ extern QS_PFNGLUNIFORM1FPROC GL_Uniform1fFunc;
extern QS_PFNGLUNIFORM3FPROC GL_Uniform3fFunc;
extern QS_PFNGLUNIFORM4FPROC GL_Uniform4fFunc;
extern qboolean gl_glsl_able;
extern qboolean gl_glsl_gamma_able;
// ericw --
//ericw -- NPOT texture support
@ -376,5 +377,9 @@ void R_DrawWorld_Water (void);
void GL_BindBuffer (GLenum target, GLuint buffer);
void GL_ClearBufferBindings ();
void GLSLGamma_DeleteTexture (void);
void GLSLGamma_GammaCorrect (void);
#endif /* __GLQUAKE_H */