Make software overbright optional (cvar r_softOverbright) and reduce the number of FBOs and FBO blits when able.

This commit is contained in:
James Canete 2012-11-20 03:34:16 +00:00
parent 1f8db4c14a
commit 467619c034
8 changed files with 166 additions and 201 deletions

View file

@ -485,7 +485,7 @@ void RB_BeginDrawingView (void) {
// drawing more world check is in case of double renders, such as skyportals // drawing more world check is in case of double renders, such as skyportals
if (backEnd.viewParms.targetFbo == NULL) if (backEnd.viewParms.targetFbo == NULL)
{ {
if (backEnd.framePostProcessed && (backEnd.refdef.rdflags & RDF_NOWORLDMODEL)) if (!tr.renderFbo || (backEnd.framePostProcessed && (backEnd.refdef.rdflags & RDF_NOWORLDMODEL)))
{ {
FBO_Bind(tr.screenScratchFbo); FBO_Bind(tr.screenScratchFbo);
} }
@ -959,7 +959,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
// FIXME: HUGE hack // FIXME: HUGE hack
if (glRefConfig.framebufferObject) if (glRefConfig.framebufferObject)
{ {
if (backEnd.framePostProcessed) if (!tr.renderFbo || backEnd.framePostProcessed)
{ {
FBO_Bind(tr.screenScratchFbo); FBO_Bind(tr.screenScratchFbo);
} }
@ -1108,7 +1108,7 @@ const void *RB_StretchPic ( const void *data ) {
// FIXME: HUGE hack // FIXME: HUGE hack
if (glRefConfig.framebufferObject) if (glRefConfig.framebufferObject)
{ {
if (backEnd.framePostProcessed) if (!tr.renderFbo || backEnd.framePostProcessed)
{ {
FBO_Bind(tr.screenScratchFbo); FBO_Bind(tr.screenScratchFbo);
} }
@ -1223,58 +1223,22 @@ const void *RB_DrawSurfs( const void *data ) {
qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]); qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]);
backEnd.depthFill = qfalse; backEnd.depthFill = qfalse;
// If we're using multisampling, resolve the depth first
if (tr.msaaResolveFbo) if (tr.msaaResolveFbo)
{ {
// If we're using multisampling, resolve the depth first
FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_DEPTH_BUFFER_BIT, GL_NEAREST); FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
} }
else if (tr.renderFbo == NULL)
{
// If we're rendering directly to the screen, copy the depth to a texture
GL_BindToTMU(tr.renderDepthImage, 0);
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, glConfig.vidWidth, glConfig.vidHeight, 0);
}
if (r_ssao->integer) if (r_ssao->integer)
{ {
vec2_t srcTexScale; // need the depth in a texture we can do GL_LINEAR sampling on, so copy it to an HDR image
vec4_t color; FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, tr.hdrDepthFbo, NULL, NULL, NULL, 0);
vec4_t quadVerts[4];
vec2_t texCoords[4];
vec2_t invTexRes;
matrix_t idmatrix;
srcTexScale[0] = srcTexScale[1] = 1.0f;
color[0] = color[1] = color[2] = color[3] = 1.0f;
FBO_Bind(tr.hdrDepthFbo);
qglViewport(0, 0, tr.hdrDepthFbo->width, tr.hdrDepthFbo->height);
qglScissor(0, 0, tr.hdrDepthFbo->width, tr.hdrDepthFbo->height);
Matrix16Identity(idmatrix);
VectorSet4(quadVerts[0], -1, 1, 0, 1);
VectorSet4(quadVerts[1], 1, 1, 0, 1);
VectorSet4(quadVerts[2], 1, -1, 0, 1);
VectorSet4(quadVerts[3], -1, -1, 0, 1);
texCoords[0][0] = 0; texCoords[0][1] = 1;
texCoords[1][0] = 1; texCoords[1][1] = 1;
texCoords[2][0] = 1; texCoords[2][1] = 0;
texCoords[3][0] = 0; texCoords[3][1] = 0;
invTexRes[0] = 0.0f;
invTexRes[1] = 0.0f;
GL_State( GLS_DEPTHTEST_DISABLE );
GLSL_BindProgram(&tr.textureColorShader);
GL_BindToTMU(tr.renderDepthImage, TB_COLORMAP);
GLSL_SetUniformMatrix16(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, idmatrix);
GLSL_SetUniformVec4(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_COLOR, color);
GLSL_SetUniformVec2(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_INVTEXRES, invTexRes);
GLSL_SetUniformVec2(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_AUTOEXPOSUREMINMAX, tr.refdef.autoExposureMinMax);
GLSL_SetUniformVec3(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_TONEMINAVGMAXLINEAR, tr.refdef.toneMinAvgMaxLinear);
RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes);
} }
if (backEnd.viewParms.flags & VPF_USESUNLIGHT) if (backEnd.viewParms.flags & VPF_USESUNLIGHT)
@ -1584,7 +1548,7 @@ const void *RB_ClearDepth(const void *data)
if (glRefConfig.framebufferObject) if (glRefConfig.framebufferObject)
{ {
if (backEnd.framePostProcessed) if (!tr.renderFbo || backEnd.framePostProcessed)
{ {
FBO_Bind(tr.screenScratchFbo); FBO_Bind(tr.screenScratchFbo);
} }
@ -1599,7 +1563,7 @@ const void *RB_ClearDepth(const void *data)
// if we're doing MSAA, clear the depth texture for the resolve buffer // if we're doing MSAA, clear the depth texture for the resolve buffer
if (tr.msaaResolveFbo) if (tr.msaaResolveFbo)
{ {
FBO_Bind(tr.screenScratchFbo); FBO_Bind(tr.msaaResolveFbo);
qglClear(GL_DEPTH_BUFFER_BIT); qglClear(GL_DEPTH_BUFFER_BIT);
} }
@ -1648,47 +1612,38 @@ const void *RB_SwapBuffers( const void *data ) {
if (glRefConfig.framebufferObject) if (glRefConfig.framebufferObject)
{ {
// copy final image to screen if (!backEnd.framePostProcessed)
vec4_t color;
if (backEnd.framePostProcessed)
{ {
// frame was postprocessed into screen fbo, copy from there if (tr.msaaResolveFbo && r_hdr->integer)
}
else if (!glRefConfig.framebuffer_srgb)
{
// Copy render to screenscratch, possibly resolving MSAA
FBO_FastBlit(tr.renderFbo, NULL, tr.screenScratchFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
else
{
FBO_t *srcFbo = tr.renderFbo;
if (tr.msaaResolveFbo)
{ {
// Resolve the MSAA before copying // Resolving an RGB16F MSAA FBO to the screen messes with the brightness, so resolve to an RGB16F FBO first
FBO_FastBlit(srcFbo, NULL, tr.msaaResolveFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST); FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
FBO_FastBlit(tr.msaaResolveFbo, NULL, tr.screenScratchFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
srcFbo = tr.msaaResolveFbo; }
else if (tr.renderFbo)
{
FBO_FastBlit(tr.renderFbo, NULL, tr.screenScratchFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
} }
// need to copy from resolve to screenscratch to fix gamma
FBO_Blit(srcFbo, NULL, NULL, tr.screenScratchFbo, NULL, NULL, NULL, 0);
} }
color[0] =
color[1] =
color[2] = pow(2, tr.overbrightBits); //exp2(tr.overbrightBits);
color[3] = 1.0f;
// turn off colormask when copying final image if (tr.screenScratchFbo)
if (backEnd.colorMask[0] || backEnd.colorMask[1] || backEnd.colorMask[2] || backEnd.colorMask[3]) {
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); vec4_t color;
FBO_Blit(tr.screenScratchFbo, NULL, NULL, NULL, NULL, NULL, color, 0);
if (backEnd.colorMask[0] || backEnd.colorMask[1] || backEnd.colorMask[2] || backEnd.colorMask[3]) color[0] =
qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]); color[1] =
color[2] = pow(2, tr.overbrightBits); //exp2(tr.overbrightBits);
color[3] = 1.0f;
// turn off colormask when copying final image
if (backEnd.colorMask[0] || backEnd.colorMask[1] || backEnd.colorMask[2] || backEnd.colorMask[3])
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
FBO_Blit(tr.screenScratchFbo, NULL, NULL, NULL, NULL, NULL, color, 0);
if (backEnd.colorMask[0] || backEnd.colorMask[1] || backEnd.colorMask[2] || backEnd.colorMask[3])
qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]);
}
} }
if ( !glState.finishCalled ) { if ( !glState.finishCalled ) {
@ -1750,11 +1705,9 @@ const void *RB_PostProcess(const void *data)
FBO_t *srcFbo; FBO_t *srcFbo;
qboolean autoExposure; qboolean autoExposure;
if (!glRefConfig.framebufferObject) if (!glRefConfig.framebufferObject || !r_postProcess->integer)
{ {
// do nothing // do nothing
backEnd.framePostProcessed = qtrue;
return (const void *)(cmd + 1); return (const void *)(cmd + 1);
} }
@ -1766,36 +1719,37 @@ const void *RB_PostProcess(const void *data)
srcFbo = tr.msaaResolveFbo; srcFbo = tr.msaaResolveFbo;
} }
if (r_postProcess->integer && r_ssao->integer) if (r_ssao->integer)
{ {
vec4i_t dstBox; FBO_BlitFromTexture(tr.screenSsaoImage, NULL, NULL, srcFbo, NULL, NULL, NULL, GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO);
VectorSet4(dstBox, 0, 0, srcFbo->width, srcFbo->height);
FBO_BlitFromTexture(tr.screenSsaoImage, NULL, NULL, srcFbo, dstBox, NULL, NULL, GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO);
} }
if (r_postProcess->integer && (r_toneMap->integer || r_forceToneMap->integer)) if (srcFbo)
{ {
autoExposure = r_autoExposure->integer || r_forceAutoExposure; if (r_hdr->integer && (r_toneMap->integer || r_forceToneMap->integer))
RB_ToneMap(srcFbo, autoExposure); {
} autoExposure = r_autoExposure->integer || r_forceAutoExposure->integer;
else if (!glRefConfig.framebuffer_srgb && r_cameraExposure->value == 0.0f) RB_ToneMap(srcFbo, autoExposure);
{ }
FBO_FastBlit(srcFbo, NULL, tr.screenScratchFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST); else if (!glRefConfig.framebuffer_srgb && r_cameraExposure->value == 0.0f)
} {
else FBO_FastBlit(srcFbo, NULL, tr.screenScratchFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
{ }
vec4_t color; else
{
vec4_t color;
color[0] = color[0] =
color[1] = color[1] =
color[2] = pow(2, r_cameraExposure->value); //exp2(r_cameraExposure->value); color[2] = pow(2, r_cameraExposure->value); //exp2(r_cameraExposure->value);
color[3] = 1.0f; color[3] = 1.0f;
FBO_Blit(srcFbo, NULL, NULL, tr.screenScratchFbo, NULL, NULL, color, 0); FBO_Blit(srcFbo, NULL, NULL, tr.screenScratchFbo, NULL, NULL, color, 0);
}
} }
#ifdef REACTION #ifdef REACTION
if (r_postProcess->integer && glRefConfig.framebufferObject) if (1)
{ {
RB_GodRays(); RB_GodRays();
@ -1820,16 +1774,16 @@ const void *RB_PostProcess(const void *data)
if (0) if (0)
{ {
vec4i_t dstBox; vec4i_t dstBox;
VectorSet4(dstBox, 256, tr.screenScratchFbo->height - 256, 256, 256); VectorSet4(dstBox, 256, glConfig.vidHeight - 256, 256, 256);
FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0); FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
VectorSet4(dstBox, 512, tr.screenScratchFbo->height - 256, 256, 256); VectorSet4(dstBox, 512, glConfig.vidHeight - 256, 256, 256);
FBO_BlitFromTexture(tr.screenShadowImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0); FBO_BlitFromTexture(tr.screenShadowImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
} }
if (0) if (0)
{ {
vec4i_t dstBox; vec4i_t dstBox;
VectorSet4(dstBox, 256, tr.screenScratchFbo->height - 256, 256, 256); VectorSet4(dstBox, 256, glConfig.vidHeight - 256, 256, 256);
FBO_BlitFromTexture(tr.renderImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0); FBO_BlitFromTexture(tr.renderImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
} }

View file

@ -502,29 +502,21 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) {
if (glRefConfig.framebufferObject) if (glRefConfig.framebufferObject)
{ {
// clear all framebuffers // clear all framebuffers
// FIXME: must be a better way to do this if (tr.msaaResolveFbo)
int i;
for (i = 0; i < 3; i++)
{ {
if (i == 1 && !tr.msaaResolveFbo) FBO_Bind(tr.msaaResolveFbo);
continue; qglClear(GL_COLOR_BUFFER_BIT);
}
switch(i) if (tr.renderFbo)
{ {
case 0: FBO_Bind(tr.renderFbo);
FBO_Bind(tr.renderFbo); qglClear(GL_COLOR_BUFFER_BIT);
break; }
case 1:
FBO_Bind(tr.msaaResolveFbo);
break;
case 2:
FBO_Bind(tr.screenScratchFbo);
break;
}
if (tr.screenScratchFbo)
{
FBO_Bind(tr.screenScratchFbo);
qglClear(GL_COLOR_BUFFER_BIT); qglClear(GL_COLOR_BUFFER_BIT);
} }

View file

@ -309,7 +309,7 @@ FBO_Bind
*/ */
void FBO_Bind(FBO_t * fbo) void FBO_Bind(FBO_t * fbo)
{ {
if (fbo && glState.currentFBO == fbo) if (glState.currentFBO == fbo)
return; return;
if (r_logFile->integer) if (r_logFile->integer)
@ -405,6 +405,8 @@ void FBO_Init(void)
ri.Cvar_SetValue("r_ext_framebuffer_multisample", (float)multisample); ri.Cvar_SetValue("r_ext_framebuffer_multisample", (float)multisample);
} }
// only create a render FBO if we need to resolve MSAA or do HDR
// otherwise just render straight to the screen (tr.renderFbo = NULL)
if (multisample && glRefConfig.framebufferMultisample) if (multisample && glRefConfig.framebufferMultisample)
{ {
tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height); tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
@ -427,7 +429,7 @@ void FBO_Init(void)
R_CheckFBO(tr.msaaResolveFbo); R_CheckFBO(tr.msaaResolveFbo);
} }
else else if (r_hdr->integer)
{ {
tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height); tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
FBO_Bind(tr.renderFbo); FBO_Bind(tr.renderFbo);
@ -443,10 +445,13 @@ void FBO_Init(void)
// clear render buffer // clear render buffer
// this fixes the corrupt screen bug with r_hdr 1 on older hardware // this fixes the corrupt screen bug with r_hdr 1 on older hardware
FBO_Bind(tr.renderFbo); if (tr.renderFbo)
qglClearColor( 1, 0, 0.5, 1 ); {
qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); FBO_Bind(tr.renderFbo);
FBO_Bind(NULL); qglClearColor( 1, 0, 0.5, 1 );
qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
FBO_Bind(NULL);
}
#ifdef REACTION #ifdef REACTION
{ {
@ -525,6 +530,7 @@ void FBO_Init(void)
R_CheckFBO(tr.targetLevelsFbo); R_CheckFBO(tr.targetLevelsFbo);
} }
if (r_softOverbright->integer)
{ {
//tr.screenScratchFbo = FBO_Create("_screenscratch", width, height); //tr.screenScratchFbo = FBO_Create("_screenscratch", width, height);
tr.screenScratchFbo = FBO_Create("_screenscratch", tr.screenScratchImage->width, tr.screenScratchImage->height); tr.screenScratchFbo = FBO_Create("_screenscratch", tr.screenScratchImage->width, tr.screenScratchImage->height);

View file

@ -2943,6 +2943,7 @@ void R_CreateBuiltinImages( void ) {
tr.godRaysImage = R_CreateImage("*godRays", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); tr.godRaysImage = R_CreateImage("*godRays", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
#endif #endif
if (r_softOverbright->integer)
{ {
int format; int format;
@ -3033,14 +3034,14 @@ void R_SetColorMappings( void ) {
tr.overbrightBits = 0; // need hardware gamma for overbright tr.overbrightBits = 0; // need hardware gamma for overbright
} }
// never overbright in windowed mode // never overbright in windowed mode without soft overbright
if ( 0 /* !glConfig.isFullscreen */ ) if ( !glConfig.isFullscreen && !r_softOverbright->integer )
{ {
tr.overbrightBits = 0; tr.overbrightBits = 0;
} }
// never overbright with tonemapping // never overbright with tonemapping
if ( r_toneMap->integer ) if ( r_toneMap->integer && r_hdr->integer )
{ {
tr.overbrightBits = 0; tr.overbrightBits = 0;
} }
@ -3077,8 +3078,11 @@ void R_SetColorMappings( void ) {
shift = tr.overbrightBits; shift = tr.overbrightBits;
if (glRefConfig.framebufferObject) // no shift with soft overbright
if (r_softOverbright->integer)
{
shift = 0; shift = 0;
}
for ( i = 0; i < 256; i++ ) { for ( i = 0; i < 256; i++ ) {
if ( g == 1 ) { if ( g == 1 ) {

View file

@ -107,6 +107,9 @@ cvar_t *r_mergeMultidraws;
cvar_t *r_mergeLeafSurfaces; cvar_t *r_mergeLeafSurfaces;
cvar_t *r_cameraExposure; cvar_t *r_cameraExposure;
cvar_t *r_softOverbright;
cvar_t *r_hdr; cvar_t *r_hdr;
cvar_t *r_postProcess; cvar_t *r_postProcess;
@ -1149,6 +1152,8 @@ void R_Register( void )
r_greyscale = ri.Cvar_Get("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH); r_greyscale = ri.Cvar_Get("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH);
ri.Cvar_CheckRange(r_greyscale, 0, 1, qfalse); ri.Cvar_CheckRange(r_greyscale, 0, 1, qfalse);
r_softOverbright = ri.Cvar_Get( "r_softOverbright", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_hdr = ri.Cvar_Get( "r_hdr", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_hdr = ri.Cvar_Get( "r_hdr", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE ); r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE );

View file

@ -2092,6 +2092,8 @@ extern cvar_t *r_anaglyphMode;
extern cvar_t *r_mergeMultidraws; extern cvar_t *r_mergeMultidraws;
extern cvar_t *r_mergeLeafSurfaces; extern cvar_t *r_mergeLeafSurfaces;
extern cvar_t *r_softOverbright;
extern cvar_t *r_hdr; extern cvar_t *r_hdr;
extern cvar_t *r_postProcess; extern cvar_t *r_postProcess;

View file

@ -112,14 +112,16 @@ void RB_BokehBlur(float blur)
if (blur > 0.0f) if (blur > 0.0f)
{ {
// create a quarter texture // create a quarter texture
FBO_Blit(tr.screenScratchFbo, NULL, NULL, tr.quarterFbo[0], NULL, NULL, NULL, 0); //FBO_Blit(NULL, NULL, NULL, tr.quarterFbo[0], NULL, NULL, NULL, 0);
FBO_FastBlit(tr.screenScratchFbo, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
} }
#ifndef HQ_BLUR #ifndef HQ_BLUR
if (blur > 1.0f) if (blur > 1.0f)
{ {
// create a 1/16th texture // create a 1/16th texture
FBO_Blit(tr.quarterFbo[0], NULL, NULL, tr.textureScratchFbo[0], NULL, NULL, NULL, 0); //FBO_Blit(tr.quarterFbo[0], NULL, NULL, tr.textureScratchFbo[0], NULL, NULL, NULL, 0);
FBO_FastBlit(tr.quarterFbo[0], NULL, tr.textureScratchFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
} }
#endif #endif
@ -340,16 +342,15 @@ void RB_GodRays(void)
VectorSet4(color, mul, mul, mul, 1); VectorSet4(color, mul, mul, mul, 1);
// first, downsample the framebuffer // first, downsample the framebuffer
VectorSet4(srcBox, 0, 0, tr.godRaysFbo->width, tr.godRaysFbo->height);
VectorSet4(dstBox, 0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height);
FBO_Blit(tr.godRaysFbo, srcBox, texScale, tr.quarterFbo[0], dstBox, &tr.textureColorShader, color, 0);
if (colorize) if (colorize)
{ {
VectorSet4(srcBox, 0, 0, tr.screenScratchFbo->width, tr.screenScratchFbo->height); FBO_FastBlit(tr.screenScratchFbo, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
FBO_Blit(tr.screenScratchFbo, srcBox, texScale, tr.quarterFbo[0], dstBox, &tr.textureColorShader, color, FBO_Blit(tr.godRaysFbo, NULL, NULL, tr.quarterFbo[0], NULL, NULL, color, GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO);
GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); }
} else
{
FBO_FastBlit(tr.godRaysFbo, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
}
} }
// radial blur passes, ping-ponging between the two quarter-size buffers // radial blur passes, ping-ponging between the two quarter-size buffers
@ -375,7 +376,7 @@ void RB_GodRays(void)
VectorSet4(color, mul, mul, mul, 1); VectorSet4(color, mul, mul, mul, 1);
VectorSet4(srcBox, 0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height); VectorSet4(srcBox, 0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height);
VectorSet4(dstBox, 0, 0, tr.screenScratchFbo->width, tr.screenScratchFbo->height); VectorSet4(dstBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
FBO_Blit(tr.quarterFbo[0], srcBox, texScale, tr.screenScratchFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE); FBO_Blit(tr.quarterFbo[0], srcBox, texScale, tr.screenScratchFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
} }
} }
@ -462,13 +463,8 @@ void RB_GaussianBlur(float blur)
VectorSet4(color, 1, 1, 1, 1); VectorSet4(color, 1, 1, 1, 1);
// first, downsample the framebuffer // first, downsample the framebuffer
VectorSet4(srcBox, 0, 0, tr.screenScratchFbo->width, tr.screenScratchFbo->height); FBO_FastBlit(tr.screenScratchFbo, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
VectorSet4(dstBox, 0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height); FBO_FastBlit(tr.quarterFbo[0], NULL, tr.textureScratchFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
FBO_Blit(tr.screenScratchFbo, srcBox, texScale, tr.quarterFbo[0], dstBox, &tr.textureColorShader, color, 0);
VectorSet4(srcBox, 0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height);
VectorSet4(dstBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height);
FBO_Blit(tr.quarterFbo[0], srcBox, texScale, tr.textureScratchFbo[0], dstBox, &tr.textureColorShader, color, 0);
// set the alpha channel // set the alpha channel
VectorSet4(srcBox, 0, 0, tr.whiteImage->width, tr.whiteImage->height); VectorSet4(srcBox, 0, 0, tr.whiteImage->width, tr.whiteImage->height);
@ -483,7 +479,7 @@ void RB_GaussianBlur(float blur)
// finally, merge back to framebuffer // finally, merge back to framebuffer
VectorSet4(srcBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height); VectorSet4(srcBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height);
VectorSet4(dstBox, 0, 0, tr.screenScratchFbo->width, tr.screenScratchFbo->height); VectorSet4(dstBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
color[3] = factor; color[3] = factor;
FBO_Blit(tr.textureScratchFbo[0], srcBox, texScale, tr.screenScratchFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA); FBO_Blit(tr.textureScratchFbo[0], srcBox, texScale, tr.screenScratchFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
} }

View file

@ -92,12 +92,18 @@ Cvars for simple rendering features:
0 - None. (default) 0 - None. (default)
1-16 - Some. 1-16 - Some.
17+ - Too much! 17+ - Too much!
r_ssao - Enable screen-space ambient occlusion. r_ssao - Enable screen-space ambient occlusion.
Currently eats framerate and has some Currently eats framerate and has some
visible artifacts. visible artifacts.
0 - No. (default) 0 - No. (default)
1 - Yes. 1 - Yes.
r_softOverbright - Enable software overbrighting. This enables
overbrighting even in a window. Is disabled
when r_toneMap 1 and r_hdr 1.
0 - No.
1 - Yes. (default)
Cvars for HDR and tonemapping: Cvars for HDR and tonemapping:
r_hdr - Do scene rendering in a framebuffer with r_hdr - Do scene rendering in a framebuffer with
@ -123,63 +129,63 @@ Cvars for HDR and tonemapping:
r_forceToneMap - Cheat. Override built-in and map tonemap r_forceToneMap - Cheat. Override built-in and map tonemap
settings and use cvars r_forceToneMapAvg, settings and use cvars r_forceToneMapAvg,
r_forceToneMapMin, and r_forceToneMapMax. r_forceToneMapMin, and r_forceToneMapMax.
0 - No. (default) 0 - No. (default)
1 - Yes. 1 - Yes.
r_forceToneMapAvg - Cheat. Map average scene luminance to this r_forceToneMapAvg - Cheat. Map average scene luminance to this
value, in powers of two. Requires value, in powers of two. Requires
r_forceToneMap. r_forceToneMap.
-2.0 - Dark. -2.0 - Dark.
-1.0 - Kinda dark. (default). -1.0 - Kinda dark. (default).
2.0 - Too bright. 2.0 - Too bright.
r_forceToneMapMin - Cheat. After mapping average, luminance r_forceToneMapMin - Cheat. After mapping average, luminance
below this level is mapped to black. below this level is mapped to black.
Requires r_forceToneMap. Requires r_forceToneMap.
-5 - Not noticeable. -5 - Not noticeable.
-3.25 - Normal. (default) -3.25 - Normal. (default)
0.0 - Too dark. 0.0 - Too dark.
r_forceToneMapMin - Cheat. After mapping average, luminance r_forceToneMapMin - Cheat. After mapping average, luminance
above this level is mapped to white. above this level is mapped to white.
Requires r_forceToneMap. Requires r_forceToneMap.
0.0 - Too bright. 0.0 - Too bright.
1.0 - Normal. (default). 1.0 - Normal. (default).
2.0 - Washed out. 2.0 - Washed out.
r_autoExposure - Do automatic exposure based on scene r_autoExposure - Do automatic exposure based on scene
brightness. Hardcoded to -2 to 2 on maps brightness. Hardcoded to -2 to 2 on maps
that don't specify otherwise. Requires that don't specify otherwise. Requires
r_hdr, r_postprocess, and r_toneMap. r_hdr, r_postprocess, and r_toneMap.
0 - No. 0 - No.
1 - Yes. (default) 1 - Yes. (default)
r_forceAutoExposure - Cheat. Override built-in and map auto r_forceAutoExposure - Cheat. Override built-in and map auto
exposure settings and use cvars exposure settings and use cvars
r_forceAutoExposureMin and r_forceAutoExposureMin and
r_forceAutoExposureMax. r_forceAutoExposureMax.
0 - No. (default) 0 - No. (default)
1 - Yes. 1 - Yes.
r_forceAutoExposureMin - Cheat. Set minimum exposure to this value, r_forceAutoExposureMin - Cheat. Set minimum exposure to this value,
in powers of two. Requires in powers of two. Requires
r_forceAutoExpsure. r_forceAutoExpsure.
-3.0 - Dimmer. -3.0 - Dimmer.
-2.0 - Normal. (default) -2.0 - Normal. (default)
-1.0 - Brighter. -1.0 - Brighter.
r_forceAutoExposureMax - Cheat. Set maximum exposure to this value, r_forceAutoExposureMax - Cheat. Set maximum exposure to this value,
in powers of two. Requires in powers of two. Requires
r_forceAutoExpsure. r_forceAutoExpsure.
1.0 - Dimmer. 1.0 - Dimmer.
2.0 - Normal. (default) 2.0 - Normal. (default)
3.0 - Brighter. 3.0 - Brighter.
r_srgb - Treat all input textures as sRGB, and do r_srgb - Treat all input textures as sRGB, and do
final rendering in a sRGB framebuffer. Only final rendering in a sRGB framebuffer. Only
required if assets were created with it in required if assets were created with it in
mind. mind.
0 - No. (default) 0 - No. (default)
1 - Yes. 1 - Yes.
@ -191,8 +197,8 @@ Cvars for advanced material usage:
1 - Yes. (default) 1 - Yes. (default)
2 - Yes, and use Oren-Nayar reflectance 2 - Yes, and use Oren-Nayar reflectance
model. model.
3 - Yes, and use tri-Ace's Oren-Nayar 3 - Yes, and use tri-Ace's Oren-Nayar
reflectance model. reflectance model.
r_specularMapping - Enable specular mapping for materials that r_specularMapping - Enable specular mapping for materials that
support it, and also specify advanced support it, and also specify advanced
@ -563,7 +569,7 @@ contributed thoughts, ideas, and whole swaths of code to this project.
- Zachary 'Zakk' Slater, Thilo Schulz, Tim Angus, and the rest of the - Zachary 'Zakk' Slater, Thilo Schulz, Tim Angus, and the rest of the
ioquake3 team and contributors, for improving massively upon the raw Quake ioquake3 team and contributors, for improving massively upon the raw Quake
3 source, and accepting my and gimhael's modular renderer patch. 3 source, and accepting my and gimhael's modular renderer patch.
- Robert 'Tr3B' Beckebans and the other contributors to XReaL, for letting me - Robert 'Tr3B' Beckebans and the other contributors to XReaL, for letting me
liberally copy code from you. :) liberally copy code from you. :)
@ -574,7 +580,7 @@ contributed thoughts, ideas, and whole swaths of code to this project.
- Yoshiharu Gotanda, Tatsuya Shoji, and the rest of tri-Ace's R&D Department, - Yoshiharu Gotanda, Tatsuya Shoji, and the rest of tri-Ace's R&D Department,
for creating the tri-Ace shading equations and posting their derivations in for creating the tri-Ace shading equations and posting their derivations in
simple English. simple English.
- Matthias 'gimhael' Bentrup, for random ideas and bits of code. - Matthias 'gimhael' Bentrup, for random ideas and bits of code.