renderergl2: reimplement greyscale as backend post after all 2D+3D draws
Fixes #654 - HUD/UI previously bypassed greyscale. r_greyscale now supports partial desaturation [0-1]. Removed unused legacy logic from tr_shade.c
This commit is contained in:
parent
7bd2c17f9d
commit
453705553b
15
code/renderergl2/glsl/greyscale_fp.glsl
Normal file
15
code/renderergl2/glsl/greyscale_fp.glsl
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
uniform sampler2D u_TextureMap;
|
||||
uniform float u_Greyscale;
|
||||
varying vec2 var_TexCoords;
|
||||
|
||||
// From Rec. 709-1 4.2 "Derivation of luminance signal"
|
||||
const vec3 LUMA = vec3(0.2125, 0.7154, 0.0721);
|
||||
|
||||
void main() {
|
||||
vec4 color = texture2D(u_TextureMap, var_TexCoords);
|
||||
if (u_Greyscale > 0.0) {
|
||||
float y = dot(color.rgb, LUMA);
|
||||
color.rgb = mix(color.rgb, vec3(y), clamp(u_Greyscale, 0.0, 1.0));
|
||||
}
|
||||
gl_FragColor = color;
|
||||
}
|
||||
11
code/renderergl2/glsl/greyscale_vp.glsl
Normal file
11
code/renderergl2/glsl/greyscale_vp.glsl
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
attribute vec4 attr_Position;
|
||||
attribute vec2 attr_TexCoord0;
|
||||
varying vec2 var_TexCoords;
|
||||
|
||||
void main() {
|
||||
vec2 clipXY = (attr_Position.xy * r_FBufScale) * 2.0 - 1.0;
|
||||
clipXY.y = -clipXY.y;
|
||||
|
||||
gl_Position = vec4(clipXY, 0.0, 1.0);
|
||||
var_TexCoords = attr_TexCoord0;
|
||||
}
|
||||
|
|
@ -394,6 +394,9 @@ void RB_BeginDrawingView (void) {
|
|||
// we will only draw a sun if there was sky rendered in this view
|
||||
backEnd.skyRenderedThisView = qfalse;
|
||||
|
||||
// cache the clamped greyscale value
|
||||
backEnd.greyscale = Com_Clamp(0.0f, 1.0f, r_greyscale->value);
|
||||
|
||||
// clip to the plane of the portal
|
||||
if ( backEnd.viewParms.isPortal ) {
|
||||
#if 0
|
||||
|
|
@ -1357,6 +1360,84 @@ const void *RB_ClearDepth(const void *data)
|
|||
return (const void *)(cmd + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
RB_DrawGreyscale
|
||||
|
||||
=============
|
||||
*/
|
||||
static void RB_DrawGreyscale(const FBO_t *src)
|
||||
{
|
||||
if (!src || !src->colorImage[0])
|
||||
return;
|
||||
|
||||
FBO_Bind(NULL);
|
||||
qglViewport(0, 0, glConfig.vidWidth, glConfig.vidHeight);
|
||||
qglScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);
|
||||
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO);
|
||||
|
||||
GLSL_BindProgram(&tr.greyscaleShader);
|
||||
GLSL_SetUniformInt(&tr.greyscaleShader, UNIFORM_TEXTUREMAP, 0);
|
||||
GLSL_SetUniformFloat(&tr.greyscaleShader, UNIFORM_GREYSCALE, backEnd.greyscale);
|
||||
GL_BindToTMU(src->colorImage[0], 0);
|
||||
|
||||
vec4_t quadVerts[4] = {
|
||||
{ 0.0f, 0.0f, 0.0f, 1.0f },
|
||||
{ (float)glConfig.vidWidth, 0.0f, 0.0f, 1.0f },
|
||||
{ (float)glConfig.vidWidth, (float)glConfig.vidHeight, 0.0f, 1.0f },
|
||||
{ 0.0f, (float)glConfig.vidHeight, 0.0f, 1.0f },
|
||||
};
|
||||
|
||||
vec2_t texCoords[4] = { {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f} };
|
||||
|
||||
RB_InstantQuad2(quadVerts, texCoords);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
RB_PresentToScreen
|
||||
|
||||
=============
|
||||
*/
|
||||
static void RB_PresentToScreen(void)
|
||||
{
|
||||
if (!glRefConfig.framebufferObject)
|
||||
return;
|
||||
|
||||
const FBO_t *src = NULL;
|
||||
|
||||
if (tr.renderFbo && tr.renderFbo->colorImage[0])
|
||||
{
|
||||
// texture-backed render FBO
|
||||
src = tr.renderFbo;
|
||||
}
|
||||
else if (tr.msaaResolveFbo && r_hdr->integer)
|
||||
{
|
||||
// Resolving an RGB16F MSAA FBO to the screen messes with the brightness, so resolve to an RGB16F FBO first
|
||||
FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
src = tr.msaaResolveFbo;
|
||||
}
|
||||
|
||||
if (src)
|
||||
{
|
||||
if (backEnd.greyscale > 0.0f)
|
||||
{
|
||||
RB_DrawGreyscale(src);
|
||||
}
|
||||
else
|
||||
{
|
||||
FBO_FastBlit(src, NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (tr.renderFbo)
|
||||
{
|
||||
FBO_FastBlit(tr.renderFbo, NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
|
|
@ -1397,19 +1478,7 @@ const void *RB_SwapBuffers( const void *data ) {
|
|||
ri.Hunk_FreeTempMemory( stencilReadback );
|
||||
}
|
||||
|
||||
if (glRefConfig.framebufferObject)
|
||||
{
|
||||
if (tr.msaaResolveFbo && r_hdr->integer)
|
||||
{
|
||||
// Resolving an RGB16F MSAA FBO to the screen messes with the brightness, so resolve to an RGB16F FBO first
|
||||
FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
FBO_FastBlit(tr.msaaResolveFbo, NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
else if (tr.renderFbo)
|
||||
{
|
||||
FBO_FastBlit(tr.renderFbo, NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
}
|
||||
RB_PresentToScreen();
|
||||
|
||||
if ( !glState.finishCalled ) {
|
||||
qglFinish();
|
||||
|
|
|
|||
|
|
@ -592,7 +592,7 @@ void FBO_BlitFromTexture(struct image_s *src, vec4_t inSrcTexCorners, vec2_t inS
|
|||
FBO_Bind(oldFbo);
|
||||
}
|
||||
|
||||
void FBO_Blit(FBO_t *src, ivec4_t inSrcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend)
|
||||
void FBO_Blit(const FBO_t *src, ivec4_t inSrcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend)
|
||||
{
|
||||
vec4_t srcTexCorners;
|
||||
|
||||
|
|
@ -617,7 +617,7 @@ void FBO_Blit(FBO_t *src, ivec4_t inSrcBox, vec2_t srcTexScale, FBO_t *dst, ivec
|
|||
FBO_BlitFromTexture(src->colorImage[0], srcTexCorners, srcTexScale, dst, dstBox, shaderProgram, color, blend | GLS_DEPTHTEST_DISABLE);
|
||||
}
|
||||
|
||||
void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int buffers, int filter)
|
||||
void FBO_FastBlit(const FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int buffers, int filter)
|
||||
{
|
||||
ivec4_t srcBoxFinal, dstBoxFinal;
|
||||
GLuint srcFb, dstFb;
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@ void FBO_Init(void);
|
|||
void FBO_Shutdown(void);
|
||||
|
||||
void FBO_BlitFromTexture(struct image_s *src, vec4_t inSrcTexCorners, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend);
|
||||
void FBO_Blit(FBO_t *src, ivec4_t srcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
|
||||
void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int buffers, int filter);
|
||||
void FBO_Blit(const FBO_t *src, ivec4_t srcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
|
||||
void FBO_FastBlit(const FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int buffers, int filter);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ extern const char *fallbackShader_texturecolor_vp;
|
|||
extern const char *fallbackShader_texturecolor_fp;
|
||||
extern const char *fallbackShader_tonemap_vp;
|
||||
extern const char *fallbackShader_tonemap_fp;
|
||||
extern const char* fallbackShader_greyscale_vp;
|
||||
extern const char* fallbackShader_greyscale_fp;
|
||||
|
||||
typedef struct uniformInfo_s
|
||||
{
|
||||
|
|
@ -156,6 +158,7 @@ static uniformInfo_t uniformsInfo[] =
|
|||
{ "u_AlphaTest", GLSL_INT },
|
||||
|
||||
{ "u_BoneMatrix", GLSL_MAT16_BONEMATRIX },
|
||||
{ "u_Greyscale", GLSL_FLOAT }
|
||||
};
|
||||
|
||||
typedef enum
|
||||
|
|
@ -1451,6 +1454,18 @@ void GLSL_InitGPUShaders(void)
|
|||
}
|
||||
|
||||
|
||||
if (!GLSL_InitGPUShader(&tr.greyscaleShader, "greyscale", attribs, qtrue, extradefines, qtrue,
|
||||
fallbackShader_greyscale_vp, fallbackShader_greyscale_fp))
|
||||
{
|
||||
ri.Error(ERR_FATAL, "Unable to load greyscale shader");
|
||||
}
|
||||
|
||||
GLSL_InitUniforms(&tr.greyscaleShader);
|
||||
GLSL_SetUniformInt(&tr.greyscaleShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
|
||||
GLSL_FinishGPUShader(&tr.greyscaleShader);
|
||||
|
||||
numEtcShaders++;
|
||||
|
||||
// GLSL 1.10+ or GL_OES_standard_derivatives extension are required for dFdx() and dFdy() GLSL functions
|
||||
if (glRefConfig.glslMajorVersion > 1 || (glRefConfig.glslMajorVersion == 1 && glRefConfig.glslMinorVersion >= 10)
|
||||
|| glRefConfig.standardDerivatives)
|
||||
|
|
|
|||
|
|
@ -1805,11 +1805,7 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, GLenum picForm
|
|||
}
|
||||
else if(lightMap)
|
||||
{
|
||||
// GL_LUMINANCE is not valid for OpenGL 3.2 Core context and
|
||||
// everything becomes solid black
|
||||
if(0 && r_greyscale->integer)
|
||||
internalFormat = GL_LUMINANCE;
|
||||
else
|
||||
|
||||
internalFormat = GL_RGBA;
|
||||
}
|
||||
else
|
||||
|
|
@ -1822,15 +1818,7 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, GLenum picForm
|
|||
// select proper internal format
|
||||
if ( samples == 3 )
|
||||
{
|
||||
if(0 && r_greyscale->integer)
|
||||
{
|
||||
if(r_texturebits->integer == 16 || r_texturebits->integer == 32)
|
||||
internalFormat = GL_LUMINANCE8;
|
||||
else
|
||||
internalFormat = GL_LUMINANCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if ( !forceNoCompression && (glRefConfig.textureCompression & TCR_BPTC) )
|
||||
{
|
||||
internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
|
||||
|
|
@ -1856,17 +1844,7 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, GLenum picForm
|
|||
internalFormat = GL_RGB;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( samples == 4 )
|
||||
{
|
||||
if(0 && r_greyscale->integer)
|
||||
{
|
||||
if(r_texturebits->integer == 16 || r_texturebits->integer == 32)
|
||||
internalFormat = GL_LUMINANCE8_ALPHA8;
|
||||
else
|
||||
internalFormat = GL_LUMINANCE_ALPHA;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !forceNoCompression && (glRefConfig.textureCompression & TCR_BPTC) )
|
||||
{
|
||||
|
|
@ -1890,7 +1868,6 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, GLenum picForm
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return internalFormat;
|
||||
}
|
||||
|
|
@ -2129,7 +2106,6 @@ Upload32
|
|||
static void Upload32(byte *data, int x, int y, int width, int height, GLenum picFormat, GLenum dataFormat, GLenum dataType, int numMips, image_t *image, qboolean scaled)
|
||||
{
|
||||
int i, c;
|
||||
byte *scan;
|
||||
|
||||
imgType_t type = image->type;
|
||||
imgFlags_t flags = image->flags;
|
||||
|
|
@ -2142,30 +2118,9 @@ static void Upload32(byte *data, int x, int y, int width, int height, GLenum pic
|
|||
if (rgba8 && !cubemap)
|
||||
{
|
||||
c = width*height;
|
||||
scan = data;
|
||||
|
||||
if (type == IMGTYPE_COLORALPHA)
|
||||
{
|
||||
if( r_greyscale->integer )
|
||||
{
|
||||
for ( i = 0; i < c; i++ )
|
||||
{
|
||||
byte luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]);
|
||||
scan[i*4] = luma;
|
||||
scan[i*4 + 1] = luma;
|
||||
scan[i*4 + 2] = luma;
|
||||
}
|
||||
}
|
||||
else if( r_greyscale->value )
|
||||
{
|
||||
for ( i = 0; i < c; i++ )
|
||||
{
|
||||
float luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]);
|
||||
scan[i*4] = LERP(scan[i*4], luma, r_greyscale->value);
|
||||
scan[i*4 + 1] = LERP(scan[i*4 + 1], luma, r_greyscale->value);
|
||||
scan[i*4 + 2] = LERP(scan[i*4 + 2], luma, r_greyscale->value);
|
||||
}
|
||||
}
|
||||
|
||||
// This corresponds to what the OpenGL1 renderer does.
|
||||
if (!(flags & IMGFLAG_NOLIGHTSCALE) && (scaled || mipmap))
|
||||
|
|
|
|||
|
|
@ -708,6 +708,8 @@ typedef enum
|
|||
|
||||
UNIFORM_BONEMATRIX,
|
||||
|
||||
UNIFORM_GREYSCALE,
|
||||
|
||||
UNIFORM_COUNT
|
||||
} uniform_t;
|
||||
|
||||
|
|
@ -1494,6 +1496,7 @@ typedef struct {
|
|||
FBO_t *last2DFBO;
|
||||
qboolean colorMask[4];
|
||||
qboolean depthFill;
|
||||
float greyscale;
|
||||
} backEndState_t;
|
||||
|
||||
/*
|
||||
|
|
@ -1614,6 +1617,7 @@ typedef struct {
|
|||
shaderProgram_t ssaoShader;
|
||||
shaderProgram_t depthBlurShader[4];
|
||||
shaderProgram_t testcubeShader;
|
||||
shaderProgram_t greyscaleShader;
|
||||
|
||||
|
||||
// -----------------------------------------
|
||||
|
|
|
|||
|
|
@ -722,20 +722,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
|
|||
break;
|
||||
}
|
||||
|
||||
// FIXME: find some way to implement this.
|
||||
#if 0
|
||||
// if in greyscale rendering mode turn all color values into greyscale.
|
||||
if(r_greyscale->integer)
|
||||
{
|
||||
int scale;
|
||||
|
||||
for(i = 0; i < tess.numVertexes; i++)
|
||||
{
|
||||
scale = (tess.svars.colors[i][0] + tess.svars.colors[i][1] + tess.svars.colors[i][2]) / 3;
|
||||
tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user