From 54c0810d41c0ab28c18eafc7fc5c8ba08390bf0d Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 19 Aug 2014 06:08:23 +0000 Subject: [PATCH] fix nq bob (also fixes show_speed in nq) tweaked waterwarp+bloom to use fbos. this fixes any issues with viewsize 10 or whatever, but depends upon npot. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4727 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_input.c | 2 +- engine/client/cl_parse.c | 14 +- engine/client/cl_pred.c | 16 +- engine/client/r_2d.c | 6 +- engine/client/r_surf.c | 3 + engine/common/protocol.h | 18 +- engine/gl/gl_bloom.c | 612 +----------------------- engine/gl/gl_rmain.c | 170 +++++-- engine/gl/glquake.h | 3 +- engine/gl/r_bishaders.h | 2 +- engine/shaders/glsl/underwaterwarp.glsl | 2 +- 11 files changed, 183 insertions(+), 665 deletions(-) diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 6f8827cd9..90079ac98 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -1561,7 +1561,7 @@ void CL_SendCmd (double frametime, qboolean mainloop) CL_ProxyMenuHooks(); - if (cls.demoplayback != DPB_NONE) + if (cls.demoplayback != DPB_NONE || cls.netchan.remote_address.type == NA_INVALID) { if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 5a6a932ea..67015de92 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -3373,6 +3373,7 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon); void CLNQ_ParseClientdata (void) { int i; + player_state_t *pl = &cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[cl.playerview[0].playernum]; unsigned int bits; @@ -3393,7 +3394,6 @@ void CLNQ_ParseClientdata (void) /*else cl.idealpitch = 0;*/ -// VectorCopy (cl.mvelocity[0], cl.mvelocity[1]); for (i=0 ; i<3 ; i++) { if (bits & (SU_PUNCH1<velocity[i] = MSG_ReadFloat(); else - /*cl.mvelocity[0][i] =*/ MSG_ReadChar()/**16*/; + pl->velocity[i] = MSG_ReadChar()*16; } -// else -// cl.mvelocity[0][i] = 0; + else + pl->velocity[i] = 0; } if ((bits & SU_ITEMS) || cls.protocol_nq == CPNQ_ID) //hipnotic bug - hipnotic demos don't always have SU_ITEMS set, yet they update STAT_ITEMS anyway. CL_SetStatInt(0, STAT_ITEMS, MSG_ReadLong()); -// cl.onground = (bits & SU_ONGROUND) != 0; + pl->onground = (bits & SU_ONGROUND) != 0; // cl.inwater = (bits & SU_INWATER) != 0; if (cls.protocol_nq == CPNQ_DP5) diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 2621d863c..ea12c2e90 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -699,6 +699,9 @@ static void CL_EntStateToPlayerState(player_state_t *plstate, entity_state_t *st { vec3_t a; int pmtype; + qboolean onground = plstate->onground; + vec3_t vel; + VectorCopy(plstate->velocity, vel); memset(plstate, 0, sizeof(*plstate)); switch(state->u.q1.pmovetype) { @@ -732,7 +735,13 @@ static void CL_EntStateToPlayerState(player_state_t *plstate, entity_state_t *st plstate->pm_type = pmtype; VectorCopy(state->origin, plstate->origin); - VectorScale(state->u.q1.velocity, 1/8.0, plstate->velocity); + if (cls.protocol == CP_NETQUAKE && !(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)) + { //nq is annoying, this stuff wasn't part of the entity state, so don't break it + VectorCopy(vel, plstate->velocity); + plstate->onground = onground; + } + else + VectorScale(state->u.q1.velocity, 1/8.0, plstate->velocity); VectorCopy(state->angles, plstate->viewangles); plstate->viewangles[0] *= -3; @@ -1178,7 +1187,10 @@ void CL_PredictMovePNum (int seat) } } } - CL_CatagorizePosition(pv, tostate->origin); + if (cls.protocol == CP_NETQUAKE && nopred) + pv->onground = tostate->onground; + else + CL_CatagorizePosition(pv, tostate->origin); if (le) { diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index 45f09b0ca..d22ff7844 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -1301,9 +1301,9 @@ texid_t R2D_RT_Configure(const char *id, int width, int height, uploadfmt_t rtfm } else { - tid = R_FindTexture(id, IF_NOMIPMAP); + tid = R_FindTexture(id, IF_NOMIPMAP|IF_CLAMP|IF_LINEAR); if (!TEXVALID(tid)) - tid = R_AllocNewTexture(id, 0, 0, IF_NOMIPMAP); + tid = R_AllocNewTexture(id, 0, 0, IF_NOMIPMAP|IF_CLAMP|IF_LINEAR); } if (rtfmt) { @@ -1317,7 +1317,7 @@ texid_t R2D_RT_Configure(const char *id, int width, int height, uploadfmt_t rtfm case 6: rtfmt = TF_DEPTH32; break; default:rtfmt = TF_INVALID; break; } - R_Upload(tid, id, rtfmt, NULL, NULL, width, height, IF_NOMIPMAP); + R_Upload(tid, id, rtfmt, NULL, NULL, width, height, IF_NOMIPMAP|IF_CLAMP|IF_LINEAR); tid.ref->width = width; tid.ref->height = height; } diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 26d0738c1..bd728ad1a 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -1986,6 +1986,9 @@ void Surf_SetupFrame(void) mleaf_t *leaf; vec3_t temp, pvsorg; + if (!cl.worldmodel || (!cl.worldmodel->nodes && cl.worldmodel->type != mod_heightmap)) + r_refdef.flags |= RDF_NOWORLDMODEL; + R_AnimateLight(); r_framecount++; diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 5aea14cf9..4f7081d82 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -1153,13 +1153,19 @@ typedef struct q1usercmd_s #define RF_FORCECOLOURMOD (1u<<22) //forces BEF_FORCECOLOURMOD // player_state_t->refdef flags -#define Q2RDF_UNDERWATER 1 // warp the screen as apropriate -#define RDF_NOWORLDMODEL 2 // used for player configuration screen +#define RDF_UNDERWATER (1u<<0) // warp the screen as apropriate (fov trick) +#define RDF_NOWORLDMODEL (1u<<1) // used for player configuration screen +//ROGUE +#define Q2RDF_IRGOGGLES (1u<<2) //ents with Q2RF_IR_VISIBLE show up pure red. +#define Q2RDF_UVGOGGLES (1u<<3) //usused / reserved +//ROGUE +#define RDF_BLOOM (1u<<16) +#define RDF_FISHEYE (1u<<17) +#define RDF_WATERWARP (1u<<18) +#define RDF_CUSTOMPOSTPROC (1u<<19) + +#define RDF_ALLPOSTPROC (RDF_BLOOM|RDF_FISHEYE|RDF_WATERWARP|RDF_CUSTOMPOSTPROC) //these flags require rendering to an fbo for the various different post-processing shaders. -//ROGUE -#define Q2RDF_IRGOGGLES 4 //ents with Q2RF_IR_VISIBLE show up pure red. -#define Q2RDF_UVGOGGLES 8 //usused / reserved -//ROGUE diff --git a/engine/gl/gl_bloom.c b/engine/gl/gl_bloom.c index dd140dfd9..ed0e640cf 100644 --- a/engine/gl/gl_bloom.c +++ b/engine/gl/gl_bloom.c @@ -53,7 +53,6 @@ static shader_t *bloomblur; static shader_t *bloomfinal; #define MAXLEVELS 3 -texid_t scrtex; texid_t pingtex[2][MAXLEVELS]; fbostate_t fbo_bloom; static int scrwidth, scrheight; @@ -69,7 +68,6 @@ static void R_InitBloomTextures(void) bloomfinal = NULL; scrwidth = 0, scrheight = 0; - scrtex = r_nulltex; for (i = 0; i < MAXLEVELS; i++) { pingtex[0][i] = r_nulltex; @@ -108,17 +106,6 @@ static void R_SetupBloomTextures(int w, int h) texheight[i] = h; } - /*we should be doing this outside of this code*/ - if (!TEXVALID(scrtex)) - scrtex = GL_AllocNewTexture("", scrwidth, scrheight, IF_NOMIPMAP|IF_NOPICMIP); - GL_MTBind(0, GL_TEXTURE_2D, scrtex); - qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, scrwidth, scrheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - /*top level uses nearest sampling*/ - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - /*now create textures for each level*/ for (j = 0; j < MAXLEVELS; j++) { @@ -127,7 +114,7 @@ static void R_SetupBloomTextures(int w, int h) if (!TEXVALID(pingtex[i][j])) { sprintf(name, "***bloom*%c*%i***", 'a'+i, j); - TEXASSIGN(pingtex[i][j], GL_AllocNewTexture(name, texwidth[j], texheight[j], IF_NOMIPMAP|IF_NOPICMIP)); + TEXASSIGN(pingtex[i][j], GL_AllocNewTexture(name, texwidth[j], texheight[j], IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR)); } GL_MTBind(0, GL_TEXTURE_2D, pingtex[i][j]); qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, texwidth[j], texheight[j], 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); @@ -185,30 +172,31 @@ static void R_SetupBloomTextures(int w, int h) bloomfinal->defaulttextures.loweroverlay = pingtex[0][1]; bloomfinal->defaulttextures.upperoverlay = pingtex[0][2]; } -void R_BloomBlend (void) +qboolean R_CanBloom(void) +{ + if (!r_bloom.value) + return false; + if (!gl_config.ext_framebuffer_objects) + return false; + if (!gl_config.arb_shader_objects) + return false; + if (!r_config.texture_non_power_of_two) + return false; + + return true; +} + +void R_BloomBlend (texid_t source, int x, int y, int w, int h) { int i; int oldfbo = 0; - if (!gl_config.ext_framebuffer_objects) - return; - if (!gl_config.arb_shader_objects) - return; - if (!r_config.texture_non_power_of_two) - return; - /*whu?*/ - if (!r_refdef.pxrect.width || !r_refdef.pxrect.height) + if (!w || !h) return; /*update textures if we need to resize them*/ - R_SetupBloomTextures(r_refdef.pxrect.width, r_refdef.pxrect.height); - - /*grab the screen, because we failed to do it earlier*/ - GL_MTBind(0, GL_TEXTURE_2D, scrtex); - qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.pxrect.x, r_refdef.pxrect.maxheight - (r_refdef.pxrect.y+r_refdef.pxrect.height), r_refdef.pxrect.width, r_refdef.pxrect.height); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + R_SetupBloomTextures(w, h); for (i = 0; i < MAXLEVELS; i++) { @@ -216,7 +204,7 @@ void R_BloomBlend (void) { /*filter the screen into a downscaled image*/ oldfbo = GLBE_FBO_Update(&fbo_bloom, 0, &pingtex[0][0], 1, r_nulltex, 0, 0); - GLBE_FBO_Sources(scrtex, r_nulltex); + GLBE_FBO_Sources(source, r_nulltex); qglViewport (0, 0, texwidth[0], texheight[0]); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomfilter); } @@ -256,8 +244,8 @@ void R_BloomBlend (void) /*combine them onto the screen*/ GLBE_FBO_Pop(oldfbo); - GLBE_FBO_Sources(scrtex, r_nulltex); - R2D_ScalePic(r_refdef.vrect.x, r_refdef.vrect.y + r_refdef.vrect.height, r_refdef.vrect.width, -r_refdef.vrect.height, bloomfinal); + GLBE_FBO_Sources(source, r_nulltex); + R2D_ScalePic(x, y + h, w, -h, bloomfinal); } void R_BloomShutdown(void) { @@ -266,562 +254,4 @@ void R_BloomShutdown(void) R_InitBloomTextures(); } -#elif defined(GLQUAKE) -#include "glquake.h" - -/* -============================================================================== - - LIGHT BLOOMS - -============================================================================== -*/ - -cvar_t r_bloom = CVARAFD("r_bloom", "0", "gl_bloom", CVAR_ARCHIVE, "Enables bloom (light bleeding from bright objects)"); -cvar_t r_bloom_alpha = CVAR("r_bloom_alpha", "0.5"); -cvar_t r_bloom_diamond_size = CVAR("r_bloom_diamond_size", "8"); -cvar_t r_bloom_intensity = CVAR("r_bloom_intensity", "1"); -cvar_t r_bloom_darken = CVAR("r_bloom_darken", "3"); -cvar_t r_bloom_sample_size = CVARF("r_bloom_sample_size", "256", CVAR_RENDERERLATCH); -cvar_t r_bloom_fast_sample = CVARF("r_bloom_fast_sample", "0", CVAR_RENDERERLATCH); - -typedef struct { - //texture numbers - texid_t tx_screen; /*a copy of the screen*/ - texid_t tx_effect; /*blured copy of bright pixels*/ - texid_t tx_backup; /*a copy of the screen to replace the pixels that we'll clobber. FIXME: use a FBO instead*/ - texid_t tx_downsample; - - //the viewport dimensions - int vp_x; - int vp_y; - int vp_w; - int vp_h; - - //texture coordinates of screen data inside screentexture - float scr_s; - float scr_t; - - //dimensions of the screen texture (power of two) - int scr_w; - int scr_h; - - //downsampled dimensions (will always be smaller than viewport) - int smp_w; - int smp_h; - //tex coords to be used for the sample - float smp_s; - float smp_t; - - int size_downsample; - int size_backup; - int size_sample; -} bloomstate_t; - -static bloomstate_t bs; - -//this macro is in sample size workspace coordinates -#define R_Bloom_SamplePass( xpos, ypos ) \ - qglBegin(GL_QUADS); \ - qglTexCoord2f( 0, bs.smp_t); \ - qglVertex2f( xpos, ypos); \ - qglTexCoord2f( 0, 0); \ - qglVertex2f( xpos, ypos+bs.smp_h); \ - qglTexCoord2f( bs.smp_s, 0); \ - qglVertex2f( xpos+bs.smp_w, ypos+bs.smp_h); \ - qglTexCoord2f( bs.smp_s, bs.smp_t); \ - qglVertex2f( xpos+bs.smp_w, ypos); \ - qglEnd(); - -#define R_Bloom_Quad( x, y, width, height, textwidth, textheight ) \ - qglBegin(GL_QUADS); \ - qglTexCoord2f( 0, textheight); \ - qglVertex2f( x, y); \ - qglTexCoord2f( 0, 0); \ - qglVertex2f( x, y+height); \ - qglTexCoord2f( textwidth, 0); \ - qglVertex2f( x+width, y+height); \ - qglTexCoord2f( textwidth, textheight); \ - qglVertex2f( x+width, y); \ - qglEnd(); - - - -/* -================= -R_Bloom_InitBackUpTexture -================= -*/ -void R_Bloom_InitBackUpTexture(int widthheight) -{ - qbyte *data; - - data = Z_Malloc(widthheight * widthheight * 4); - - bs.size_backup = widthheight; - bs.tx_backup = GL_LoadTexture32("***bs.tx_backup***", bs.size_backup, bs.size_backup, (unsigned int*)data, IF_NOMIPMAP|IF_NOALPHA|IF_NOGAMMA); - - Z_Free (data); -} - -/* -================= -R_Bloom_InitEffectTexture -================= -*/ -void R_Bloom_InitEffectTexture(void) -{ - qbyte *data; - float bloomsizecheck; - - if (r_bloom_sample_size.value < 32) - Cvar_SetValue (&r_bloom_sample_size, 32); - - //make sure bloom size is a power of 2 - bs.size_sample = min(r_bloom_sample_size.value, gl_max_size.value); - bloomsizecheck = (float)bs.size_sample; - while (bloomsizecheck > 1.0f) bloomsizecheck /= 2.0f; - if (bloomsizecheck != 1.0f) - { - bs.size_sample = 32; - while (bs.size_sample < r_bloom_sample_size.value) - bs.size_sample *= 2; - } - - //make sure bloom size doesn't have stupid values - if (bs.size_sample > bs.scr_w || - bs.size_sample > bs.scr_h) - bs.size_sample = min(bs.scr_w, bs.scr_h); - - if (bs.size_sample != r_bloom_sample_size.value) - Cvar_SetValue (&r_bloom_sample_size, bs.size_sample); - - data = Z_Malloc(bs.size_sample * bs.size_sample * 4); - - bs.tx_effect = GL_LoadTexture32("***bs.tx_effect***", bs.size_sample, bs.size_sample, (unsigned int*)data, IF_NOMIPMAP|IF_NOALPHA|IF_NOGAMMA); - - Z_Free (data); -} - -/* -================= -R_Bloom_InitTextures -================= -*/ -void R_Bloom_InitTextures(void) -{ - qbyte *data; - int size; - int maxtexsize; - - //find closer power of 2 to screen size - for (bs.scr_w = 1;bs.scr_w < vid.pixelwidth;bs.scr_w *= 2); - for (bs.scr_h = 1;bs.scr_h < vid.pixelheight;bs.scr_h *= 2); - - //disable blooms if we can't handle a texture of that size - qglGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxtexsize); - if (bs.scr_w > maxtexsize || - bs.scr_h > maxtexsize) - { - bs.scr_w = bs.scr_h = 0; - Cvar_SetValue (&r_bloom, 0); - Con_Printf("WARNING: 'R_InitBloomScreenTexture' too high resolution for Light Bloom. Effect disabled\n"); - return; - } - - //init the screen texture - size = bs.scr_w * bs.scr_h * 4; - data = Z_Malloc(size); - memset(data, 255, size); - if (!TEXVALID(bs.tx_screen)) - bs.tx_screen = GL_AllocNewTexture("***bloom screen***", bs.scr_w, bs.scr_h); - GL_MTBind(0, GL_TEXTURE_2D, bs.tx_screen); - qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, bs.scr_w, bs.scr_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - Z_Free (data); - - - //validate bloom size and init the bloom effect texture - R_Bloom_InitEffectTexture (); - - //if screensize is more than 2x the bloom effect texture, set up for stepped downsampling - bs.tx_downsample = r_nulltex; - bs.size_downsample = 0; - if (vid.pixelwidth > (bs.size_sample * 2) && !r_bloom_fast_sample.value) - { - bs.size_downsample = (int)(bs.size_sample * 2); - data = Z_Malloc(bs.size_downsample * bs.size_downsample * 4); - bs.tx_downsample = GL_LoadTexture32("***bs.tx_downsample***", bs.size_downsample, bs.size_downsample, (unsigned int*)data, IF_NOMIPMAP|IF_NOALPHA|IF_NOGAMMA); - Z_Free (data); - } - - //Init the screen backup texture - if (bs.size_downsample) - R_Bloom_InitBackUpTexture(bs.size_downsample); - else - R_Bloom_InitBackUpTexture(bs.size_sample); -} - -void R_BloomRegister(void) -{ - Cvar_Register (&r_bloom, "bloom"); - Cvar_Register (&r_bloom_alpha, "bloom"); - Cvar_Register (&r_bloom_diamond_size, "bloom"); - Cvar_Register (&r_bloom_intensity, "bloom"); - Cvar_Register (&r_bloom_darken, "bloom"); - Cvar_Register (&r_bloom_sample_size, "bloom"); - Cvar_Register (&r_bloom_fast_sample, "bloom"); -} - -/* -================= -R_InitBloomTextures -================= -*/ -void R_InitBloomTextures(void) -{ - bs.size_sample = 0; - if (!r_bloom.ival) - return; - - bs.tx_screen = r_nulltex; //this came from a vid_restart, where none of the textures are valid any more. - R_Bloom_InitTextures (); -} - - -/* -================= -R_Bloom_DrawEffect -================= -*/ -void R_Bloom_DrawEffect(void) -{ - GL_MTBind(0, GL_TEXTURE_2D, bs.tx_effect); - qglEnable(GL_BLEND); - qglBlendFunc(GL_ONE, GL_ONE); - qglColor4f(r_bloom_alpha.value, r_bloom_alpha.value, r_bloom_alpha.value, 1.0f); - GL_TexEnv(GL_MODULATE); - qglBegin(GL_QUADS); - qglTexCoord2f (0, bs.smp_t); - qglVertex2f (bs.vp_x, bs.vp_y); - qglTexCoord2f (0, 0); - qglVertex2f (bs.vp_x, bs.vp_y + bs.vp_h); - qglTexCoord2f (bs.smp_s, 0); - qglVertex2f (bs.vp_x + bs.vp_w, bs.vp_y + bs.vp_h); - qglTexCoord2f (bs.smp_s, bs.smp_t); - qglVertex2f (bs.vp_x + bs.vp_w, bs.vp_y); - qglEnd(); - - qglDisable(GL_BLEND); -} - - -#if 0 -/* -================= -R_Bloom_GeneratexCross - alternative bluring method -================= -*/ -void R_Bloom_GeneratexCross(void) -{ - int i; - static int BLOOM_BLUR_RADIUS = 8; - //static float BLOOM_BLUR_INTENSITY = 2.5f; - float BLOOM_BLUR_INTENSITY; - static float intensity; - static float range; - - //set up sample size workspace - qglViewport( 0, 0, bs.smp_w, bs.smp_h ); - qglMatrixMode( GL_PROJECTION ); - qglLoadIdentity (); - qglOrtho(0, bs.smp_w, bs.smp_h, 0, -10, 100); - qglMatrixMode( GL_MODELVIEW ); - qglLoadIdentity (); - - //copy small scene into bs.tx_effect - GL_Bind(0, bs.tx_effect); - qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h); - - //start modifying the small scene corner - qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); - qglEnable(GL_BLEND); - - //darkening passes - if( r_bloom_darken.value ) - { - qglBlendFunc(GL_DST_COLOR, GL_ZERO); - GL_TexEnv(GL_MODULATE); - - for(i=0; iinteger ;i++) { - R_Bloom_SamplePass( 0, 0 ); - } - qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h); - } - - //bluring passes - if( BLOOM_BLUR_RADIUS ) { - - qglBlendFunc(GL_ONE, GL_ONE); - - range = (float)BLOOM_BLUR_RADIUS; - - BLOOM_BLUR_INTENSITY = r_bloom_intensity.value; - //diagonal-cross draw 4 passes to add initial smooth - qglColor4f( 0.5f, 0.5f, 0.5f, 1.0); - R_Bloom_SamplePass( 1, 1 ); - R_Bloom_SamplePass( -1, 1 ); - R_Bloom_SamplePass( -1, -1 ); - R_Bloom_SamplePass( 1, -1 ); - qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h); - - for(i=-(BLOOM_BLUR_RADIUS+1);i bs.vp_w) - { - bs.smp_s = (float)bs.vp_w / (float)bs.vp_h; - bs.smp_t = 1.0f; - } - else - { - bs.smp_s = 1.0f; - bs.smp_t = (float)bs.vp_h / (float)bs.vp_w; - } - bs.smp_w = bs.size_sample * bs.smp_s; - bs.smp_h = bs.size_sample * bs.smp_t; - - bs.smp_s = (float)bs.smp_w/bs.size_sample; - bs.smp_t = (float)bs.smp_h/bs.size_sample; - - buw = bs.size_backup * bs.smp_s; - buh = bs.size_backup * bs.smp_t; - - //copy the screen space we'll use to work into the backup texture - GL_MTBind(0, GL_TEXTURE_2D, bs.tx_backup); - qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, buw, buh); - - //create the bloom image - R_Bloom_DownsampleView(); - - R_Bloom_GeneratexDiamonds(); - //R_Bloom_GeneratexCross(); - - //restore the screen-backup to the screen - qglDisable(GL_BLEND); - GL_MTBind(0, GL_TEXTURE_2D, bs.tx_backup); - qglColor4f(1, 1, 1, 1); - R_Bloom_Quad(0, - vid.pixelheight - (buh), - buw, - buh, - bs.smp_s, - bs.smp_t); - - R_Bloom_DrawEffect(); - - - qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - checkglerror(); - - PPL_RevertToKnownState(); -} - #endif diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 9c35f3de9..bc9eb056b 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -98,6 +98,7 @@ texid_t scenepp_postproc_cube; int scenepp_postproc_cube_size; fbostate_t fbo_gameview; +fbostate_t fbo_postproc; // KrimZon - init post processing - called in GL_CheckExtensions, when they're called // I put it here so that only this file need be changed when messing with the post @@ -111,7 +112,7 @@ void GL_InitSceneProcessingShaders_WaterWarp (void) "{\n" "program underwaterwarp\n" "{\n" - "map $currentrender\n" + "map $sourcecolour\n" "}\n" "{\n" "map $upperoverlay\n" @@ -129,6 +130,7 @@ void GL_InitSceneProcessingShaders_WaterWarp (void) void GL_ShutdownPostProcessing(void) { GLBE_FBO_Destroy(&fbo_gameview); + GLBE_FBO_Destroy(&fbo_postproc); R_BloomShutdown(); } @@ -388,7 +390,16 @@ void R_SetupGL (float stereooffset) // // set up viewpoint // - if (*r_refdef.rt_destcolour[0].texname) + if (r_refdef.flags & (RDF_ALLPOSTPROC)) + { + //with fbo postprocessing, we disable all viewport. + r_refdef.pxrect.x = 0; + r_refdef.pxrect.y = 0; + r_refdef.pxrect.width = vid.fbpwidth; + r_refdef.pxrect.height = vid.fbpheight; + r_refdef.pxrect.maxheight = vid.fbpheight; + } + else if (*r_refdef.rt_destcolour[0].texname) { //with fbo rendering, we disable all virtual scaling. x = r_refdef.vrect.x; @@ -407,18 +418,18 @@ void R_SetupGL (float stereooffset) } else { - x = r_refdef.vrect.x * (int)vid.pixelwidth/(int)vid.width; - x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * (int)vid.pixelwidth/(int)vid.width; - y = (r_refdef.vrect.y) * (int)vid.pixelheight/(int)vid.height; - y2 = (r_refdef.vrect.y + r_refdef.vrect.height) * (int)vid.pixelheight/(int)vid.height; + x = r_refdef.vrect.x * (int)vid.fbpwidth/(int)vid.width; + x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * (int)vid.fbpwidth/(int)vid.width; + y = (r_refdef.vrect.y) * (int)vid.fbpheight/(int)vid.height; + y2 = (r_refdef.vrect.y + r_refdef.vrect.height) * (int)vid.fbpheight/(int)vid.height; // fudge around because of frac screen scale if (x > 0) x--; - if (x2 < vid.pixelwidth) + if (x2 < vid.fbpwidth) x2++; - if (y2 < vid.pixelheight) + if (y2 < vid.fbpheight) y2++; if (y > 0) y--; @@ -430,21 +441,21 @@ void R_SetupGL (float stereooffset) { w /= 2; if (stereooffset > 0) - x += vid.pixelwidth/2; + x += vid.fbpwidth/2; } r_refdef.pxrect.x = x; r_refdef.pxrect.y = y; r_refdef.pxrect.width = w; r_refdef.pxrect.height = h; - r_refdef.pxrect.maxheight = vid.pixelheight; + r_refdef.pxrect.maxheight = vid.fbpheight; } fov_x = r_refdef.fov_x;//+sin(cl.time)*5; fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5; GL_ViewportUpdate(); - if ((r_waterwarp.value<0 || (r_waterwarp.value && !R_GameRectIsFullscreen())) && (r_viewcontents & FTECONTENTS_FLUID)) + if ((r_refdef.flags & RDF_UNDERWATER) && !(r_refdef.flags & RDF_WATERWARP)) { fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value); fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value); @@ -510,6 +521,7 @@ void R_SetupGL (float stereooffset) } void Surf_SetupFrame(void); + /* ================ R_RenderScene @@ -524,8 +536,6 @@ void R_RenderScene (void) int stereomode; int i; int tmpvisents = cl_numvisedicts; /*world rendering is allowed to add additional ents, but we don't want to keep them for recursive views*/ - if (!cl.worldmodel || (!cl.worldmodel->nodes && cl.worldmodel->type != mod_heightmap)) - r_refdef.flags |= RDF_NOWORLDMODEL; stereomode = r_stereo_method.ival; if (stereomode == 1) @@ -569,7 +579,7 @@ void R_RenderScene (void) qglDrawBuffer(GL_BACK_RIGHT); break; #endif - case 2: //red/cyan + case 2: //red/cyan(green+blue) if (stereooffset[i] < 0) qglColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE); else @@ -593,8 +603,6 @@ void R_RenderScene (void) if (i) qglClear (GL_DEPTH_BUFFER_BIT); - Surf_SetupFrame(); - TRACE(("dbg: calling R_SetupGL\n")); R_SetupGL (stereooffset[i]); @@ -1320,6 +1328,7 @@ static void R_RenderMotionBlur(void) #endif } +#if 0 /*FIXME: we could use geometry shaders to draw to all 6 faces at once*/ qboolean R_RenderScene_Cubemap(void) { @@ -1490,6 +1499,34 @@ qboolean R_RenderScene_Cubemap(void) */ return true; } +#endif + +texid_t R_RenderPostProcess (texid_t sourcetex, int type, shader_t *shader, char *restexname) +{ + if (r_refdef.flags & type) + { + r_refdef.flags &= ~type; + GLBE_FBO_Sources(sourcetex, r_nulltex); + + if (r_refdef.flags & RDF_ALLPOSTPROC) + { //there's other post-processing passes that still need to be applied. + //thus we need to write this output to a texture. + int w = (r_refdef.vrect.width * vid.pixelwidth) / vid.width; + int h = (r_refdef.vrect.height * vid.pixelheight) / vid.height; + sourcetex = R2D_RT_Configure(restexname, w, h, TF_RGBA32); + GLBE_FBO_Update(&fbo_postproc, 0, &sourcetex, 1, r_nulltex, w, h); + R2D_ScalePic(0, vid.pixelheight-r_refdef.vrect.height, r_refdef.vrect.width, r_refdef.vrect.height, scenepp_waterwarp); + GLBE_RenderToTextureUpdate2d(true); + } + else + { //yay, dump it to the screen + //update stuff now that we're not rendering the 3d scene + R2D_ScalePic(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, scenepp_waterwarp); + } + } + + return sourcetex; +} /* ================ @@ -1502,12 +1539,16 @@ void GLR_RenderView (void) { int dofbo = *r_refdef.rt_destcolour[0].texname || *r_refdef.rt_depth.texname; double time1 = 0, time2; + texid_t sourcetex = r_nulltex; + shader_t *custompostproc = NULL; checkglerror(); if (r_norefresh.value || !vid.pixelwidth || !vid.pixelheight) return; + //when loading/bugged, its possible that the world is still loading. + //in this case, don't act as a wallhack (unless the world is meant to be hidden anyway) if (!(r_refdef.flags & RDF_NOWORLDMODEL)) { //FIXME: fbo stuff @@ -1522,6 +1563,43 @@ void GLR_RenderView (void) // Sys_Error ("R_RenderView: NULL worldmodel"); } + //check if we're underwater (this also limits damage from stereo wallhacks). + Surf_SetupFrame(); + r_refdef.flags &= ~RDF_ALLPOSTPROC; + + //if bloom is + if (R_CanBloom()) + r_refdef.flags |= RDF_BLOOM; + + //check if we can do underwater warp + if (cls.protocol != CP_QUAKE2) //quake2 tells us directly + { + if (r_viewcontents & FTECONTENTS_FLUID) + r_refdef.flags |= RDF_UNDERWATER; + else + r_refdef.flags &= ~RDF_UNDERWATER; + } + if (r_refdef.flags & RDF_UNDERWATER) + { + if (!r_waterwarp.value) + r_refdef.flags &= ~RDF_UNDERWATER; //no warp at all + else if (r_waterwarp.value > 0 && scenepp_waterwarp) + r_refdef.flags |= RDF_WATERWARP; //try fullscreen warp instead if we can + } + + // + if (*r_postprocshader.string) + { + custompostproc = R_RegisterCustom(r_postprocshader.string, SUF_NONE, NULL, NULL); + if (custompostproc) + r_refdef.flags |= RDF_CUSTOMPOSTPROC; + } + + //disable stuff if its simply not supported. + if (dofbo || !gl_config.arb_shader_objects || !gl_config.ext_framebuffer_objects || !r_config.texture_non_power_of_two) + r_refdef.flags &= ~(RDF_ALLPOSTPROC); //block all of this stuff + + BE_Scissor(NULL); if (dofbo) { @@ -1569,7 +1647,18 @@ void GLR_RenderView (void) flags |= FBO_RB_DEPTH; GLBE_FBO_Update(&fbo_gameview, flags, col, mrt, depth, vid.fbpwidth, vid.fbpheight); } - else + else if (r_refdef.flags & (RDF_ALLPOSTPROC)) + { + //the game needs to be drawn to a texture for post processing + vid.fbvwidth = vid.fbpwidth = (r_refdef.vrect.width * vid.pixelwidth) / vid.width; + vid.fbvheight = vid.fbpheight = (r_refdef.vrect.height * vid.pixelheight) / vid.height; + + sourcetex = R2D_RT_Configure("rt/$lastgameview", vid.fbpwidth, vid.fbpheight, TF_RGBA32); + + GLBE_FBO_Update(&fbo_gameview, FBO_RB_DEPTH, &sourcetex, 1, r_nulltex, vid.fbpwidth, vid.fbpheight); + dofbo = true; + } + else { vid.fbvwidth = vid.width; vid.fbvheight = vid.height; @@ -1604,11 +1693,11 @@ void GLR_RenderView (void) time1 = Sys_DoubleTime (); } - if (!dofbo && !(r_refdef.flags & RDF_NOWORLDMODEL) && R_RenderScene_Cubemap()) - { - - } - else +// if (!dofbo && !(r_refdef.flags & RDF_NOWORLDMODEL) && R_RenderScene_Cubemap()) +// { +// +// } +// else { GL_SetShaderState2D(false); @@ -1643,40 +1732,17 @@ void GLR_RenderView (void) GL_Set2D (false); } - //FIXME: support bloom+waterwarp even when drawing to an fbo? - //FIXME: force waterwarp to a temp fbo always - if ((r_refdef.flags & RDF_NOWORLDMODEL) || dofbo) - return; - - if (!R_GameRectIsFullscreen()) - return; - - if (r_bloom.value) - R_BloomBlend(); - // SCENE POST PROCESSING - // we check if we need to use any shaders - currently it's just waterwarp - if ((r_waterwarp.value>0 && (r_viewcontents & FTECONTENTS_WATER))) - { - if (scenepp_waterwarp) - { - R2D_ScalePic(0, 0, vid.width, vid.height, scenepp_waterwarp); - } - } + sourcetex = R_RenderPostProcess (sourcetex, RDF_WATERWARP, scenepp_waterwarp, "rt/$waterwarped"); + sourcetex = R_RenderPostProcess (sourcetex, RDF_CUSTOMPOSTPROC, custompostproc, "rt/$postproced"); + if (r_refdef.flags & RDF_BLOOM) + R_BloomBlend(sourcetex, r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height); + GLBE_FBO_Sources(r_nulltex, r_nulltex); - if (gl_motionblur.value>0 && gl_motionblur.value < 1 && qglCopyTexImage2D) - R_RenderMotionBlur(); - - if (*r_postprocshader.string) - { - shader_t *postproc = R_RegisterCustom(r_postprocshader.string, SUF_NONE, NULL, NULL); - if (postproc) - { - R2D_ScalePic(0, 0, vid.width, vid.height, postproc); - } - } +// if (gl_motionblur.value>0 && gl_motionblur.value < 1 && qglCopyTexImage2D) +// R_RenderMotionBlur(); checkglerror(); } diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index e3774fa92..45ea632e9 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -423,7 +423,8 @@ void D3_GenerateAreas(model_t *mod); //gl_bloom.c #ifdef GLQUAKE void R_BloomRegister(void); -void R_BloomBlend(void); +qboolean R_CanBloom(void); +void R_BloomBlend (texid_t source, int x, int y, int w, int h); void R_BloomShutdown(void); #endif diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index bfaf36ee1..114e40bcc 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -2291,7 +2291,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "void main ()\n" "{\n" "gl_Position = ftetransform();\n" -"v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0;\n" +"v_stc = vec2(v_texcoord.x, 1.0-v_texcoord.y);\n" "v_warp.s = e_time * 0.25 + v_texcoord.s;\n" "v_warp.t = e_time * 0.25 + v_texcoord.t;\n" "v_edge = v_texcoord.xy;\n" diff --git a/engine/shaders/glsl/underwaterwarp.glsl b/engine/shaders/glsl/underwaterwarp.glsl index 266443c75..47c9501bd 100644 --- a/engine/shaders/glsl/underwaterwarp.glsl +++ b/engine/shaders/glsl/underwaterwarp.glsl @@ -12,7 +12,7 @@ uniform float e_time; void main () { gl_Position = ftetransform(); - v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0; + v_stc = vec2(v_texcoord.x, 1.0-v_texcoord.y); v_warp.s = e_time * 0.25 + v_texcoord.s; v_warp.t = e_time * 0.25 + v_texcoord.t; v_edge = v_texcoord.xy;