OpenGL ESのRetina対応

OpenGL ESのRetina対応の方法をちょっとメモしておきます。OpenGL以外のRetina対応については@k_katsumiさんの記事「アプリケーションを iPhone 4 の Retina Display に対応するための方法いろいろ」がとても参考になると思います。というか、この記事を見てOpenGLについては書いてなかったので触発されて書くことにしました。

Xcodeの「OpenGL ES Application」で作成したプロジェクトの場合で書きますと、EAGLViewのViewのサイズはRetinaディスプレイでも変わらず320×480です。iOS4からUIView(およびEAGLViewなどのサブクラス)にcontentScaleFactorというメソッドが追加され、この値を変更することでUIViewの中の解像度を変更することができるようになりました。もうひとつ、UIViewがもってるCALayerのcontentsScaleでも解像度を変えることができるようです。デフォルトでは1.0になっていますので、Retinaディスプレイの解像度に合わせるには2.0にします。実際には、UIScreenのscaleからディスプレイのサイズの比率が取得できますので、そこからセットします。

ちょっとやってみましょう。AppDelegateのapplication:didFinishLaunchingWithOptions:メソッドに次のコードを書き加えてください。

glView.contentScaleFactor = [UIScreen mainScreen].scale;

基本、これだけでRetinaディスプレイのiPhone4だと倍の解像度になるのですが、「OpenGL ES Application」のデフォルト状態の描画内容だと効果が全然わからないので、さらにコードを変えてみます。

まず、シェーダーとか使ってるとめんどくさいのでES2Rendererを使わないようにします。以下のようにEAGLViewのinitWithCoderの中の一行を書き換えてください。

renderer = [[ES2Renderer alloc] init];
↓
renderer = nil;

次に、ES1Rendererのrenderメソッドの中の縦に動かしている一行を、高解像度の効果がわかりやすいように回転に変更します。

glTranslatef(0.0f, (GLfloat)(sinf(transY)/2.0f), 0.0f);
↓
glRotatef(transY, 0, 0, 1.0);

コードの変更は以上です。一番最初にAppDelegateに追加したglView.contentScaleFactorの一行のありなしでそれぞれiPhone 4で実行してみると四角形のエッジのスムーズさの違いがわかると思います。iPhone 4実機をもっていなくても、iPhone simulatorのデバイスをiPhone 4にすることで確認できます。

OpenGL的には単純に解像度が倍になりますので、ディスプレイのサイズに依存してアプリを作っていたら結構な修正を余儀なくされると思います。場所がずれたりとか、テクスチャも荒く表示されちゃったりとかすると思います。さらにやっかいなのが、UITouchの位置は2倍にならないってことです。scaleに応じて位置を調整する必要があります。

ちなみに、EAGLViewのcontentScaleFactorをセットするだけで解像度が変わっているのではなく、scaleをセットしてからESRendererのresizeFromLayerメソッドの中の[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer]が呼ばれて始めてGLの解像度が変わります。もし、glView生成時でなく、後からscaleを変更したいなんていう場合には、contentScaleFactorをセットしたあとにresizeFromLayerを呼んでください。

あと今、iOS4より前のバージョンもサポートするなら、iPadのiPhoneシミュレータで動くことも考えないといけなそうです。iPadでiPhoneアプリを2倍に表示するとUIScreenのscaleが2.0になってしまいますが、UIViewにはcontentScaleFactorがありません。また、CALayerのcontentsScaleはiPadでも受け付けることができますが、GLの解像度が変わることはありません。プロパティの有無やOSのバージョンなどでscaleを無視する必要がありそうです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です