Огромное падение частоты кадров с прозрачным EAGLView

У меня есть проект Cocos2d, и мне нужен постоянный фон во всем приложении. В методе applicationDidFinishLaunching его делегата я заменил строку:

Я изменил пиксельный формат glView с kEAGLColorFormatRGB565 на kEAGLColorFormatRGBA8. Когда я делаю это изменение, glView становится прозрачным, и я могу видеть сквозь него, но частота кадров резко падает. Если я не внесу это изменение, вид не станет прозрачным, но я не вижу огромного падения частоты кадров. Я говорю о значительном падении фпс, с 59.0-60.0 примерно до 35.0-42.0.

Я использую этот код прямо под строкой addSubview выше, чтобы сделать представление прозрачным:

director.openGLView.opaque = NO;

Весь метод applicationDidFinishLaunching выглядит так:

- (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]];
}

Любые идеи относительно того, почему это происходит? Я могу предоставить больше кода, если это необходимо.

Я забыл упомянуть еще одно изменение кода, которое я сделал. В CCDirector.m setGLDefaultValues я изменил эту строку с этой:

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

К этому:

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

person Stephen    schedule 28.01.2013    source источник


Ответы (2)


Каждый раз, когда вы добавляете альфа-канал с прозрачностью, движку OpenGL придется выполнять некоторую форму (хотя и по умолчанию) альфа-смешивания. Это математика на пиксель, которую не нужно было делать в случае без RGBA (то есть RGB 565). Каждый раз, когда вы добавляете к математике, необходимой для движка, частота кадров будет падать.

person trumpetlicks    schedule 28.01.2013
comment
Есть ли другой способ сделать EAGLView прозрачным без изменения этой строки кода? - person Stephen; 29.01.2013
comment
@Stephen - зависит от того, что вы действительно пытаетесь сделать. Может возникнуть ситуация, когда EAGLView может быть позади, а не впереди (как вы это делаете в настоящее время), что позволит EAGLView быть непрозрачным. Я предполагаю, что у вас есть что-то за этим, что вы хотите показать через это. Если у вас вещь сзади стала вещью спереди, и наоборот, то возможны варианты! Кроме этого, не очень, если вам нужно что-то, чтобы показать через другую вещь, вам нужно разрешить прозрачность и смешивание. Вы можете изменить режим наложения. - person trumpetlicks; 29.01.2013
comment
@Stephen - Если вы знаете, что будете только на 100 % прозрачным или на 100 % непрозрачным, вы можете изменить режим наложения на более упрощенный (по сравнению с более тяжелым математическим) режимом наложения. Он по-прежнему допускал бы прозрачность, но, по сути, его можно было бы проще включать или выключать. Я знаю, что в приложении, которое я написал, у меня была функция, которая более просто запускалась при достижении 50% точки. Попробуйте здесь: opengl.org/sdk/docs/man/xhtml/glBlendFunc .xml - person trumpetlicks; 29.01.2013
comment
Мне действительно нужно только, чтобы EAGLview был прозрачным для главного меню, а затем он может быть форматом пикселей по умолчанию. Можно ли изменять формат пикселей каждый раз, когда отображается главное меню, а затем снова переключать его? - person Stephen; 29.01.2013
comment
Нет причин, по которым это невозможно, вы можете заметить временную задержку при переключении этого контекста, но, возможно, стоит увеличить частоту кадров там, где вы хотите / нуждаетесь в этом. - person trumpetlicks; 29.01.2013
comment
Могу ли я получить доступ к формату пикселей EAGLView в других классах так же, как и в appDelegate? - person Stephen; 29.01.2013
comment
Я бы, вероятно, написал пользовательскую процедуру в appDelegate, которая переключает режим, а затем вызовет ее из других дочерних классов. Другими словами, позвольте делегату делать то, что он должен, и управлять EGL. - person trumpetlicks; 29.01.2013
comment
Без использования метода init в EAGLView я точно не знаю, как бы я изменил формат пикселей. Для него есть свойство, но оно доступно только для чтения. Что ты предлагаешь. - person Stephen; 29.01.2013
comment
Не лучше ли перенести это в чат? Лично я никогда не общался. - person Stephen; 29.01.2013
comment
Не совсем уверен, что я бы изменил формат пикселей, лучше использовать функцию gl, которая включает и выключает прозрачность (glEnable (GL_BLEND), glDisable (GL_BLEND)); Если вы отключите glBlending, тогда OpenGL должен игнорировать альфа-канал и рассчитывать, как будто он непрозрачен. - person trumpetlicks; 29.01.2013
comment
Я попытался отключить GL_BLEND для обоих форматов пикселей, но он работает только в формате kEAGLColorFormatRGB565, поэтому я все еще получаю огромное падение FPS? - person Stephen; 29.01.2013

Этого следовало ожидать. Фреймбуфер RGBA8888 использует в два раза больше памяти, и GPU должен выполнять больше работы для рендеринга в этот фреймбуфер. Вот почему RGB565 является форматом по умолчанию.

person LearnCocos2D    schedule 28.01.2013
comment
на самом деле это больше добавленная математика, чем добавленная память. Именно это добавленное альфа-смешивание снижает частоту кадров. Другими словами, это не рендеринг в больший буфер кадра, это математика, которую он должен выполнить до попадания в буфер кадра, хотя я полагаю, вы правы, что он также должен поместить 2 дополнительных байта в буфер кадра для каждый пиксель тоже :-) Также ПОЛНОСТЬЮ согласен, что этого и следовало ожидать LOL - person trumpetlicks; 29.01.2013