Friday, March 9, 2012

Black screen on simulator for iPad retina using cocos2d

I am excited to see that iPad has a retina display. As I am developing my first iPhone/iPad game (universal application) using cocos2d 1.0.1, I updated my Xcode to 4.3.1 to see if my code still works on the new device display.

It showed a black screen.  Nothing displayed.  But the code seems to be running and responding to touch events.  I did not know what happened so I started to search on the web.  I found one posting on cocos2d-iphone forum started a day ago was discussing exactly the same problem.  I read every post and experimented all the proposed solutions.  I don't think it is anything to do with '-hd' image files, as the sample cocos2d HelloWorld did not work in iPad retina display either. But apparently lowering the resolution makes everything work again.  I noticed one member mentioned something particularly interesting, which was about the call to

gluPerspective() in CCDirectorIOS -setProjection()

The call stack is
enableRetinaDisplay => setContentScaleFactor => setProjection, as enableRetinaDisplay is the center of the discussion.

I found that switching to the commented code one line before the now in-use code in CCDirectorIOS makes my code work again in all the simulators.  I posted it to the thread. But here is the complete posting.  Hope this helps you as well.


I was following DonomaGames's post on gluPerspective() (CCDirectorIOS line 212-213).  Line 212 was commented out and replaced with line 213,

gluPerspective(60, (GLfloat)size.width/size.height, 0.5f, 1500);

which has zFar as 1500.  I did a calculation using the formula on 212, zNear=zeye-height/2, zFar=zeye+height/2. On iPad retina, the zFar value is 2794.707275.  It is larger than 1500. The rendering may be clipped off.

For comparison I computed the whole four types.

TypezNear  zFar
iPhone SD   175655
iPhone HD  3501310
iPad SD3731397
iPad HD7462794

Given that, I changed line 212 in CCDirectorIOS.m to
gluPerspective(60, (GLfloat)size.width/size.height, 0.5f, 2800);
It worked for iPad retina simulator.

I also tried the following code and worked also.

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad &&
    [[UIScreen mainScreen] scale] > 1.0 )
{
    gluPerspective(60, (GLfloat)size.width/size.height, zeye-size.height/2, zeye+size.height/2 );
} else {
    gluPerspective(60, (GLfloat)size.width/size.height, 0.5f, 1500);
}

This combines the original 212 and 213 code.

2 comments:

  1. Thanks this works for me. That black screen was a dead end and was driving me mad.
    I hope it is the correct answer as upgrading cocos2d again may kill me.
    I really need to get a new ipad to test it for sure.

    cheers

    ReplyDelete
    Replies
    1. @SpeakingStones,
      I sent the git pull request to cocos2d. From the messages I received from github, the proposed change has been integrated into cocos2d 1.1 beta and 2.0 draft.
      Definitely buy a new iPad to test it out. I need to do the same as well. Glad it helped.

      Delete