« kyoto-client | トップページ | android.opengl.GLSurfaceView.Renderer »

2012年3月23日 (金)

AndroidのOpenGLテクスチャでハマる

AndroidでOpenGLアプリを作っていたところ、glTexImage2DがGL_INVALID_VALUE (1281) というエラーになって動かない。よくよく調べると、テクスチャの寸法が768x768と、2のベキじゃない値になっている。元のPNGファイルは間違いなく512x512なのに。誰かが勝手に画像を拡大している!?

と、ここまで気づくのに2日間。

このテクスチャは、PNGをres/drawableに置いておき、BitmapFactory.decodeResource(Resources,int)で読み込んでいたのだが、このメソッドが勝手に拡大しているとしか思えない。

decodeResourceメソッドには、引数を3個取るバージョンがあって、第3引数にはBitmapFactory.Optionsというものを渡す。この説明をよーく読むと、Options.inScaledというパラメタがあって「ビットマップを読み込むときにターゲットの解像度に合わせてスケールする。デフォトはオンなので、ビットマップをスケールしないで読み込みたい場合はオフにしなさい。」みたいなことが書いてありました。それで、引数が2個の場合は、Optionsはすべてデフォルトとみなされる、と。

そこまでわかって改めて調べると、テストに使っていたデバイスのDisplayMetrics.densityは1.5だった。なるほどね。

つまり、こうすればよかったのだ。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap texture = BitmapFactory.decodeResource(res, R.drawable.texture, options);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, texture, 0);

わかってしまえばどうということは無いのだが、ウェブで検索してもこのポイントの説明を見かけない。こんなことでハマるのは私だけなのかな?


追記

「わかってしまえば」と偉そうなことを書きましたが、実はまだわかっていませんでした。

res/drawable-nodpi というフォルダを作って、そこにファイルを置けば、BitmapFactory.Optionsなんていうものを持ち出さなくてもそのまま読み込めました。

つまり、Androidでのビットマップファイルの置き場というのは、

res/drawable
デバイス解像度に応じて適当に拡大縮小されたものを読み込む
res/drawable-{l,m,h,xh}dpi
デバイス解像度に応じたフォルダが選ばれ、画像自体は拡大縮小されない
res/drawable-nodpi
デバイス解像度によらず、拡大縮小されずに読み込まれる

という規約なのでしたよ。

…ということが、まとめて書いてあるドキュメントが存在しないのが、また、なんというか、アレだ。

« kyoto-client | トップページ | android.opengl.GLSurfaceView.Renderer »

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/285638/44607622

この記事へのトラックバック一覧です: AndroidのOpenGLテクスチャでハマる:

« kyoto-client | トップページ | android.opengl.GLSurfaceView.Renderer »