1

I have a Cocos2d project and I want a constant background throughout the app. In the applicationDidFinishLaunching method of its delegate, I have replaced the line:

I have changed the pixelFormat of glView from kEAGLColorFormatRGB565 to kEAGLColorFormatRGBA8. When I make that change, glView becomes transparent and I can see through it, but the fps drops dramatically. If I don't make that change, the view doesn't become transparent, but I don't see the huge drop in fps. I'm talking about a significant drop in fps, from 59.0-60.0 to about 35.0-42.0.

I am using this code right below the addSubview line above to make the view transparent:

director.openGLView.opaque = NO;

The whole applicationDidFinishLaunching method looks like this:

- (void) applicationDidFinishLaunching:(UIApplication*)application
{
    // Init the window
    window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    // Try to use CADisplayLink director
    // if it fails (SDK < 3.1) use the default director
    if( ! [CCDirector setDirectorType:kCCDirectorTypeDisplayLink] )
        [CCDirector setDirectorType:kCCDirectorTypeDefault];


    CCDirector *director = [CCDirector sharedDirector];

    // Init the View Controller
    viewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];
    viewController.wantsFullScreenLayout = YES;

    //
    // Create the EAGLView manually
    //  1. Create a RGB565 format. Alternative: RGBA8
    //  2. depth format of 0 bit. Use 16 or 24 bit for 3d effects, like CCPageTurnTransition
    //
    //
    EAGLView *glView = [EAGLView viewWithFrame:[window bounds]
                                   pixelFormat:kEAGLColorFormatRGBA8    // kEAGLColorFormatRGBA8
                                   depthFormat:0                        // GL_DEPTH_COMPONENT16_OES
                        ];

    // attach the openglView to the director
    [director setOpenGLView:glView];
    glView.opaque = NO;
//  // Enables High Res mode (Retina Display) on iPhone 4 and maintains low res on all other devices
    if( ! [director enableRetinaDisplay:YES] )
        CCLOG(@"Retina Display Not supported");

    //
    // VERY IMPORTANT:
    // If the rotation is going to be controlled by a UIViewController
    // then the device orientation should be "Portrait".
    //
    // IMPORTANT:
    // By default, this template only supports Landscape orientations.
    // Edit the RootViewController.m file to edit the supported orientations.
    //
#if GAME_AUTOROTATION == kGameAutorotationUIViewController 
    [director setDeviceOrientation:kCCDeviceOrientationPortrait];
#else
    [director setDeviceOrientation:kCCDeviceOrientationLandscapeLeft];
#endif

    [director setAnimationInterval:1.0/60];
    [director setDisplayFPS:YES];


    // make the OpenGLView a child of the view controller
    [viewController setView:glView];

    //Required in iOS6, recommended in 4 and 5
    [window setRootViewController:viewController];

    // make the View Controller a child of the main window, needed for iOS 4 and 5
    [window addSubview: viewController.view];

    [window makeKeyAndVisible];

    // Default texture format for PNG/BMP/TIFF/JPEG/GIF images
    // It can be RGBA8888, RGBA4444, RGB5_A1, RGB565
    // You can change anytime.
    [CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];


    // Removes the startup flicker
    [self removeStartupFlicker];

    // Run the intro Scene
    [[CCDirector sharedDirector] runWithScene: [Intro scene]];
}

Any ideas as to why this is happening? I can provide more code if need be.

I forgot to mention one other code change that I did. In CCDirector.m setGLDefaultValuesI changed this line from this:

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

To this:

glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Stephen
  • 499
  • 9
  • 28

2 Answers2

1

Anytime you add an alpha channel with transparency, the OpenGL engine is going to have to perform some form (albeit default) alpha blending. This is math per pixel that it wasnt having to do in the non-RGBA (i.e. RGB 565) case. Anytime you add to the math needed by the engine frame rates are going to drop.

trumpetlicks
  • 7,033
  • 2
  • 19
  • 33
  • Is there another way to get the EAGLView to be transparent without changing that line of code? – Stephen Jan 28 '13 at 22:51
  • 1
    @Stephen - Kinda depends on really what you are trying to do. There may be a situation where the EAGLView can be behind instead of in front (how you are currently doing it) that will allow the EAGLView to be non-transparent. I am assuming that you have something behind it that you wish to be displayed through it. If you have the thing in the back become the thing in the front, and vice versa, then there may be options! Other than that not really, if you need something to show through another thing you will need to allow transparency and blending. You may be able to change the blend mode. – trumpetlicks Jan 28 '13 at 22:54
  • 1
    @Stephen - If you know that you are only going to be 100% transparent of 100% opaque, you may be able to modify the blend mode to a more simplistic (versus more heavy mathematical) blend mode. It would still allow transperency but it would essentially be able to more simply turn on or turn off. I know in an app I wrote, I had a function that was more simply triggered by a 50% point. Try here: http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunc.xml – trumpetlicks Jan 28 '13 at 22:57
  • I really only need to have the EAGLview to be transparent for the main menu and then it can be the default pixel format from there on. Is it possible to keep changing the pixel format each time the main menu is shown and then switch it back again? – Stephen Jan 28 '13 at 23:07
  • 1
    No reason why it cant, you may realize a time lag in switching that context, but it may be worth it to get your frame rate up where you want / need it. – trumpetlicks Jan 28 '13 at 23:08
  • Can I access the EAGLView pixel format the same way in other classes as I am in the appDelegate? – Stephen Jan 28 '13 at 23:11
  • 1
    I would probably write a custom routine within the appDelegate that switches the mode, then have the other child classes call that. In other words let the delegate do what it is supposed to and manage the EGL. – trumpetlicks Jan 28 '13 at 23:14
  • Without using the init method on the EAGLView I don't know for sure how I would change the pixel format. There is a property for it but it's a read only property. What would you suggest. – Stephen Jan 28 '13 at 23:19
  • Would it be better to move this to a chat? I personally have never done a chat. – Stephen Jan 28 '13 at 23:25
  • Not completely sure I would change the pixel format, just rather use the gl function that turns on and off transparency (glEnable (GL_BLEND), glDisable(GL_BLEND)); If you disable glBlending, then OpenGL should go ahead and ignore the alpha channel and calculate as if it is opaque. – trumpetlicks Jan 28 '13 at 23:48
  • I tried disabling the GL_BLEND on both pixel formats but it only works in the kEAGLColorFormatRGB565 format, therefore I am still getting the huge drop in FPS? – Stephen Jan 29 '13 at 18:00
1

This is to be expected. The RGBA8888 framebuffer uses twice as much memory and the GPU needs to perform more work to render into this framebuffer. This is why RGB565 is the default format.

CodeSmile
  • 64,284
  • 20
  • 132
  • 217
  • actually its more the added math then it is the added memory. It is that added alpha blending that makes the frame rates drop. In other words its not the rendering into the bigger frame buffer, it is the math that it has to do prior to it hitting the frame buffer, although I suppose you are correct that it also has to push 2 extra bytes to the frame buffer for each pixel as well :-) Also TOTALLY agree that it is to be expected LOL – trumpetlicks Jan 28 '13 at 22:48