How to create 1536×2048 framebuffer for iPad Retina sample (GLGravity)

So of course the first thing I’m trying on my new iPad (4g) is the old GLGravity example. The only modification I’ve made is to set the target device to “iPad”.

However, when running on the device, the UIView’s bounds are set to 768,1024 as are the “backingWidth, backingHeight” in createFramebuffer.

  • MonoTouch: Doubling Appearance Image size when Hue adjusted on Retina display
  • Not including non-retina display images in an iPhone project
  • Creating retina screenshot programmatically resulting in non retina image
  • How do I create a 1px line in Interface Builder?
  • Retina display VS normal display color difference
  • How to support both iPad and iPhone retina graphics in universal apps
  • Eyeballing the image confirms it’s still being rendered at 768×1024. What have I missed – how do I get this to render at native resolution?

    4 Solutions Collect From Internet About “How to create 1536×2048 framebuffer for iPad Retina sample (GLGravity)”

    To enable conditional support for Retina graphics, as we did for the iPhone 4, you would need to have a line of code like this somewhere in the setup for your OpenGL ES hosting view (GLGravityView, in this case):

    self.contentScaleFactor = [[UIScreen mainScreen] scale];

    This makes sure that the content within that view (such as Quartz drawing) is rendered with the 2-pixels-per-point scaling used in the current Retina displays on the iPhone and iPad.

    Your view’s bounds will remain at the 768 x 1024 point size, but the render buffer will return 1536 x 2048 as its pixel dimensions when queried by glGetRenderbufferParameterivOES(). This will allow you to render Retina-level graphics within your OpenGL ES context.

    Note that some of Apple’s sample code (like GLGravity) uses the view bounds to size other display elements, so they will appear too small in the scene. You might need to replace calculations based on the view bounds (in points) with the backing width (in pixels) to make sure that the 2.0 scaling of the Retina graphics is taken into account.

    As an expansion on this answer, the GLGravity sample needs another change to ensure the GL viewport is set correctly. This is because theboundsproperty returns Quartz points, not pixels.

      CGRect rect = self.bounds;
      // new code - modify the viewport dimensions.
      rect.size.width *= self.contentScaleFactor;
      rect.size.height *= self.contentScaleFactor;
      // end of new code
      glFrustumf(-size, size, -size / (rect.size.width / rect.size.height), size / (rect.size.width / rect.size.height), zNear, zFar);
      glViewport(0, 0, rect.size.width, rect.size.height);

    I had the same problem: @2x ipad images present, but everything renders @1x on the new iPad. iPhone/iPod Touch works OK on retina and non-retina devices.
    Searching the Apple dev forums I found the problem: I am still on Xcode 4.2, building for iOS 5.0. This OS does not foresee the possibility of a retina ipad. So I need to build with 5.1.

    I think I kind of get this.

    XIB files measure in pts, not pixels. A pt is a unit of distance, like a cm, or a light-year. A pixel is not a unit of distance, it stands for “picture element”. Different devices can have different pixel densities.

    Your XIB file tells the size of your display area in pts. iPhone apps default to 320×480 pts, iPad 768×1024 pts. You can check this out in your xib file.

    Now, self.contentScaleFactor that Brad refers to is the answer. What this value does is: “convert from the default logical coordinate space (768×1024 pts) into the device coordinate space of this screen (1536×2048 px).”

    In other words, self.contentScaleFactor is a measure of pixels/pt used by the device. This value varies naturally from device to device. XCode has you specify UI elements in pts (unit of real world distance), so things don’t appear screwed up on different resolutions.

    You can even set self.contentScaleFactor=4, which actually looks kinda cool (it supersamples) (but can run slow).

    Another gotcha here is touch events will always be in pts, never in pixels. That is, retina devices still only resolve touch events on a 768×1024 scale.

    So, if your view supports touch picking, you need to multiply each incoming touch event by self.contentScaleFactor in order for the incoming location in pts to map to pixels in your framebuffer.