diff --git a/engine/gl/gl_bloom.c b/engine/gl/gl_bloom.c index 879f8588e..bfa0431a6 100644 --- a/engine/gl/gl_bloom.c +++ b/engine/gl/gl_bloom.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// r_bloom.c: 2D lighting post process effect +// gl_bloom.c: 2D lighting post process effect //http://www.quakesrc.org/forums/viewtopic.php?t=4340&start=0 @@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef RGLQUAKE #include "glquake.h" -extern vrect_t scr_vrect; +extern vrect_t gl_truescreenrect; /* ============================================================================== @@ -61,54 +61,60 @@ static float Diamond4x[4][4] = { {0.4f, 0.9f, 0.9f, 0.4f}, {0.3f, 0.4f, 0.4f, 0.3f} }; + cvar_t r_bloom = FCVAR("r_bloom", "gl_bloom", "0", CVAR_ARCHIVE); +static cvar_t r_bloom_alpha = SCVAR("r_bloom_alpha", "0.5"); +static cvar_t r_bloom_diamond_size = SCVAR("r_bloom_diamond_size", "8"); +static cvar_t r_bloom_intensity = SCVAR("r_bloom_intensity", "1"); +static cvar_t r_bloom_darken = SCVAR("r_bloom_darken", "3"); +static cvar_t r_bloom_sample_size = SCVARF("r_bloom_sample_size", "256", CVAR_RENDERERLATCH); +static cvar_t r_bloom_fast_sample = SCVARF("r_bloom_fast_sample", "0", CVAR_RENDERERLATCH); -static int BLOOM_SIZE; +typedef struct { + //texture numbers + int tx_screen; + int tx_effect; + int tx_backup; + int tx_downsample; -cvar_t r_bloom = FCVAR("r_bloom", "gl_bloom", "0", CVAR_ARCHIVE); -cvar_t r_bloom_alpha = SCVAR("r_bloom_alpha", "0.5"); -cvar_t r_bloom_diamond_size = SCVAR("r_bloom_diamond_size", "8"); -cvar_t r_bloom_intensity = SCVAR("r_bloom_intensity", "1"); -cvar_t r_bloom_darken = SCVAR("r_bloom_darken", "3"); -cvar_t r_bloom_sample_size = SCVARF("r_bloom_sample_size", "256", CVAR_RENDERERLATCH); -cvar_t r_bloom_fast_sample = SCVARF("r_bloom_fast_sample", "0", CVAR_RENDERERLATCH); + //the viewport dimensions + int vp_x; + int vp_y; + int vp_w; + int vp_h; -int r_bloomscreentexture; -int r_bloomeffecttexture; -int r_bloombackuptexture; -int r_bloomdownsamplingtexture; + //texture coordinates of screen data inside screentexture + float scr_s; + float scr_t; -static int r_screendownsamplingtexture_size; -static int screen_texture_width, screen_texture_height; -static int r_screenbackuptexture_size; + //dimensions of the screen texture (power of two) + int scr_w; + int scr_h; -//current refdef size: -static int curView_x; -static int curView_y; -static int curView_width; -static int curView_height; + //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; -//texture coordinates of screen data inside screentexture -static float screenText_tcw; -static float screenText_tch; + int size_downsample; + int size_backup; + int size_sample; +} bloomstate_t; -static int sample_width; -static int sample_height; - -//texture coordinates of adjusted textures -static float sampleText_tcw; -static float sampleText_tch; +static bloomstate_t bs; //this macro is in sample size workspace coordinates -#define R_Bloom_SamplePass( xpos, ypos ) \ - qglBegin(GL_QUADS); \ - qglTexCoord2f( 0, sampleText_tch); \ - qglVertex2f( xpos, ypos); \ - qglTexCoord2f( 0, 0); \ - qglVertex2f( xpos, ypos+sample_height); \ - qglTexCoord2f( sampleText_tcw, 0); \ - qglVertex2f( xpos+sample_width, ypos+sample_height); \ - qglTexCoord2f( sampleText_tcw, sampleText_tch); \ - qglVertex2f( xpos+sample_width, ypos); \ +#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 ) \ @@ -130,17 +136,16 @@ static float sampleText_tch; R_Bloom_InitBackUpTexture ================= */ -void R_Bloom_InitBackUpTexture( int width, int height ) +void R_Bloom_InitBackUpTexture(int widthheight) { qbyte *data; - data = Z_Malloc( width * height * 4 ); + data = Z_Malloc(widthheight * widthheight * 4); - r_screenbackuptexture_size = width; - - r_bloombackuptexture = GL_LoadTexture32("***r_bloombackuptexture***", width, height, (unsigned int*)data, false, false ); + bs.size_backup = widthheight; + bs.tx_backup = GL_LoadTexture32("***bs.tx_backup***", bs.size_backup, bs.size_backup, (unsigned int*)data, false, false); - Z_Free ( data ); + Z_Free (data); } /* @@ -148,38 +153,38 @@ void R_Bloom_InitBackUpTexture( int width, int height ) R_Bloom_InitEffectTexture ================= */ -void R_Bloom_InitEffectTexture( void ) +void R_Bloom_InitEffectTexture(void) { qbyte *data; float bloomsizecheck; - if( r_bloom_sample_size.value < 32 ) + if (r_bloom_sample_size.value < 32) Cvar_SetValue (&r_bloom_sample_size, 32); //make sure bloom size is a power of 2 - BLOOM_SIZE = r_bloom_sample_size.value; - bloomsizecheck = (float)BLOOM_SIZE; - while(bloomsizecheck > 1.0f) bloomsizecheck /= 2.0f; - if( bloomsizecheck != 1.0f ) + bs.size_sample = r_bloom_sample_size.value; + bloomsizecheck = (float)bs.size_sample; + while (bloomsizecheck > 1.0f) bloomsizecheck /= 2.0f; + if (bloomsizecheck != 1.0f) { - BLOOM_SIZE = 32; - while( BLOOM_SIZE < r_bloom_sample_size.value ) - BLOOM_SIZE *= 2; + 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( BLOOM_SIZE > screen_texture_width || - BLOOM_SIZE > screen_texture_height ) - BLOOM_SIZE = min( screen_texture_width, screen_texture_height ); + if (bs.size_sample > bs.scr_w || + bs.size_sample > bs.scr_h) + bs.size_sample = min(bs.scr_w, bs.scr_h); - if( BLOOM_SIZE != r_bloom_sample_size.value ) - Cvar_SetValue (&r_bloom_sample_size, BLOOM_SIZE); + if (bs.size_sample != r_bloom_sample_size.value) + Cvar_SetValue (&r_bloom_sample_size, bs.size_sample); - data = Z_Malloc( BLOOM_SIZE * BLOOM_SIZE * 4 ); + data = Z_Malloc(bs.size_sample * bs.size_sample * 4); - r_bloomeffecttexture = GL_LoadTexture32("***r_bloomeffecttexture***", BLOOM_SIZE, BLOOM_SIZE, (unsigned int*)data, false, false ); + bs.tx_effect = GL_LoadTexture32("***bs.tx_effect***", bs.size_sample, bs.size_sample, (unsigned int*)data, false, false); - Z_Free ( data ); + Z_Free (data); } /* @@ -187,58 +192,59 @@ void R_Bloom_InitEffectTexture( void ) R_Bloom_InitTextures ================= */ -void R_Bloom_InitTextures( void ) +void R_Bloom_InitTextures(void) { qbyte *data; int size; int maxtexsize; //find closer power of 2 to screen size - for (screen_texture_width = 1;screen_texture_width < glwidth;screen_texture_width *= 2); - for (screen_texture_height = 1;screen_texture_height < glheight;screen_texture_height *= 2); + for (bs.scr_w = 1;bs.scr_w < glwidth;bs.scr_w *= 2); + for (bs.scr_h = 1;bs.scr_h < glheight;bs.scr_h *= 2); //disable blooms if we can't handle a texture of that size qglGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxtexsize); - if( screen_texture_width > maxtexsize || - screen_texture_height > maxtexsize ) { - screen_texture_width = screen_texture_height = 0; + 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" ); + Con_Printf("WARNING: 'R_InitBloomScreenTexture' too high resolution for Light Bloom. Effect disabled\n"); return; } //init the screen texture - size = screen_texture_width * screen_texture_height * 4; - data = Z_Malloc( size ); - memset( data, 255, size ); - if (!r_bloomscreentexture) - r_bloomscreentexture = texture_extension_number++; - GL_Bind(r_bloomscreentexture); - qglTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, screen_texture_width, screen_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + size = bs.scr_w * bs.scr_h * 4; + data = Z_Malloc(size); + memset(data, 255, size); + if (!bs.tx_screen) + bs.tx_screen = texture_extension_number++; + GL_Bind(bs.tx_screen); + qglTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, bs.scr_w, bs.scr_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - Z_Free ( data ); + 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 - r_bloomdownsamplingtexture = 0; - r_screendownsamplingtexture_size = 0; - if( glwidth > (BLOOM_SIZE * 2) && !r_bloom_fast_sample.value ) + bs.tx_downsample = 0; + bs.size_downsample = 0; + if (glwidth > (bs.size_sample * 2) && !r_bloom_fast_sample.value) { - r_screendownsamplingtexture_size = (int)(BLOOM_SIZE * 2); - data = Z_Malloc( r_screendownsamplingtexture_size * r_screendownsamplingtexture_size * 4 ); - r_bloomdownsamplingtexture = GL_LoadTexture32("***r_bloomdownsamplingtexture***", r_screendownsamplingtexture_size, r_screendownsamplingtexture_size, (unsigned int*)data, false, false ); - Z_Free ( data ); + 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, false, false); + Z_Free (data); } //Init the screen backup texture - if( r_screendownsamplingtexture_size ) - R_Bloom_InitBackUpTexture( r_screendownsamplingtexture_size, r_screendownsamplingtexture_size ); + if (bs.size_downsample) + R_Bloom_InitBackUpTexture(bs.size_downsample); else - R_Bloom_InitBackUpTexture( BLOOM_SIZE, BLOOM_SIZE ); + R_Bloom_InitBackUpTexture(bs.size_sample); } void R_BloomRegister(void) @@ -257,13 +263,13 @@ void R_BloomRegister(void) R_InitBloomTextures ================= */ -void R_InitBloomTextures( void ) +void R_InitBloomTextures(void) { - BLOOM_SIZE = 0; - if( !r_bloom.value ) + bs.size_sample = 0; + if (!r_bloom.value) return; - r_bloomscreentexture = 0; //this came from a vid_restart, where none of the textures are valid any more. + bs.tx_screen = 0; //this came from a vid_restart, where none of the textures are valid any more. R_Bloom_InitTextures (); } @@ -273,22 +279,22 @@ void R_InitBloomTextures( void ) R_Bloom_DrawEffect ================= */ -void R_Bloom_DrawEffect( void ) +void R_Bloom_DrawEffect(void) { - GL_Bind(r_bloomeffecttexture); + GL_Bind(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, sampleText_tch ); - qglVertex2f( curView_x, curView_y ); - qglTexCoord2f( 0, 0 ); - qglVertex2f( curView_x, curView_y + curView_height ); - qglTexCoord2f( sampleText_tcw, 0 ); - qglVertex2f( curView_x + curView_width, curView_y + curView_height ); - qglTexCoord2f( sampleText_tcw, sampleText_tch ); - qglVertex2f( curView_x + curView_width, curView_y ); + 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); @@ -301,7 +307,7 @@ void R_Bloom_DrawEffect( void ) R_Bloom_GeneratexCross - alternative bluring method ================= */ -void R_Bloom_GeneratexCross( void ) +void R_Bloom_GeneratexCross(void) { int i; static int BLOOM_BLUR_RADIUS = 8; @@ -311,16 +317,16 @@ void R_Bloom_GeneratexCross( void ) static float range; //set up sample size workspace - qglViewport( 0, 0, sample_width, sample_height ); + qglViewport( 0, 0, bs.smp_w, bs.smp_h ); qglMatrixMode( GL_PROJECTION ); qglLoadIdentity (); - qglOrtho(0, sample_width, sample_height, 0, -10, 100); + qglOrtho(0, bs.smp_w, bs.smp_h, 0, -10, 100); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity (); - //copy small scene into r_bloomeffecttexture - GL_Bind(0, r_bloomeffecttexture); - qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); + //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 ); @@ -335,7 +341,7 @@ void R_Bloom_GeneratexCross( void ) for(i=0; iinteger ;i++) { R_Bloom_SamplePass( 0, 0 ); } - qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); + qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h); } //bluring passes @@ -352,7 +358,7 @@ void R_Bloom_GeneratexCross( void ) R_Bloom_SamplePass( -1, 1 ); R_Bloom_SamplePass( -1, -1 ); R_Bloom_SamplePass( 1, -1 ); - qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); + qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h); for(i=-(BLOOM_BLUR_RADIUS+1);i 7 || r_bloom_diamond_size.value <= 3) + if (r_bloom_diamond_size.value > 7 || r_bloom_diamond_size.value <= 3) { - if( r_bloom_diamond_size.value != 8 ) Cvar_SetValue( &r_bloom_diamond_size, 8 ); + if (r_bloom_diamond_size.value != 8) + Cvar_SetValue(&r_bloom_diamond_size, 8); - for(i=0; i 5 ) { - - if( r_bloom_diamond_size.value != 6 ) Cvar_SetValue(&r_bloom_diamond_size, 6 ); + } + else if (r_bloom_diamond_size.value > 5) + { + if (r_bloom_diamond_size.value != 6) + Cvar_SetValue(&r_bloom_diamond_size, 6); - for(i=0; i 3 ) { + } + else if (r_bloom_diamond_size.value > 3) + { + if (r_bloom_diamond_size.value != 4) + Cvar_SetValue(&r_bloom_diamond_size, 4); - if( r_bloom_diamond_size.value != 4 ) Cvar_SetValue(&r_bloom_diamond_size, 4 ); - - for(i=0; i scr_vrect.width ) { - sampleText_tcw = ((float)(scr_vrect.width+0.5) / (float)scr_vrect.height); - sampleText_tch = 1.0f; - } else { - sampleText_tcw = 1.0f; - sampleText_tch = ((float)(scr_vrect.height+0.5) / (float)scr_vrect.width); + bs.vp_x = gl_truescreenrect.x; + bs.vp_y = glheight - gl_truescreenrect.y; + bs.vp_w = gl_truescreenrect.width; + bs.vp_h = gl_truescreenrect.height; + bs.scr_s = (float)bs.vp_w / (float)bs.scr_w; + bs.scr_t = (float)bs.vp_h / (float)bs.scr_h; + if (bs.vp_h > bs.vp_w) + { + bs.smp_s = (float)bs.vp_w / (float)bs.vp_h; + bs.smp_t = 1.0f; } - sample_width = BLOOM_SIZE * sampleText_tcw; - sample_height = BLOOM_SIZE * sampleText_tch; + 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; - if (qglGetError()) - Con_Printf("GL Error whilst rendering bloom\n"); + bs.smp_s = (float)bs.smp_w/bs.size_sample; + bs.smp_t = (float)bs.smp_h/bs.size_sample; + + buw = bs.size_downsample * bs.smp_s; + buh = bs.size_downsample * bs.smp_t; //copy the screen space we'll use to work into the backup texture - GL_Bind(r_bloombackuptexture); - qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, r_screenbackuptexture_size * sampleText_tcw, r_screenbackuptexture_size * sampleText_tch); - if (qglGetError()) - Con_Printf("GL Error whilst rendering bloom\n"); + GL_Bind(bs.tx_backup); + qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, buw, buh); + //create the bloom image R_Bloom_DownsampleView(); - if (qglGetError()) - Con_Printf("GL Error whilst rendering bloom\n"); + R_Bloom_GeneratexDiamonds(); //R_Bloom_GeneratexCross(); - if (qglGetError()) - Con_Printf("GL Error whilst rendering bloom\n"); - //restore the screen-backup to the screen qglDisable(GL_BLEND); - GL_Bind(r_bloombackuptexture); - qglColor4f( 1, 1, 1, 1 ); - R_Bloom_Quad( 0, - glheight - (r_screenbackuptexture_size * sampleText_tch), - r_screenbackuptexture_size * sampleText_tcw, - r_screenbackuptexture_size * sampleText_tch, - sampleText_tcw, - sampleText_tch ); + GL_Bind(bs.tx_backup); + qglColor4f(1, 1, 1, 1); + R_Bloom_Quad(0, + glheight - (buh), + buw, + buh, + bs.smp_s, + bs.smp_t); R_Bloom_DrawEffect(); diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index cecdeeee4..909281ef8 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -36,6 +36,8 @@ void R_RenderBrushPoly (msurface_t *fa); extern int gl_canstencil; +vrect_t gl_truescreenrect; + FTEPFNGLCOMPRESSEDTEXIMAGE2DARBPROC qglCompressedTexImage2DARB; FTEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC qglGetCompressedTexImageARB; @@ -737,6 +739,13 @@ void GLR_DrawEntitiesOnList (void) } } + if (currententity->model->engineflags & MDLF_NOTREPLACEMENTS) + { + if (currententity->model->fromgame != fg_quake || currententity->model->type != mod_halflife) + if (!ruleset_allow_sensative_texture_replacements.value) + continue; + } + switch (currententity->model->type) { case mod_alias: @@ -1008,6 +1017,11 @@ void R_SetupGL (void) w = h = 256; } + gl_truescreenrect.x = x; + gl_truescreenrect.y = y; + gl_truescreenrect.width = w; + gl_truescreenrect.height = h; + qglViewport (glx + x, gly + y2, w, h); qglMatrixMode(GL_PROJECTION);