How could I implement the bloom sample in EAGLView without the PVRShell ?


I’m working on an AR application and I can’t render my object properly: I want it to receive the bloom effect from the samples, but if the object is rendered and textured, the camera capture behind disappeared (black screen) and there is no bloom effect.

So my question is fairly simple : How does the cpp sample renders to the EAGLView, I know the PVRShell is involved somewhere, but how? To be more specific: I tried to implement the EAGLView by getting rid of everything that is tied to the PVRShell because I have to implement the UIGLViewProtocol provided by vuforia, it has a single method which sync the GL render to the AR calculations, which give me that header file

/******************************************************************************<br />
<br />
@File         EAGLView.h<br />
<br />
@Title<br />
<br />
@Version<br />
<br />
@Copyright    Copyright (c) Imagination Technologies Limited.<br />
<br />
@Platform<br />
<br />
@Description<br />
<br />
******************************************************************************/<br />
#ifndef _EAGLVIEW_H_<br />
#define _EAGLVIEW_H_<br />
<br />
<br />
#import <UIKit/UIKit.h><br />
#import <QCAR/UIGLViewProtocol.h><br />
<br />
#import <OpenGLES/EAGL.h><br />
#import <OpenGLES/EAGLDrawable.h><br />
<br />
#import <OpenGLES/ES2/gl.h><br />
#import <OpenGLES/ES2/glext.h><br />
<br />
#define MSAAx4 1<br />
<br />
const double c_TouchDistanceThreshold = 20.0;<br />
<br />
//CLASSES:<br />
<br />
@class EAGLView, QCARutils;<br />
<br />
//PROTOCOLS:<br />
<br />
@protocol EAGLViewDelegate <NSObject><br />
- (void) didResizeEAGLSurfaceForView:(EAGLView*)view; //Called whenever the EAGL surface has been resized<br />
@end<br />
<br />
<br />
/*<br />
This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass.<br />
The view content is basically an EAGL surface you render your OpenGL scene into.<br />
Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel.<br />
*/<br />
@interface EAGLView : UIView<br />
{<br />
<br />
@private<br />
NSString*                                   _format;<br />
GLuint                                      _depthFormat;<br />
BOOL                                        _autoresize;<br />
EAGLContext                                 *_context;<br />
GLuint                                      _framebuffer;<br />
GLuint                                      _renderbuffer;<br />
GLuint                                      _depthBuffer;<br />
int                                         _enableMSAA;<br />
int                                         _enableFramebufferDiscard;<br />
GLuint                                      _msaaMaxSamples;<br />
GLuint                                      _msaaFrameBuffer;<br />
GLuint                                      _msaaColourBuffer;<br />
GLuint                                      _msaaDepthBuffer;<br />
CGSize                                      _size;<br />
BOOL                                        _hasBeenCurrent;<br />
id<EAGLViewDelegate> __unsafe_unretained	_delegate;<br />
float                                       _scale;<br />
}<br />
- (id) initWithFrame:(CGRect)frame; //These also set the current context<br />
- (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format;<br />
- (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained scale:(float)fscale msaaMaxSamples:(GLuint)maxSamples;<br />
<br />
@property(readonly) GLuint framebuffer;<br />
@property(readonly) NSString* pixelFormat;<br />
@property(readonly) GLuint depthFormat;<br />
@property(readonly) EAGLContext *context;<br />
<br />
@property BOOL autoresizesSurface; //NO by default - Set to YES to have the EAGL surface automatically resized when the view bounds change, otherwise the EAGL surface contents is rendered scaled<br />
@property(readonly, nonatomic) CGSize surfaceSize;<br />
<br />
@property (nonatomic, unsafe_unretained) id<EAGLViewDelegate> delegate;<br />
<br />
- (void) setCurrentContext;<br />
- (BOOL) isCurrentContext;<br />
- (void) clearCurrentContext;<br />
<br />
- (void) BeginRender;<br />
- (void) EndRender;<br />
- (void) swapBuffers; //This also checks the current OpenGL error and logs an error if needed<br />
<br />
- (CGPoint) convertPointFromViewToSurface:(CGPoint)point;<br />
- (CGRect) convertRectFromViewToSurface:(CGRect)rect;<br />
<br />
@end<br />
<br />
#endif // _EAGLVIEW_H_
```<br />
Note that I also erase the stencil buffer, since the bloom effect does not need one (right?). I also changed the default initWithFrame method:<br />
  • (id) initWithFrame:(CGRect)frame


    return [self initWithFrame:frame pixelFormat:kEAGLColorFormatRGBA8 depthFormat:GL_DEPTH_COMPONENT24_OES preserveBackbuffer:NO scale:1.0f msaaMaxSamples:0];

So I can simply add the view in a UIViewController with [[UIView alloc] initWithFrame: viewBounds]. I have no error when trying to implement the renderFrameQCAR mehod with this<br />

[self BeginRender];

// Clear colour and depth buffers


// Retrieve tracking state and render video background and

QCAR::State state = QCAR::Renderer::getInstance().begin();



//[self swapBuffers];

[self EndRender];

Nothing is drawn, when I run Instrument, I have a severe "Present of Non-Existent Renderbuffer" ("Your application attempted to present a non-existent renderbuffer...")<br />
When calling the swapBuffers method, I have an "Uninitialized Color Attachment" warning ("Your application presented a renderbuffer, but did not render content to all pixels in the renderbuffer....")<br />
<br />
My questions are all tied to my misunderstanding of how the EAGLView _framebuffer,  _renderBuffer and _depthbuffer communicate with the other buffers used in the samples. I also tried to extend the PVR EAGLView, merge the Bloom sample in it, use it on a view controller and prayed that some kind of magic will present an existing renderbuffer or fill the color attachment, but I end up with a "Present of Not Layer Backed Renderbuffer", basically saying that the "renderbufferStorage:fromDrawable" is not called.<br />
<br />
Anyway, if someone has the time and kindness to have a look<br />
Or to point me to the right direction, I've been hugely struggling with this.<br />


I’ve looked through your code and couldn’t see anything which seemed obviously incorrect.

The 3 variables you mentioned in the EAGLView class (_renderBuffer, _depthBuffer and _frameBuffer) are for OS usage. On iOS, developers are required to render to a user-initialised renderbuffer/framebuffer which is then passed to UIKit and composited by the OS. The Bloom example doesn’t use these variables directly - they should be used only in EAGLView code however they are essentially the frame buffer which your application should write to. The Bloom example uses several framebuffer objects in order to implement the technique which require similar handles and function calls. This could be the cause of your issue having incorrect framebuffers bound at a particular point in time. It’s hard to determine the exact problem in your case just by reading the code but my suggestion would be to inspect the handle ID’s of _renderBuffer and _frameBuffer when they are initialised and then in the calls to swapBuffer and/or EndRender to verify that the same handles are bound.

Does you application work correctly with no Bloom code implemented at all? Could it be that the AR library is setting an incorrect GL state?

Hi Arron. Thank you for an answer I was not expecting anymore.

Given tests I’ve made, I think you’re probably right when you say that my problem rests on the AR lib. So for debug purposes I just forgot my AR_EAGLView extends and used the EAGLView, implemented the UIGLViewProtocol so I have a renderFrameQCAR. Given that I just had warnings saying that I have uninitialized pixels (“MSAA Resolve of Uninitialized Color Attachment” if I use AA, “Present of uninitialized color attachment” if not), because nothing is drawn. OK…

If I now call the method that is supposed to draw my video background, I have the exact same warnings coming from the EndRender method…

    [self BeginRender];<br />
<br />
<br />
// draw video background<br />
QCAR::State state = QCAR::Renderer::getInstance().begin();<br />
QCAR::Renderer::getInstance().drawVideoBackground();<br />
<br />
QCAR::Renderer::getInstance().end();<br />
<br />
[self EndRender];
```<br />
which brings me back to zero. Either my code is wrong, or the QCAR does not guess, find the correct renderBuffer it's supposed to draw on... which means my code is wrong... You talked about inspecting the handle ID's, how can I do that ? I also looked the EAGLView from the QCAR samples and it basically follows the same procedure I'm trying to grab from your's, so I will be surprised if it comes from QCAR. Anyway, here is the last EAGLView I'm working with :<br />
<br />
Thank you.


What happens if you just strip your code back-to-basics? Call glClearColor(1.0f,0.0f,0.0f,1.0f); to set the clear colour to red, and remove the QCAR::* calls. If this still fails and you see nothing there’s some error somewhere in the EAGLView code which needs to be solved.

Try dropping some NSLog(@“Framebuffer binding: %dn”, _framebuffer); calls in strategic places in the render code for instance _createSurface or BeginRender and then in EndRender call glGetIntegerv(GL_FRAMEBUFFER_BINDING, &framebuffer); and make sure ‘_framebuffer’ and ‘framebuffer’ are the same.

Also check that _hasBeenCurrent is initialised to NO somewhere otherwise the call to glViewport will never be called.

Hey Arron, thanks for your insightful feedback and sorry for my very late reply.

It was probably something messy with the default frame buffer since I have not been able to draw anything on it and always ended with an empty frame buffer error. Somehow, somewhere, I was missing something… Since I’m not that skilled with OpenGL I decided to use a GLKViewController and TADAH, the rest went smoothly. Thanks for pointing the origin of my problem and let’s call that post answered…