Ok, so I have done some progress that I would like to share. Maybe get a little feedback too.
This is the Blur.fsh applied in realtime to a CCRenderTexture of the entire screen buffer. The RenderTexture is rendered on top of the main layer with some opacity altered.
I took the liberty of using some code from other users of this forum.

Wel, first of all, I'm using cocos2d 2.0 so I can use shaders. As you can see the fps are pretty low, like 11 fps average. Nonetheless, I think my next step is finding out how to make a layer (CCLayer) draw into a virtual context so the image only renders once. If somebody sees a big mistake here please post! I'm starting to think maybe fullscreen shader are too expensive to be useable in realtime. I've read people writing about RenderTextures being slow, but I have to keep reading.
After grabbing the blur test code from the cocos2d shader tests you'll have something like:
@interface SpriteBlur : CCSprite
{
CGPoint blur_;
CGFloat sub_[4];
GLuint blurLocation;
GLuint subLocation;
}
@end
@implementation SpriteBlur
-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
{
if( (self=[super initWithTexture:texture rect:rect]) ) {
blur_ = ccp(0.001, 0.001);
sub_[0] = sub_[1] = sub_[2] = sub_[3] = 0;
self.shaderProgram = [[GLProgram alloc] initWithVertexShaderFilename:@"PositionTextureColor.vsh"
fragmentShaderFilename:@"Blur.fsh"];
[self.shaderProgram release];
CHECK_GL_ERROR_DEBUG();
[shaderProgram_ addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position];
[shaderProgram_ addAttribute:kCCAttributeNameColor index:kCCVertexAttrib_Color];
[shaderProgram_ addAttribute:kCCAttributeNameTexCoord index:kCCVertexAttrib_TexCoords];
CHECK_GL_ERROR_DEBUG();
[shaderProgram_ link];
CHECK_GL_ERROR_DEBUG();
[shaderProgram_ updateUniforms];
CHECK_GL_ERROR_DEBUG();
subLocation = glGetUniformLocation( shaderProgram_->program_, "substract");
blurLocation = glGetUniformLocation( shaderProgram_->program_, "blurSize");
CHECK_GL_ERROR_DEBUG();
}
return self;
}
-(void) draw
{
ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex );
ccGLBlendFunc( blendFunc_.src, blendFunc_.dst );
ccGLUseProgram( shaderProgram_->program_ );
ccGLUniformModelViewProjectionMatrix( shaderProgram_ );
glUniform2f( blurLocation, blur_.x, blur_.y );
glUniform4f( subLocation, sub_[0], sub_[1], sub_[2], sub_[3] );
ccGLBindTexture2D( [texture_ name] );
//ccGLBindTexture2D( [newTexture name] );
//
// Attributes
//
#define kQuadSize sizeof(quad_.bl)
long offset = (long)&quad_;
// vertex
NSInteger diff = offsetof( ccV3F_C4B_T2F, vertices);
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));
// texCoods
diff = offsetof( ccV3F_C4B_T2F, texCoords);
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));
// color
diff = offsetof( ccV3F_C4B_T2F, colors);
glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
@end
I still don't know how to render my CCLayer into a virtual CGContext, so I'm basically duplicating the screen inside a CCRenderTexture.
mRenderTexture = [[CCRenderTexture renderTextureWithWidth:s.width height:s.height] retain];
CCSprite *auxRenderTextureSprite = [mRenderTexture sprite];
[auxRenderTextureSprite setPosition:ccp(s.width/2, s.height/2)];
[auxRenderTextureSprite setOpacity:255*0.5];
We are creating a full screen CCRenderTexture and lowering the opacity.
Then we create the BlurShader and pass the CCTexture2d instance of the Render Texture and flipping the Y coordinate cause render textures invert themselves for some reason.
SpriteBlur *blurSprite = [SpriteBlur spriteWithTexture:[[mRenderTexture sprite] texture]];
[blurSprite setPosition:ccp(s.width/2, s.height/2)];
blurSprite.scaleY *= -1;
[self addChild:blurSprite];
Lastly we need to update the CCRenderTexture with the actual screen buffer. This goes in the update(tick) method.
The first line makes our CCRenderTexture have alpha opacity.
[[mRenderTexture sprite] setBlendFunc:(ccBlendFunc){GL_ONE, GL_ONE_MINUS_SRC_ALPHA}];
[mRenderTexture beginWithClear:0 g:0 b:0 a:0];
[self visit];
[mRenderTexture end];