/* * R_BlitTextureToScrFbo */ static void R_BlitTextureToScrFbo( const refdef_t *fd, image_t *image, int dstFbo, int program_type, const vec4_t color, int blendMask ) { int x, y; int w, h; RB_BindFrameBufferObject( dstFbo ); if( !dstFbo ) { // default framebuffer // set the viewport to full resolution // but keep the scissoring region x = fd->x; y = fd->y; w = fd->width; h = fd->height; RB_Viewport( 0, 0, glConfig.width, glConfig.height ); RB_Scissor( rn.scissor[0], rn.scissor[1], rn.scissor[2], rn.scissor[3] ); } else { // aux framebuffer // set the viewport to full resolution of the framebuffer // set scissor to default framebuffer resolution x = 0; y = 0; w = rf.frameBufferWidth; h = rf.frameBufferHeight; RB_Viewport( 0, 0, w, h ); RB_Scissor( 0, 0, glConfig.width, glConfig.height ); } // blit + flip R_DrawStretchQuick( x, y, w, h, (float)(x)/image->upload_width, 1.0 - (float)(y)/image->upload_height, (float)(x+w)/image->upload_width, 1.0 - (float)(y+h)/image->upload_height, color, program_type, image, blendMask ); // restore 2D viewport and scissor RB_Viewport( 0, 0, rf.frameBufferWidth, rf.frameBufferHeight ); RB_Scissor( 0, 0, rf.frameBufferWidth, rf.frameBufferHeight ); }
/* * R_BlitTextureToScrFbo */ static void R_BlitTextureToScrFbo( const refdef_t *fd, image_t *image, int dstFbo, int program_type, const vec4_t color, int blendMask, int numShaderImages, image_t **shaderImages ) { int x, y; int w, h, fw, fh; static char s_name[] = "$builtinpostprocessing"; static shaderpass_t p; static shader_t s; int i; static tcmod_t tcmod; mat4_t m; assert( rsh.postProcessingVBO ); // blit + flip using a static mesh to avoid redundant buffer uploads // (also using custom PP effects like FXAA with the stream VBO causes // Adreno to mark the VBO as "slow" (due to some weird bug) // for the rest of the frame and drop FPS to 10-20). RB_FlushDynamicMeshes(); RB_BindFrameBufferObject( dstFbo ); if( !dstFbo ) { // default framebuffer // set the viewport to full resolution // but keep the scissoring region x = fd->x; y = fd->y; w = fw = fd->width; h = fh = fd->height; RB_Viewport( 0, 0, glConfig.width, glConfig.height ); RB_Scissor( rn.scissor[0], rn.scissor[1], rn.scissor[2], rn.scissor[3] ); } else { // aux framebuffer // set the viewport to full resolution of the framebuffer (without the NPOT padding if there's one) // draw quad on the whole framebuffer texture // set scissor to default framebuffer resolution image_t *cb = RFB_GetObjectTextureAttachment( dstFbo, false ); x = 0; y = 0; w = fw = rf.frameBufferWidth; h = fh = rf.frameBufferHeight; if( cb ) { fw = cb->upload_width; fh = cb->upload_height; } RB_Viewport( 0, 0, w, h ); RB_Scissor( 0, 0, glConfig.width, glConfig.height ); } s.vattribs = VATTRIB_POSITION_BIT|VATTRIB_TEXCOORDS_BIT; s.sort = SHADER_SORT_NEAREST; s.numpasses = 1; s.name = s_name; s.passes = &p; p.rgbgen.type = RGB_GEN_IDENTITY; p.alphagen.type = ALPHA_GEN_IDENTITY; p.tcgen = TC_GEN_NONE; p.images[0] = image; for( i = 0; i < numShaderImages; i++ ) p.images[i + 1] = shaderImages[i]; p.flags = blendMask; p.program_type = program_type; if( !dstFbo ) { tcmod.type = TC_MOD_TRANSFORM; tcmod.args[0] = ( float )( w ) / ( float )( image->upload_width ); tcmod.args[1] = ( float )( h ) / ( float )( image->upload_height ); tcmod.args[4] = ( float )( x ) / ( float )( image->upload_width ); tcmod.args[5] = ( float )( image->upload_height - h - y ) / ( float )( image->upload_height ); p.numtcmods = 1; p.tcmods = &tcmod; } else { p.numtcmods = 0; } Matrix4_Identity( m ); Matrix4_Scale2D( m, fw, fh ); Matrix4_Translate2D( m, x, y ); RB_LoadObjectMatrix( m ); RB_BindShader( NULL, &s, NULL ); RB_BindVBO( rsh.postProcessingVBO->index, GL_TRIANGLES ); RB_DrawElements( 0, 4, 0, 6, 0, 0, 0, 0 ); RB_LoadObjectMatrix( mat4x4_identity ); // restore 2D viewport and scissor RB_Viewport( 0, 0, rf.frameBufferWidth, rf.frameBufferHeight ); RB_Scissor( 0, 0, rf.frameBufferWidth, rf.frameBufferHeight ); }