/* ================= R_Bloom_RestoreScreen_Postprocessed Restore the temporary framebuffer section we used with the backup texture ================= */ static void R_Bloom_RestoreScreen_Postprocessed( void ) { glslProgram_t *program; if (vertexShaders) R_GLSL_UseProgram(tr.postprocessingProgram); // Feed GLSL postprocess program program=tr.programs[tr.postprocessingProgram]; if (program->u_ScreenSizeX > -1) R_GLSL_SetUniform_u_ScreenSizeX(program, glConfig.vidWidth); if (program->u_ScreenSizeY > -1) R_GLSL_SetUniform_u_ScreenSizeY(program, glConfig.vidHeight); if (program->u_ScreenToNextPixelX > -1) R_GLSL_SetUniform_u_ScreenToNextPixelX(program, 0.00125); if (program->u_ScreenToNextPixelY > -1) R_GLSL_SetUniform_u_ScreenToNextPixelY(program, (float)1.0/(float)glConfig.vidHeight); if (program->u_zFar > -1) R_GLSL_SetUniform_u_zFar(program, tr.viewParms.zFar); GL_SelectTexture(0); GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); GL_Bind( postproc.screen.texture ); GL_SelectTexture(7); GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); GL_Bind( postproc.depth.texture ); qglColor4f( 1, 1, 1, 1 ); R_Bloom_Quad( glConfig.vidWidth, glConfig.vidHeight, 0, 0, postproc.screen.readW,postproc.screen.readH ); if (vertexShaders) R_GLSL_UseProgram(0); GL_SelectTexture(0); }
/* ================= R_Bloom_RestoreScreen Restore the temporary framebuffer section we used with the backup texture ================= */ static void R_Bloom_RestoreScreen( void ) { float dry=r_bloom_dry->value; if(r_bloom_cascade->integer) dry=r_bloom_cascade_dry->value; GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); GL_Bind( bloom.screen.texture ); qglColor4f( dry,dry,dry, 1 ); if(dry<.99f){ R_Bloom_Quad( bloom.screen.width, bloom.screen.height, 0, 0, 1.f, 1.f ); }else{ R_Bloom_Quad( bloom.work.width, bloom.work.height, 0, 0, bloom.work.width / (float)bloom.screen.width, bloom.work.height / (float)bloom.screen.height ); } }
/* ================= R_Bloom_DrawEffect ================= */ static void R_Bloom_DrawEffect( void ) { float alpha=r_bloom_alpha->value; GL_Bind( bloom.effect.texture ); GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); if(r_bloom_cascade->integer){ alpha=r_bloom_cascade_alpha->value; } qglColor4f( alpha,alpha,alpha, 1.0f ); R_Bloom_Quad( glConfig.vidWidth, glConfig.vidHeight, 0, 0, bloom.effect.readW, bloom.effect.readW ); }
// ================= // R_Bloom_DownsampleView // ================= void R_Bloom_DownsampleView( void ) { glDisable( GL_BLEND ); glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); // Stepped downsample. if( r_screendownsamplingtexture_size ) { int midsample_width = r_screendownsamplingtexture_size * sampleText_tcw; int midsample_height = r_screendownsamplingtexture_size * sampleText_tch; // Copy the screen and draw resized. GL_Bind(r_bloomscreentexture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, curView_x, glheight - (curView_y + curView_height), curView_width, curView_height); R_Bloom_Quad( 0, glheight - midsample_height, midsample_width, midsample_height, screenText_tcw, screenText_tch ); // Now copy into Downsampling (mid-sized) texture. GL_Bind(r_bloomdownsamplingtexture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, midsample_width, midsample_height); // Now draw again in bloom size. glColor4f( 0.5f, 0.5f, 0.5f, 1.0f ); R_Bloom_Quad( 0, glheight - sample_height, sample_width, sample_height, sampleText_tcw, sampleText_tch ); // Now blend the big screen texture into the bloom generation space (hoping it adds some blur). glEnable( GL_BLEND ); glBlendFunc(GL_ONE, GL_ONE); glColor4f( 0.5f, 0.5f, 0.5f, 1.0f ); GL_Bind(r_bloomscreentexture); R_Bloom_Quad( 0, glheight - sample_height, sample_width, sample_height, screenText_tcw, screenText_tch ); glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); glDisable( GL_BLEND ); } else { // Downsample simple. GL_Bind(r_bloomscreentexture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, curView_x, glheight - (curView_y + curView_height), curView_width, curView_height); R_Bloom_Quad( 0, glheight - sample_height, sample_width, sample_height, screenText_tcw, screenText_tch ); } }
/* ================= R_Bloom_DownsampleView ================= */ static void R_Bloom_DownsampleView( void ) { pglDisable( GL_BLEND ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); if( r_screendownsamplingtexture_size ) { // stepped downsample int midsample_width = ( r_screendownsamplingtexture_size * sampleText_tcw ); int midsample_height = ( r_screendownsamplingtexture_size * sampleText_tch ); // copy the screen and draw resized GL_Bind( GL_TEXTURE0, r_bloomscreentexture ); pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, curView_x, glState.height - ( curView_y + curView_height ), curView_width, curView_height ); R_Bloom_Quad( 0, glState.height - midsample_height, midsample_width, midsample_height, screenTex_tcw, screenTex_tch ); // now copy into downsampling (mid-sized) texture GL_Bind( GL_TEXTURE0, r_bloomdownsamplingtexture ); pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, midsample_width, midsample_height ); // now draw again in bloom size pglColor4f( 0.5f, 0.5f, 0.5f, 1.0f ); R_Bloom_Quad( 0, glState.height - sample_height, sample_width, sample_height, sampleText_tcw, sampleText_tch ); // now blend the big screen texture into the bloom generation space (hoping it adds some blur) pglEnable( GL_BLEND ); pglBlendFunc( GL_ONE, GL_ONE ); pglColor4f( 0.5f, 0.5f, 0.5f, 1.0f ); GL_Bind( GL_TEXTURE0, r_bloomscreentexture ); R_Bloom_Quad( 0, glState.height - sample_height, sample_width, sample_height, screenTex_tcw, screenTex_tch ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); pglDisable( GL_BLEND ); } else { // downsample simple GL_Bind( GL_TEXTURE0, r_bloomscreentexture ); pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, curView_x, glState.height - ( curView_y + curView_height ), curView_width, curView_height ); R_Bloom_Quad( 0, glState.height - sample_height, sample_width, sample_height, screenTex_tcw, screenTex_tch ); } }
/* * R_Bloom_DownsampleView */ static void R_Bloom_DownsampleView( void ) { qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); if( r_screendownsamplingtexture_size ) { // stepped downsample int midsample_width = ( r_screendownsamplingtexture_size * sampleText_tcw ); int midsample_height = ( r_screendownsamplingtexture_size * sampleText_tch ); // copy the screen and draw resized GL_Bind( 0, r_bloomscreentexture ); qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, curView_x, glState.height - ( curView_y + curView_height ), curView_width, curView_height ); R_Bloom_Quad( 0, 0, midsample_width, midsample_height, screenTex_tcw, screenTex_tch ); // now copy into downsampling (mid-sized) texture GL_Bind( 0, r_bloomdownsamplingtexture ); qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, midsample_width, midsample_height ); // now draw again in bloom size qglColor4f( 0.5f, 0.5f, 0.5f, 1.0f ); R_Bloom_Quad( 0, 0, sample_width, sample_height, sampleText_tcw, sampleText_tch ); // now blend the big screen texture into the bloom generation space (hoping it adds some blur) GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE ); GL_Bind( 0, r_bloomscreentexture ); R_Bloom_Quad( 0, 0, sample_width, sample_height, screenTex_tcw, screenTex_tch ); qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); } else { // downsample simple GL_Bind( 0, r_bloomscreentexture ); qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, curView_x, glState.height - ( curView_y + curView_height ), curView_width, curView_height ); R_Bloom_Quad( 0, 0, sample_width, sample_height, screenTex_tcw, screenTex_tch ); } }
// ================= // R_BloomBlend // ================= void R_BloomBlend (void) { extern vrect_t scr_vrect; if( !r_bloom.value ) { return; } if( !BLOOM_SIZE || screen_texture_width < glwidth || screen_texture_height < glheight) { R_Bloom_InitTextures(); } if( screen_texture_width < BLOOM_SIZE || screen_texture_height < BLOOM_SIZE ) { return; } // Set up full screen workspace. glViewport( 0, 0, glwidth, glheight ); glDisable( GL_DEPTH_TEST ); glMatrixMode( GL_PROJECTION ); glLoadIdentity (); glOrtho(0, glwidth, glheight, 0, -10, 100); glMatrixMode( GL_MODELVIEW ); glLoadIdentity (); glDisable(GL_CULL_FACE); glDisable( GL_BLEND ); glEnable( GL_TEXTURE_2D ); glColor4f( 1, 1, 1, 1 ); // Setup current sizes curView_x = scr_vrect.x * ((float)glwidth / vid.width); curView_y = scr_vrect.y * ((float)glheight / vid.height); curView_width = scr_vrect.width * ((float)glwidth / vid.width); curView_height = scr_vrect.height * ((float)glheight / vid.height); screenText_tcw = ((float)curView_width / (float)screen_texture_width); screenText_tch = ((float)curView_height / (float)screen_texture_height); if( scr_vrect.height > scr_vrect.width ) { sampleText_tcw = ((float)scr_vrect.width / (float)scr_vrect.height); sampleText_tch = 1.0f; } else { sampleText_tcw = 1.0f; sampleText_tch = ((float)scr_vrect.height / (float)scr_vrect.width); } sample_width = BLOOM_SIZE * sampleText_tcw; sample_height = BLOOM_SIZE * sampleText_tch; // Copy the screen space we'll use to work into the backup texture. GL_Bind(r_bloombackuptexture); //glBindTexture(GL_TEXTURE_2D, r_bloombackuptexture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, r_screenbackuptexture_size * sampleText_tcw, r_screenbackuptexture_size * sampleText_tch); // Create the bloom image. R_Bloom_DownsampleView(); R_Bloom_GeneratexDiamonds(); //R_Bloom_GeneratexCross(); // Restore the screen-backup to the screen. glDisable(GL_BLEND); GL_Bind(r_bloombackuptexture); glColor4f( 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 ); R_Bloom_DrawEffect(); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); }
/* * R_BloomBlend */ void R_BloomBlend( const refdef_t *fd ) { if( !( fd->rdflags & RDF_BLOOM ) || !r_bloom->integer ) return; if( !BLOOM_SIZE ) R_Bloom_InitTextures(); if( screen_texture_width < BLOOM_SIZE || screen_texture_height < BLOOM_SIZE ) return; // set up full screen workspace GL_Scissor( 0, 0, glState.width, glState.height ); GL_Viewport( 0, 0, glState.width, glState.height ); qglMatrixMode( GL_PROJECTION ); qglLoadIdentity(); qglOrtho( 0, glState.width, glState.height, 0, -10, 100 ); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity(); GL_Cull( 0 ); GL_SetState( GLSTATE_NO_DEPTH_TEST ); qglColor4f( 1, 1, 1, 1 ); // set up current sizes curView_x = fd->x; curView_y = fd->y; curView_width = fd->width; curView_height = fd->height; screenTex_tcw = ( (float)curView_width / (float)screen_texture_width ); screenTex_tch = ( (float)curView_height / (float)screen_texture_height ); if( curView_height > curView_width ) { sampleText_tcw = ( (float)curView_width / (float)curView_height ); sampleText_tch = 1.0f; } else { sampleText_tcw = 1.0f; sampleText_tch = ( (float)curView_height / (float)curView_width ); } sample_width = ( BLOOM_SIZE * sampleText_tcw ); sample_height = ( BLOOM_SIZE * sampleText_tch ); // copy the screen space we'll use to work into the backup texture GL_Bind( 0, r_bloombackuptexture ); qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, r_screenbackuptexture_width, r_screenbackuptexture_height ); // create the bloom image R_Bloom_DownsampleView(); R_Bloom_GeneratexDiamonds(); // restore the screen-backup to the screen GL_SetState( GLSTATE_NO_DEPTH_TEST ); GL_Bind( 0, r_bloombackuptexture ); qglColor4f( 1, 1, 1, 1 ); R_Bloom_Quad( 0, 0, r_screenbackuptexture_width, r_screenbackuptexture_height, 1.0f, 1.0f ); GL_Scissor( ri.scissor[0], ri.scissor[1], ri.scissor[2], ri.scissor[3] ); R_Bloom_DrawEffect(); GL_Viewport( ri.viewport[0], ri.viewport[1], ri.viewport[2], ri.viewport[3] ); }
/* ================= R_BloomBlend ================= */ void R_BloomBlend( const ref_params_t *fd ) { if( !r_bloom->value ) return; if( !BLOOM_SIZE ) R_Bloom_InitTextures(); if( screen_texture_width < BLOOM_SIZE || screen_texture_height < BLOOM_SIZE ) return; // set up full screen workspace pglScissor( 0, 0, glState.width, glState.height ); pglViewport( 0, 0, glState.width, glState.height ); pglMatrixMode( GL_PROJECTION ); pglLoadIdentity(); pglOrtho( 0, glState.width, glState.height, 0, -10, 100 ); pglMatrixMode( GL_MODELVIEW ); pglLoadIdentity(); pglDisable( GL_DEPTH_TEST ); pglDisable( GL_ALPHA_TEST ); pglDepthMask( GL_FALSE ); pglDisable( GL_BLEND ); GL_Cull( 0 ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); // set up current sizes curView_x = fd->viewport[0]; curView_y = fd->viewport[1]; curView_width = fd->viewport[2]; curView_height = fd->viewport[3]; screenTex_tcw = ( (float)curView_width / (float)screen_texture_width ); screenTex_tch = ( (float)curView_height / (float)screen_texture_height ); if( curView_height > curView_width ) { sampleText_tcw = ( (float)curView_width / (float)curView_height ); sampleText_tch = 1.0f; } else { sampleText_tcw = 1.0f; sampleText_tch = ( (float)curView_height / (float)curView_width ); } sample_width = ( BLOOM_SIZE * sampleText_tcw ); sample_height = ( BLOOM_SIZE * sampleText_tch ); // copy the screen space we'll use to work into the backup texture GL_Bind( GL_TEXTURE0, r_bloombackuptexture ); pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, r_screenbackuptexture_width * sampleText_tcw, r_screenbackuptexture_height * sampleText_tch ); // create the bloom image R_Bloom_DownsampleView(); R_Bloom_GeneratexDiamonds(); pglDisable( GL_BLEND ); // restore the screen-backup to the screen GL_Bind( GL_TEXTURE0, r_bloombackuptexture ); pglColor4f( 1, 1, 1, 1 ); R_Bloom_Quad( 0, glState.height - (r_screenbackuptexture_height * sampleText_tch), r_screenbackuptexture_width * sampleText_tcw, r_screenbackuptexture_height * sampleText_tch, sampleText_tcw, sampleText_tch ); pglScissor( RI.scissor[0], RI.scissor[1], RI.scissor[2], RI.scissor[3] ); R_Bloom_DrawEffect(); pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] ); pglMatrixMode( GL_PROJECTION ); GL_LoadMatrix( RI.projectionMatrix ); pglMatrixMode( GL_MODELVIEW ); GL_LoadMatrix( RI.worldviewMatrix ); pglEnable( GL_DEPTH_TEST ); pglDepthMask( GL_TRUE ); pglDisable( GL_BLEND ); GL_Cull( GL_FRONT ); }
/* ================= R_Bloom_GeneratexDiamonds ================= */ static void R_Bloom_WarsowEffect( void ) { int i, j, k; float intensity, scale, *diamond; qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); //Take the backup texture and downscale it GL_Bind( bloom.screen.texture ); GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); R_Bloom_Quad( bloom.work.width, bloom.work.height, 0, 0, bloom.screen.readW, bloom.screen.readH ); //Copy downscaled framebuffer into a texture GL_Bind( bloom.effect.texture ); qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height ); // darkening passes with repeated filter if( r_bloom_darken->integer ) { int i; GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO ); for( i = 0; i < r_bloom_darken->integer; i++ ) { R_Bloom_Quad( bloom.work.width, bloom.work.height, 0, 0, bloom.effect.readW, bloom.effect.readH ); } qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height ); } /* Copy the result to the effect texture */ GL_Bind( bloom.effect.texture ); qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height ); // bluring passes, warsow uses a repeated semi blend on a selectable diamond grid qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE_MINUS_SRC_COLOR ); if( r_bloom_diamond_size->integer > 7 || r_bloom_diamond_size->integer <= 3 ) { if( r_bloom_diamond_size->integer != 8 ) ri.Cvar_Set( "r_bloom_diamond_size", "8" ); } else if( r_bloom_diamond_size->integer > 5 ) { if( r_bloom_diamond_size->integer != 6 ) ri.Cvar_Set( "r_bloom_diamond_size", "6" ); } else if( r_bloom_diamond_size->integer > 3 ) { if( r_bloom_diamond_size->integer != 4 ) ri.Cvar_Set( "r_bloom_diamond_size", "4" ); } switch( r_bloom_diamond_size->integer ) { case 4: k = 2; diamond = &Diamond4x[0][0]; scale = r_bloom_intensity->value * 0.8f; break; case 6: k = 3; diamond = &Diamond6x[0][0]; scale = r_bloom_intensity->value * 0.5f; break; default: // case 8: k = 4; diamond = &Diamond8x[0][0]; scale = r_bloom_intensity->value * 0.3f; break; } for( i = 0; i < r_bloom_diamond_size->integer; i++ ) { for( j = 0; j < r_bloom_diamond_size->integer; j++, diamond++ ) { float x, y; intensity = *diamond * scale; if( intensity < 0.01f ) continue; qglColor4f( intensity, intensity, intensity, 1.0 ); x = (i - k) * ( 2 / 640.0f ) * bloom.effect.readW; y = (j - k) * ( 2 / 480.0f ) * bloom.effect.readH; R_Bloom_Quad( bloom.work.width, bloom.work.height, x, y, bloom.effect.readW, bloom.effect.readH ); } } qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height ); }
/* ================= R_Bloom_Cascaded ================= Tcpp: sorry for my poor English skill. */ static void R_Bloom_Cascaded( void ){ int scale; int oldWorkW, oldWorkH; int newWorkW, newWorkH; float bloomShiftX=r_bloom_cascade_blur->value/(float)bloom.effect.width; float bloomShiftY=r_bloom_cascade_blur->value/(float)bloom.effect.height; float intensity=r_bloom_cascade_intensity->value; float intensity2; qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); //Take the backup texture and downscale it GL_Bind( bloom.screen.texture ); GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); R_Bloom_Quad( bloom.work.width, bloom.work.height, 0, 0, bloom.screen.readW, bloom.screen.readH ); //Copy downscaled framebuffer into a texture GL_Bind( bloom.effect.texture ); qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height ); /* Copy the result to the effect texture */ GL_Bind( bloom.effect2.texture ); qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height ); // do blurs.. scale=32; while(bloom.work.width<scale) scale>>=1; while(bloom.work.height<scale) scale>>=1; // prepare the first level. newWorkW=bloom.work.width/scale; newWorkH=bloom.work.height/scale; GL_Bind( bloom.effect2.texture ); GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); intensity2=intensity/(float)scale; qglColor4f( intensity2, intensity2, intensity2, 1.0 ); R_Bloom_Quad( newWorkW, newWorkH, 0, 0, bloom.effect2.readW, bloom.effect2.readH ); // go through levels. while(scale>1){ float oldScaleInv=1.f/(float)scale; scale>>=1; oldWorkH=newWorkH; oldWorkW=newWorkW; newWorkW=bloom.work.width/scale; newWorkH=bloom.work.height/scale; // get effect texture. GL_Bind( bloom.effect.texture ); qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWorkW, oldWorkH); // maginfy the previous level. if(r_bloom_cascade_blur->value<.01f){ // don't blur. qglColor4f( 1.f, 1.f, 1.f, 1.0 ); GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); R_Bloom_Quad( newWorkW, newWorkH, 0, 0, bloom.effect.readW*oldScaleInv, bloom.effect.readH*oldScaleInv ); }else{ // blur. qglColor4f( .25f, .25f, .25f, 1.0 ); GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); R_Bloom_Quad( newWorkW, newWorkH, -bloomShiftX, -bloomShiftY, bloom.effect.readW*oldScaleInv, bloom.effect.readH*oldScaleInv ); GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); R_Bloom_Quad( newWorkW, newWorkH, bloomShiftX, -bloomShiftY, bloom.effect.readW*oldScaleInv, bloom.effect.readH*oldScaleInv ); R_Bloom_Quad( newWorkW, newWorkH, -bloomShiftX, bloomShiftY, bloom.effect.readW*oldScaleInv, bloom.effect.readH*oldScaleInv ); R_Bloom_Quad( newWorkW, newWorkH, bloomShiftX, bloomShiftY, bloom.effect.readW*oldScaleInv, bloom.effect.readH*oldScaleInv ); } // add the input. intensity2=intensity/(float)scale; qglColor4f( intensity2, intensity2, intensity2, 1.0 ); GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); GL_Bind( bloom.effect2.texture ); R_Bloom_Quad( newWorkW, newWorkH, 0, 0, bloom.effect2.readW, bloom.effect2.readH ); } GL_Bind( bloom.effect.texture ); qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height ); }
void R_BloomBlend ( refdef_t *fd ) { if( !(fd->rdflags & RDF_BLOOM) || !r_bloom->value || r_showtris->value ) return; if( !BLOOM_SIZE ) R_Bloom_InitTextures(); if( screen_texture_width < BLOOM_SIZE || screen_texture_height < BLOOM_SIZE ) return; //set up full screen workspace qglViewport ( 0, 0, vid.width, vid.height ); GL_TexEnv (GL_REPLACE); // Knightmare added GL_Disable (GL_DEPTH_TEST); qglMatrixMode (GL_PROJECTION); qglLoadIdentity (); qglOrtho(0, vid.width, vid.height, 0, -10, 100); qglMatrixMode (GL_MODELVIEW); qglLoadIdentity (); GL_Disable (GL_CULL_FACE); GL_Disable (GL_BLEND); qglEnable (GL_TEXTURE_2D); qglColor4f (1, 1, 1, 1); //set up current sizes curView_x = fd->x; curView_y = fd->y; curView_width = fd->width; curView_height = fd->height; screenText_tcw = ((float)fd->width / (float)screen_texture_width); screenText_tch = ((float)fd->height / (float)screen_texture_height); if( fd->height > fd->width ) { sampleText_tcw = ((float)fd->width / (float)fd->height); sampleText_tch = 1.0f; } else { sampleText_tcw = 1.0f; sampleText_tch = ((float)fd->height / (float)fd->width); } sample_width = BLOOM_SIZE * sampleText_tcw; sample_height = BLOOM_SIZE * sampleText_tch; //copy the screen space we'll use to work into the backup texture GL_Bind(r_bloombackuptexture->texnum); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, r_screenbackuptexture_size * sampleText_tcw, r_screenbackuptexture_size * sampleText_tch); //create the bloom image R_Bloom_DownsampleView(); R_Bloom_GeneratexDiamonds( fd ); //R_Bloom_GeneratexCross(); //restore the screen-backup to the screen GL_Disable(GL_BLEND); GL_Bind(r_bloombackuptexture->texnum); qglColor4f( 1, 1, 1, 1 ); R_Bloom_Quad( 0, vid.height - (r_screenbackuptexture_size * sampleText_tch), r_screenbackuptexture_size * sampleText_tcw, r_screenbackuptexture_size * sampleText_tch, sampleText_tcw, sampleText_tch ); R_Bloom_DrawEffect( fd ); // Knightmare added R_SetupGL (); GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); qglEnable (GL_TEXTURE_2D); qglColor4f(1,1,1,1); }