From b641cdf4343692743e15b2427f183a92890e118f Mon Sep 17 00:00:00 2001 From: havoc Date: Sun, 16 Oct 2011 09:54:40 +0000 Subject: [PATCH] removed cvars r_hdr and r_hdr_range - now the only way to get HDR rendering is using r_viewfbo 2 (which is faster and nicer) implemented fbo rendering for water, bloom and gamma, setting r_viewfbo to 1 gives a consistent speed gain because it avoids all texture copies git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11426 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_rmain.c | 457 ++++++++++++++++++++++++++--------------------------- menu.c | 24 ++- r_shadow.c | 19 +-- render.h | 42 ++--- 4 files changed, 259 insertions(+), 283 deletions(-) diff --git a/gl_rmain.c b/gl_rmain.c index 0082d614..6c3af4a7 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -197,10 +197,8 @@ cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resol cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"}; cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"}; -cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"}; cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"}; cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"}; -cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"}; cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"}; cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"}; cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"}; @@ -4312,10 +4310,8 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_bloom_resolution); Cvar_RegisterVariable(&r_bloom_colorexponent); Cvar_RegisterVariable(&r_bloom_colorsubtract); - Cvar_RegisterVariable(&r_hdr); Cvar_RegisterVariable(&r_hdr_scenebrightness); Cvar_RegisterVariable(&r_hdr_glowintensity); - Cvar_RegisterVariable(&r_hdr_range); Cvar_RegisterVariable(&r_hdr_irisadaptation); Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier); Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue); @@ -5572,12 +5568,21 @@ static void R_Water_StartFrame(void) if (p->texture_refraction) R_FreeTexture(p->texture_refraction); p->texture_refraction = NULL; + if (p->fbo_refraction) + R_Mesh_DestroyFramebufferObject(p->fbo_refraction); + p->fbo_refraction = 0; if (p->texture_reflection) R_FreeTexture(p->texture_reflection); p->texture_reflection = NULL; + if (p->fbo_reflection) + R_Mesh_DestroyFramebufferObject(p->fbo_reflection); + p->fbo_reflection = 0; if (p->texture_camera) R_FreeTexture(p->texture_camera); p->texture_camera = NULL; + if (p->fbo_camera) + R_Mesh_DestroyFramebufferObject(p->fbo_camera); + p->fbo_camera = 0; } memset(&r_fb.water, 0, sizeof(r_fb.water)); r_fb.water.texturewidth = texturewidth; @@ -5758,24 +5763,45 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) { if (!p->texture_refraction) - p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); + p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); if (!p->texture_refraction) goto error; + if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object) + { + if (r_fb.water.depthtexture == NULL) + r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false); + if (p->fbo_refraction == 0) + p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL); + } } else if (p->materialflags & MATERIALFLAG_CAMERA) { if (!p->texture_camera) - p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL); + p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL); if (!p->texture_camera) goto error; + if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object) + { + if (r_fb.water.depthtexture == NULL) + r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false); + if (p->fbo_camera == 0) + p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL); + } } if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) { if (!p->texture_reflection) - p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); + p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); if (!p->texture_reflection) goto error; + if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object) + { + if (r_fb.water.depthtexture == NULL) + r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false); + if (p->fbo_reflection == 0) + p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL); + } } } @@ -5794,7 +5820,7 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t r_refdef.view = myview; if(r_water_scissormode.integer) { - R_SetupView(true, fbo, depthtexture, colortexture); + R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection); if(R_ScissorForBBox(p->mins, p->maxs, myscissor)) continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible } @@ -5817,7 +5843,7 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t } r_fb.water.hideplayer = r_water_hideplayer.integer >= 2; - R_ResetViewRendering3D(fbo, depthtexture, colortexture); + R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection); R_ClearScreen(r_refdef.fogenabled); if(r_water_scissormode.integer & 2) R_View_UpdateWithScissor(myscissor); @@ -5825,9 +5851,10 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t R_View_Update(); if(r_water_scissormode.integer & 1) GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]); - R_RenderScene(fbo, depthtexture, colortexture); + R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection); - R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); + if (!p->fbo_reflection) + R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); r_fb.water.hideplayer = false; } @@ -5838,7 +5865,7 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t r_refdef.view = myview; if(r_water_scissormode.integer) { - R_SetupView(true, fbo, depthtexture, colortexture); + R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction); if(R_ScissorForBBox(p->mins, p->maxs, myscissor)) continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible } @@ -5864,7 +5891,7 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t PlaneClassify(&r_refdef.view.clipplane); - R_ResetViewRendering3D(fbo, depthtexture, colortexture); + R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction); R_ClearScreen(r_refdef.fogenabled); if(r_water_scissormode.integer & 2) R_View_UpdateWithScissor(myscissor); @@ -5872,9 +5899,10 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t R_View_Update(); if(r_water_scissormode.integer & 1) GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]); - R_RenderScene(fbo, depthtexture, colortexture); + R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction); - R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); + if (!p->fbo_refraction) + R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); r_fb.water.hideplayer = false; } else if (p->materialflags & MATERIALFLAG_CAMERA) @@ -5920,12 +5948,13 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t r_fb.water.hideplayer = false; - R_ResetViewRendering3D(fbo, depthtexture, colortexture); + R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera); R_ClearScreen(r_refdef.fogenabled); R_View_Update(); - R_RenderScene(fbo, depthtexture, colortexture); + R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera); - R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); + if (!p->fbo_camera) + R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); r_fb.water.hideplayer = false; } @@ -5934,7 +5963,8 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t r_fb.water.renderingscene = false; r_refdef.view = originalview; R_ResetViewRendering3D(fbo, depthtexture, colortexture); - R_ClearScreen(r_refdef.fogenabled); + if (!r_fb.water.depthtexture) + R_ClearScreen(r_refdef.fogenabled); R_View_Update(); goto finish; error: @@ -5963,9 +5993,30 @@ finish: void R_Bloom_StartFrame(void) { + int i; int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight; int viewwidth, viewheight; - textype_t textype; + + r_fb.textype = TEXTYPE_COLORBUFFER; + switch (vid.renderpath) + { + case RENDERPATH_GL20: + case RENDERPATH_GLES2: + if (vid.support.ext_framebuffer_object) + { + if (r_viewfbo.integer == 2) r_fb.textype = TEXTYPE_COLORBUFFER16F; + if (r_viewfbo.integer == 3) r_fb.textype = TEXTYPE_COLORBUFFER32F; + } + break; + case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: + case RENDERPATH_D3D9: + case RENDERPATH_D3D10: + case RENDERPATH_D3D11: + case RENDERPATH_SOFT: + break; + } if (r_viewscale_fpsscaling.integer) { @@ -6025,93 +6076,93 @@ void R_Bloom_StartFrame(void) for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2); } - if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d)) + if ((r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d)) { - Cvar_SetValueQuick(&r_hdr, 0); Cvar_SetValueQuick(&r_bloom, 0); Cvar_SetValueQuick(&r_motionblur, 0); Cvar_SetValueQuick(&r_damageblur, 0); } - if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer) + if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer) screentexturewidth = screentextureheight = 0; - if (!r_hdr.integer && !r_bloom.integer) + if (!r_bloom.integer) bloomtexturewidth = bloomtextureheight = 0; - textype = TEXTYPE_COLORBUFFER; - switch (vid.renderpath) - { - case RENDERPATH_GL20: - case RENDERPATH_GLES2: - if (vid.support.ext_framebuffer_object) - { - if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F; - if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F; - } - break; - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GLES1: - case RENDERPATH_D3D9: - case RENDERPATH_D3D10: - case RENDERPATH_D3D11: - case RENDERPATH_SOFT: - break; - } - // allocate textures as needed if (r_fb.screentexturewidth != screentexturewidth || r_fb.screentextureheight != screentextureheight || r_fb.bloomtexturewidth != bloomtexturewidth || r_fb.bloomtextureheight != bloomtextureheight - || r_fb.texturetype != textype || r_fb.viewfbo != r_viewfbo.integer) { - if (r_fb.texture_bloom) - R_FreeTexture(r_fb.texture_bloom); - r_fb.texture_bloom = NULL; - if (r_fb.texture_screen) - R_FreeTexture(r_fb.texture_screen); - r_fb.texture_screen = NULL; - if (r_fb.fbo_framebuffer) - R_Mesh_DestroyFramebufferObject(r_fb.fbo_framebuffer); - r_fb.fbo_framebuffer = 0; - if (r_fb.texture_framebuffercolor) - R_FreeTexture(r_fb.texture_framebuffercolor); - r_fb.texture_framebuffercolor = NULL; - if (r_fb.texture_framebufferdepth) - R_FreeTexture(r_fb.texture_framebufferdepth); - r_fb.texture_framebufferdepth = NULL; + for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++) + { + if (r_fb.bloomtexture[i]) + R_FreeTexture(r_fb.bloomtexture[i]); + r_fb.bloomtexture[i] = NULL; + + if (r_fb.bloomfbo[i]) + R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]); + r_fb.bloomfbo[i] = 0; + } + + if (r_fb.fbo) + R_Mesh_DestroyFramebufferObject(r_fb.fbo); + r_fb.fbo = 0; + + if (r_fb.colortexture) + R_FreeTexture(r_fb.colortexture); + r_fb.colortexture = NULL; + + if (r_fb.depthtexture) + R_FreeTexture(r_fb.depthtexture); + r_fb.depthtexture = NULL; + + if (r_fb.ghosttexture) + R_FreeTexture(r_fb.ghosttexture); + r_fb.ghosttexture = NULL; + r_fb.screentexturewidth = screentexturewidth; r_fb.screentextureheight = screentextureheight; + r_fb.bloomtexturewidth = bloomtexturewidth; + r_fb.bloomtextureheight = bloomtextureheight; + r_fb.viewfbo = r_viewfbo.integer; + if (r_fb.screentexturewidth && r_fb.screentextureheight) - r_fb.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); - if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object) - { - // FIXME: choose depth bits based on a cvar - r_fb.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false); - r_fb.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); - r_fb.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor, NULL, NULL, NULL); - R_Mesh_SetRenderTargets(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor, NULL, NULL, NULL); -#ifndef USE_GLES2 - // render depth into one texture and normalmap into the other - if (qglDrawBuffer) + { + if (r_motionblur.value > 0 || r_damageblur.value > 0) + r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); + r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); + if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object) { - int status; - qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR - qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR - status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR - if (status != GL_FRAMEBUFFER_COMPLETE) - Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status); - } + // FIXME: choose depth bits based on a cvar + r_fb.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false); + r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL); + R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL); +#ifndef USE_GLES2 + // render depth into one texture and color into the other + if (qglDrawBuffer) + { + int status; + qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR + qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR + status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR + if (status != GL_FRAMEBUFFER_COMPLETE) + Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status); + } #endif + } } - r_fb.bloomtexturewidth = bloomtexturewidth; - r_fb.bloomtextureheight = bloomtextureheight; + if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight) - r_fb.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); - r_fb.viewfbo = r_viewfbo.integer; - r_fb.texturetype = textype; + { + for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++) + { + r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); + if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object) + r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL); + } + } } // bloom texture is a different resolution @@ -6168,26 +6219,32 @@ void R_Bloom_StartFrame(void) break; } - if ((r_hdr.integer || r_bloom.integer) && r_fb.bloomwidth) - { - r_fb.enabled = true; - r_fb.hdr = r_hdr.integer != 0 && !r_fb.fbo_framebuffer; - } - - R_Viewport_InitOrtho(&r_fb.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_fb.bloomheight - r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL); + R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, r_refdef.view.x, (r_fb.bloomfbo[0] ? r_fb.bloomtextureheight : vid.height) - r_fb.bloomheight - r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL); - if (r_fb.fbo_framebuffer) + if (r_fb.fbo) r_refdef.view.clear = true; } -void R_Bloom_CopyBloomTexture(float colorscale) +void R_Bloom_MakeTexture(void) { + int x, range, dir; + float xoffset, yoffset, r, brighten; + rtexture_t *intex; + float colorscale = r_bloom_colorscale.value; + r_refdef.stats.bloom++; + if (!r_fb.fbo) + { + R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); + r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; + } + // scale down screen texture to the bloom texture size CHECKGLERROR - R_Mesh_SetRenderTargets(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor, NULL, NULL, NULL); - R_SetViewport(&r_fb.viewport); + r_fb.bloomindex = 0; + R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL); + R_SetViewport(&r_fb.bloomviewport); GL_BlendFunc(GL_ONE, GL_ZERO); GL_Color(colorscale, colorscale, colorscale, 1); // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that... @@ -6208,66 +6265,57 @@ void R_Bloom_CopyBloomTexture(float colorscale) break; } // TODO: do boxfilter scale-down in shader? - R_SetupShader_Generic(r_fb.texture_screen, NULL, GL_MODULATE, 1, false, true); + R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight; - // we now have a bloom image in the framebuffer - // copy it into the bloom image texture for later processing - R_Mesh_CopyToTexture(r_fb.texture_bloom, 0, 0, r_fb.viewport.x, r_fb.viewport.y, r_fb.viewport.width, r_fb.viewport.height); - r_refdef.stats.bloom_copypixels += r_fb.viewport.width * r_fb.viewport.height; -} - -void R_Bloom_CopyHDRTexture(void) -{ - R_Mesh_CopyToTexture(r_fb.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); - r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; -} - -void R_Bloom_MakeTexture(void) -{ - int x, range, dir; - float xoffset, yoffset, r, brighten; - - r_refdef.stats.bloom++; - - R_ResetViewRendering2D(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor); - - // we have a bloom image in the framebuffer - CHECKGLERROR - R_SetViewport(&r_fb.viewport); + // we now have a properly scaled bloom image + if (!r_fb.bloomfbo[r_fb.bloomindex]) + { + // copy it into the bloom texture + R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height); + r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height; + } + // multiply bloom image by itself as many times as desired for (x = 1;x < min(r_bloom_colorexponent.value, 32);) { + intex = r_fb.bloomtexture[r_fb.bloomindex]; + r_fb.bloomindex ^= 1; + R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL); x *= 2; r = bound(0, r_bloom_colorexponent.value / x, 1); GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); GL_Color(r,r,r,1); R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f); - R_SetupShader_Generic(r_fb.texture_bloom, NULL, GL_MODULATE, 1, false, true); + R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight; - // copy the vertically blurred bloom view to a texture - R_Mesh_CopyToTexture(r_fb.texture_bloom, 0, 0, r_fb.viewport.x, r_fb.viewport.y, r_fb.viewport.width, r_fb.viewport.height); - r_refdef.stats.bloom_copypixels += r_fb.viewport.width * r_fb.viewport.height; + if (!r_fb.bloomfbo[r_fb.bloomindex]) + { + // copy the darkened image to a texture + R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height); + r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height; + } } range = r_bloom_blur.integer * r_fb.bloomwidth / 320; brighten = r_bloom_brighten.value; - if (r_fb.hdr) - brighten *= r_hdr_range.value; brighten = sqrt(brighten); if(range >= 1) brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle" - R_SetupShader_Generic(r_fb.texture_bloom, NULL, GL_MODULATE, 1, false, true); for (dir = 0;dir < 2;dir++) { + intex = r_fb.bloomtexture[r_fb.bloomindex]; + r_fb.bloomindex ^= 1; + R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL); // blend on at multiple vertical offsets to achieve a vertical blur // TODO: do offset blends using GLSL // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges GL_BlendFunc(GL_ONE, GL_ZERO); + R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true); for (x = -range;x <= range;x++) { if (!dir){xoffset = 0;yoffset = x;} @@ -6298,72 +6346,15 @@ void R_Bloom_MakeTexture(void) GL_BlendFunc(GL_ONE, GL_ONE); } - // copy the vertically blurred bloom view to a texture - R_Mesh_CopyToTexture(r_fb.texture_bloom, 0, 0, r_fb.viewport.x, r_fb.viewport.y, r_fb.viewport.width, r_fb.viewport.height); - r_refdef.stats.bloom_copypixels += r_fb.viewport.width * r_fb.viewport.height; + if (!r_fb.bloomfbo[r_fb.bloomindex]) + { + // copy the vertically or horizontally blurred bloom view to a texture + R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height); + r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height; + } } } -void R_HDR_RenderBloomTexture(void) -{ - int oldwidth, oldheight; - float oldcolorscale; - qboolean oldwaterstate; - - oldwaterstate = r_fb.water.enabled; - oldcolorscale = r_refdef.view.colorscale; - oldwidth = r_refdef.view.width; - oldheight = r_refdef.view.height; - r_refdef.view.width = r_fb.bloomwidth; - r_refdef.view.height = r_fb.bloomheight; - - if(r_hdr.integer < 2) - r_fb.water.enabled = false; - - // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance. - // TODO: add exposure compensation features - // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object) - - r_refdef.view.showdebug = false; - r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16); - - R_ResetViewRendering3D(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor); - - R_ClearScreen(r_refdef.fogenabled); - if (r_timereport_active) - R_TimeReport("HDRclear"); - - R_View_Update(); - if (r_timereport_active) - R_TimeReport("visibility"); - - // only do secondary renders with HDR if r_hdr is 2 or higher - r_fb.water.numwaterplanes = 0; - if (r_fb.water.enabled) - R_RenderWaterPlanes(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor); - - r_refdef.view.showdebug = true; - R_RenderScene(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor); - r_fb.water.numwaterplanes = 0; - - R_ResetViewRendering2D(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor); - - R_Bloom_CopyHDRTexture(); - R_Bloom_MakeTexture(); - - // restore the view settings - r_fb.water.enabled = oldwaterstate; - r_refdef.view.width = oldwidth; - r_refdef.view.height = oldheight; - r_refdef.view.colorscale = oldcolorscale; - - R_ResetViewRendering3D(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor); - - R_ClearScreen(r_refdef.fogenabled); - if (r_timereport_active) - R_TimeReport("viewclear"); -} - static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) { unsigned int permutation; @@ -6378,18 +6369,19 @@ static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortext case RENDERPATH_SOFT: case RENDERPATH_GLES2: permutation = - (r_fb.texture_bloom ? SHADERPERMUTATION_BLOOM : 0) + (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0) | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0) | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0) | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0) | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0); - if (r_fb.texture_screen) + if (r_fb.colortexture) { - // make sure the buffer is available - if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); } - - R_ResetViewRendering2D(fbo, depthtexture, colortexture); + if (!r_fb.fbo) + { + R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); + r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; + } if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0)) { @@ -6409,10 +6401,10 @@ static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortext // from the goal, pick an averaged value between goal and last value cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1); blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha; - + // enforce minimum amount of blur blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value; - + //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel); // calculate values into a standard alpha @@ -6425,13 +6417,14 @@ static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortext / max(0.0001, cl.time - cl.oldtime) // fps independent ); - + // randomization for the blur value to combat persistent ghosting cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value); cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value); - + // apply the blur - if (cl.motionbluralpha > 0 && !r_refdef.envmap) + R_ResetViewRendering2D(fbo, depthtexture, colortexture); + if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture) { GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_Color(1, 1, 1, cl.motionbluralpha); @@ -6451,21 +6444,24 @@ static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortext R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f); break; } - R_SetupShader_Generic(r_fb.texture_screen, NULL, GL_MODULATE, 1, false, true); + R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; } - - // updates old view angles for next pass + + // updates old view angles for next pass VectorCopy(cl.viewangles, blur_oldangles); - } - // copy view into the screen texture - R_Mesh_CopyToTexture(r_fb.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); - r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; + // copy view into the ghost texture + if (!r_fb.ghosttexture) + r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "motionblurtexture", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL); + R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); + r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; + } } else { + // no r_fb.colortexture means we're rendering to the real fb // we may still have to do view tint... if (r_refdef.viewblend[3] >= (1.0f / 256.0f)) { @@ -6480,11 +6476,8 @@ static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortext break; // no screen processing, no bloom, skip it } - if (r_fb.texture_bloom && !r_fb.hdr) + if (r_fb.bloomtexture[0]) { - // render simple bloom effect - // copy the screen and shrink it and darken it for the bloom process - R_Bloom_CopyBloomTexture(r_bloom_colorscale.value); // make the bloom texture R_Bloom_MakeTexture(); } @@ -6502,7 +6495,7 @@ static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortext if (r_glsl_postprocess_uservec4_enable.integer) sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]); - R_ResetViewRendering2D(0, NULL, NULL); + R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer! GL_Color(1, 1, 1, 1); GL_BlendFunc(GL_ONE, GL_ZERO); @@ -6512,8 +6505,8 @@ static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortext case RENDERPATH_GLES2: R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f); R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation); - if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.texture_screen); - if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.texture_bloom ); + if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture); + if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]); if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps ); if (r_glsl_permutation->loc_ViewTintColor >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight); @@ -6530,8 +6523,8 @@ static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortext // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that... R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f); R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation); - R_Mesh_TexBind(GL20TU_FIRST , r_fb.texture_screen); - R_Mesh_TexBind(GL20TU_SECOND , r_fb.texture_bloom ); + R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture); + R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture); R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps ); hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight); @@ -6553,8 +6546,8 @@ static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortext case RENDERPATH_SOFT: R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f); R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation); - R_Mesh_TexBind(GL20TU_FIRST , r_fb.texture_screen); - R_Mesh_TexBind(GL20TU_SECOND , r_fb.texture_bloom ); + R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture); + R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]); R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps ); DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight); @@ -6903,9 +6896,9 @@ void R_RenderView(void) R_Water_StartFrame(); // now we probably have an fbo to render into - fbo = r_fb.fbo_framebuffer; - depthtexture = r_fb.texture_framebufferdepth; - colortexture = r_fb.texture_framebuffercolor; + fbo = r_fb.fbo; + depthtexture = r_fb.depthtexture; + colortexture = r_fb.colortexture; CHECKGLERROR if (r_timereport_active) @@ -6921,14 +6914,6 @@ void R_RenderView(void) } r_refdef.view.clear = true; - // this produces a bloom texture to be used in R_BlendView() later - if (r_fb.hdr) - { - R_HDR_RenderBloomTexture(); - // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures - r_textureframe++; // used only by R_GetCurrentTexture - } - r_refdef.view.showdebug = true; R_View_Update(); @@ -6990,8 +6975,8 @@ extern cvar_t cl_locs_show; static void R_DrawLocs(void); static void R_DrawEntityBBoxes(void); static void R_DrawModelDecals(void); -extern void R_DrawModelShadows(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture); -extern void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture); +extern void R_DrawModelShadows(void); +extern void R_DrawModelShadowMaps(void); extern cvar_t cl_decals_newsystem; extern qboolean r_shadow_usingdeferredprepass; void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) @@ -7073,7 +7058,7 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0) { R_ResetViewRendering3D(fbo, depthtexture, colortexture); - R_DrawModelShadowMaps(fbo, depthtexture, colortexture); + R_DrawModelShadowMaps(); R_ResetViewRendering3D(fbo, depthtexture, colortexture); // don't let sound skip if going slow if (r_refdef.scene.extraupdate) @@ -7102,7 +7087,7 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0) { R_ResetViewRendering3D(fbo, depthtexture, colortexture); - R_DrawModelShadows(fbo, depthtexture, colortexture); + R_DrawModelShadows(); R_ResetViewRendering3D(fbo, depthtexture, colortexture); // don't let sound skip if going slow if (r_refdef.scene.extraupdate) @@ -7123,7 +7108,7 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0) { R_ResetViewRendering3D(fbo, depthtexture, colortexture); - R_DrawModelShadows(fbo, depthtexture, colortexture); + R_DrawModelShadows(); R_ResetViewRendering3D(fbo, depthtexture, colortexture); // don't let sound skip if going slow if (r_refdef.scene.extraupdate) @@ -7232,8 +7217,6 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) // don't let sound skip if going slow if (r_refdef.scene.extraupdate) S_ExtraUpdate (); - - R_ResetViewRendering2D(fbo, depthtexture, colortexture); } static const unsigned short bboxelements[36] = diff --git a/menu.c b/menu.c index c09abda4..f61dc5e8 100644 --- a/menu.c +++ b/menu.c @@ -1978,10 +1978,8 @@ extern cvar_t r_bloom_colorexponent; extern cvar_t r_bloom_blur; extern cvar_t r_bloom_brighten; extern cvar_t r_bloom_resolution; -extern cvar_t r_hdr; extern cvar_t r_hdr_scenebrightness; extern cvar_t r_hdr_glowintensity; -extern cvar_t r_hdr_range; extern cvar_t gl_picmip; static void M_Menu_Options_Graphics_AdjustSliders (int dir) @@ -1999,10 +1997,8 @@ static void M_Menu_Options_Graphics_AdjustSliders (int dir) else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_shadow_realtime_world, !r_shadow_realtime_world.integer); else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_shadow_realtime_world_lightmaps, bound(0, r_shadow_realtime_world_lightmaps.value + dir * 0.1, 1)); else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_shadow_realtime_world_shadows, !r_shadow_realtime_world_shadows.integer); - else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_hdr_scenebrightness, bound(0.25, r_hdr_scenebrightness.value + dir * 0.125, 4)); else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_bloom, !r_bloom.integer); - else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_hdr, !r_hdr.integer); - else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_hdr_range, bound(1, r_hdr_range.value + dir * 0.25, 16)); + else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_hdr_scenebrightness, bound(0.25, r_hdr_scenebrightness.value + dir * 0.125, 4)); else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_hdr_glowintensity, bound(0, r_hdr_glowintensity.value + dir * 0.25, 4)); else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_bloom_colorscale, bound(0.0625, r_bloom_colorscale.value + dir * 0.0625, 1)); else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_bloom_colorsubtract, bound(0, r_bloom_colorsubtract.value + dir * 0.0625, 1-0.0625)); @@ -2038,17 +2034,15 @@ static void M_Options_Graphics_Draw (void) M_Options_PrintCheckbox(" RT World", true, r_shadow_realtime_world.integer); M_Options_PrintSlider( " RT World Lightmaps", true, r_shadow_realtime_world_lightmaps.value, 0, 1); M_Options_PrintCheckbox(" RT World Shadow", true, r_shadow_realtime_world_shadows.integer); + M_Options_PrintCheckbox(" Bloom Effect", true, r_bloom.integer); M_Options_PrintSlider( " Scene Brightness", true, r_hdr_scenebrightness.value, 0.25, 4); - M_Options_PrintCheckbox(" Bloom Effect", !r_hdr.integer, r_bloom.integer); - M_Options_PrintCheckbox(" HDR Bloom Effect", true, r_hdr.integer); - M_Options_PrintSlider( " HDR Dynamic Range", r_hdr.integer, r_hdr_range.value, 1, 16); - M_Options_PrintSlider( " HDR Glow Intensity", r_hdr.integer, r_hdr_glowintensity.value, 0, 4); - M_Options_PrintSlider( " Bloom Color Scale", r_hdr.integer || r_bloom.integer, r_bloom_colorscale.value, 0.0625, 1); - M_Options_PrintSlider( " Bloom Color Subtract", r_hdr.integer || r_bloom.integer, r_bloom_colorsubtract.value, 0, 1-0.0625); - M_Options_PrintSlider( " Bloom Color Exponent", r_hdr.integer || r_bloom.integer, r_bloom_colorexponent.value, 1, 8); - M_Options_PrintSlider( " Bloom Intensity", r_hdr.integer || r_bloom.integer, r_bloom_brighten.value, 1, 4); - M_Options_PrintSlider( " Bloom Blur", r_hdr.integer || r_bloom.integer, r_bloom_blur.value, 1, 16); - M_Options_PrintSlider( " Bloom Resolution", r_hdr.integer || r_bloom.integer, r_bloom_resolution.value, 64, 2048); + M_Options_PrintSlider( " Glow Brightness", true, r_hdr_glowintensity.value, 0, 4); + M_Options_PrintSlider( " Bloom Color Scale", r_bloom.integer, r_bloom_colorscale.value, 0.0625, 1); + M_Options_PrintSlider( " Bloom Color Subtract", r_bloom.integer, r_bloom_colorsubtract.value, 0, 1-0.0625); + M_Options_PrintSlider( " Bloom Color Exponent", r_bloom.integer, r_bloom_colorexponent.value, 1, 8); + M_Options_PrintSlider( " Bloom Intensity", r_bloom.integer, r_bloom_brighten.value, 1, 4); + M_Options_PrintSlider( " Bloom Blur", r_bloom.integer, r_bloom_blur.value, 1, 16); + M_Options_PrintSlider( " Bloom Resolution", r_bloom.integer, r_bloom_resolution.value, 64, 2048); M_Options_PrintCommand( " Restart Renderer", true); } diff --git a/r_shadow.c b/r_shadow.c index 26cc9531..c5d14ec2 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -2143,7 +2143,7 @@ void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size) float nearclip, farclip, bias; r_viewport_t viewport; int flipped; - GLuint fbo = 0; + GLuint fbo2d = 0; float clearcolor[4]; nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius; farclip = 1.0f; @@ -2163,14 +2163,14 @@ void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size) R_Shadow_MakeVSDCT(); if (!r_shadow_shadowmap2dtexture) R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize); - if (r_shadow_shadowmap2dtexture) fbo = r_shadow_fbo2d; + if (r_shadow_shadowmap2dtexture) fbo2d = r_shadow_fbo2d; r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture); r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture); r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D; R_Mesh_ResetTextureState(); R_Shadow_RenderMode_Reset(); - R_Mesh_SetRenderTargets(fbo, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL); + R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL); R_SetupShader_DepthOrShadow(true); GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value); GL_DepthMask(true); @@ -2234,7 +2234,6 @@ init_done: void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping) { R_Mesh_ResetTextureState(); - R_Mesh_SetRenderTargets(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture, NULL, NULL, NULL); if (transparent) { r_shadow_lightscissor[0] = r_refdef.view.viewport.x; @@ -4484,8 +4483,6 @@ void R_Shadow_DrawPrepass(void) if (r_refdef.scene.lights[lnum]->draw) R_Shadow_DrawLight(r_refdef.scene.lights[lnum]); - R_Mesh_SetRenderTargets(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture, NULL, NULL, NULL); - R_Shadow_RenderMode_End(); if (r_timereport_active) @@ -4545,14 +4542,14 @@ void R_Shadow_PrepareLights(int fbo, rtexture_t *depthtexture, rtexture_t *color switch (vid.renderpath) { case RENDERPATH_D3D9: - r_shadow_prepassgeometrydepthcolortexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrydepthcolormap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL); + r_shadow_prepassgeometrydepthcolortexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrydepthcolormap", vid.width, vid.height, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL); break; default: break; } - r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL); - r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL); - r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL); + r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL); + r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL); + r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL); // set up the geometry pass fbo (depth + normalmap) r_shadow_prepassgeometryfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL); @@ -4807,7 +4804,7 @@ void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colort case R_SHADOW_SHADOWMODE_SHADOWMAP2D: if (!r_shadow_shadowmap2dtexture) R_Shadow_MakeShadowMap(0, r_shadow_shadowmapmaxsize); - fbo2d = r_shadow_fbo2d; + fbo = r_shadow_fbo2d; r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture); r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture); r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D; diff --git a/render.h b/render.h index a3fc44cc..890d838d 100644 --- a/render.h +++ b/render.h @@ -448,9 +448,12 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight); typedef struct r_waterstate_waterplane_s { - rtexture_t *texture_refraction; - rtexture_t *texture_reflection; - rtexture_t *texture_camera; + rtexture_t *texture_refraction; // MATERIALFLAG_WATERSHADER or MATERIALFLAG_REFRACTION + rtexture_t *texture_reflection; // MATERIALFLAG_WATERSHADER or MATERIALFLAG_REFLECTION + rtexture_t *texture_camera; // MATERIALFLAG_CAMERA + int fbo_refraction; + int fbo_reflection; + int fbo_camera; mplane_t plane; int materialflags; // combined flags of all water surfaces on this plane unsigned char pvsbits[(MAX_MAP_LEAFS+7)>>3]; // FIXME: buffer overflow on huge maps @@ -470,6 +473,7 @@ typedef struct r_waterstate_s int waterwidth, waterheight; int texturewidth, textureheight; int camerawidth, cameraheight; + rtexture_t *depthtexture; int maxwaterplanes; // same as MAX_WATERPLANES int numwaterplanes; @@ -482,30 +486,28 @@ r_waterstate_t; typedef struct r_framebufferstate_s { - qboolean enabled; - qboolean hdr; - - int bloomwidth, bloomheight; + int viewfbo; // copy of r_viewfbo cvar (to cause reallocation of textures if needed) - textype_t texturetype; - int viewfbo; // used to check if r_viewfbo cvar has changed + textype_t textype; // type of color buffer we're using (dependent on r_viewfbo cvar) + int fbo; // non-zero if r_viewfbo is enabled and working + int screentexturewidth, screentextureheight; // dimensions of texture - int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working - rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero - rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero - - int screentexturewidth, screentextureheight; - rtexture_t *texture_screen; /// \note also used for motion blur if enabled! + rtexture_t *colortexture; // non-NULL if fbo is non-zero + rtexture_t *depthtexture; // non-NULL if fbo is non-zero + rtexture_t *ghosttexture; // for r_motionblur (not recommended on multi-GPU hardware!) + rtexture_t *bloomtexture[2]; // for r_bloom, multi-stage processing + int bloomfbo[2]; // fbos for rendering into bloomtexture[] + int bloomindex; // which bloomtexture[] contains the final image + int bloomwidth, bloomheight; int bloomtexturewidth, bloomtextureheight; - rtexture_t *texture_bloom; // arrays for rendering the screen passes - float screentexcoord2f[8]; - float bloomtexcoord2f[8]; - float offsettexcoord2f[8]; + float screentexcoord2f[8]; // texcoords for colortexture or ghosttexture + float bloomtexcoord2f[8]; // texcoords for bloomtexture[] + float offsettexcoord2f[8]; // temporary use while updating bloomtexture[] - r_viewport_t viewport; + r_viewport_t bloomviewport; r_waterstate_t water; } -- 2.39.2