iPhone : OpenGL ES で画像をイヤラシくだす。② | ゲームプログラマ志望が福岡で叫ぶ 『絶望』

ゲームプログラマ志望が福岡で叫ぶ 『絶望』

プログラマーになりたい!!!!! あ、風のうわさで聞いた最近若者で流行っているトゥイッターなるものを始めてみました (・ト・) @toshi_desu_yo

前回から早数週間・・・


【 ( URL) iPhone : OpenGL ES で画像をイヤラシくだす。① 】




OpenGL ESで画像を生成したのはいいものの

[貼り付け] → [描画] を書いていないという現実逃走をしていたので



今回は実際に読み込んだ画像を画面に出してみます!(`・ω・´)




前回、
画像を読み込み

テクスチャに貼り付けて表示するには2のべき乗でないとダメなので
2のべき乗で生成したbitmapに画像を作りなおす
ところまでを終えました。



次に、
テクスチャを作成し
テクスチャに、生成したbitmapをぺたりと貼り付けてみようと思います。




テクスチャの生成は簡単です。

OpenGL ES初期化時に フレームバッファとレンダバッファを生成しましたが
それと同じ流れになります。 Gen で作成し、 Bind で設定する。



種類は違えど、

処理を同じ流れで作っていただくととても覚えやすくなりますね!




まずはヘッダーにテクスチャの識別番号を保持する入れ物を宣言します。

これも GLuint( 4 Byte ) なので、テクスチャ自身ではなく、
テクスチャが存在する場所の識別子を保持します。



----- [ ViewController.h ] ----- 

/** テクスチャ **/
GLuint mTexture;




次に .m の初期化関数の下の方でテクスチャを割り当ててみます


----- [ ViewController.m ] ----- 

/** テクスチャ領域を生成し、 mTexture 変数に識別番号を入れる。 **/
glGenTextures( 1, &mTexture );

/** これから使用するテクスチャをセットする。 **/
glBindTexture( GL_TEXTURE_2D, mTexture );





次に、テクスチャにBitMapを貼り付けるのですが、

その前に貼り付け方や保管方法などの設定をします。


----- [ ViewController.m ] ----- 

// 自動的にミップマップ画像を作成してくれる
glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP_HINT, GL_TRUE );

// テクスチャを拡大縮小するときの保管方法
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );

//
テクスチャの繰り返し方法
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_SGL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_TGL_CLAMP_TO_EDGE );




テクスチャを実際に画面に出す時、
テクスチャを実際のサイズより大きく表示したり小さく表示したりすることが多々あります。


その時、


予め適当な小さい画像、大きい画像を作成しておき
それを表示することでぼやけが少なくなります。

「ミップマップ画像を自動生成」というのはそれを自動で作成してくれるというものです。



内部で勝手にしてくれるので最初は適当に放置しておいてありがたく使用しておきましょう!





「テクスチャを拡大縮小するときの保管方法」
「テクスチャの繰り返し方法
」 とかは・・・


まぁこの設定でいいと思います(適当)





決して面倒くさいからとかではない・・・



というかココらへんは最初は別に気にせずに先行きましょ。

取り敢えず最初は描画できたらおっけー という感じで。






設定が終わったら後はテクスチャに2のべき乗のビットマップを貼り付け。



【 glTexImage2D 関数】
 
void glTexImage2D(
        GLenum target,                
/* GL_TEXTURE_2D 固定 */
        GLint level,                        /* MIPMAPレベル  */
        GLint internalFormat,      /* テクスチャの形式 */
        GLsizei width,                   /* テクスチャの幅 */
        GLsizei height,                 /* テクスチャの高さ */ 
        GLint border,                    /* テクスチャの境界線の幅 */
        GLenum format,              /* ピクセルの形式 */
        GLenum type,                  /* ピクセルの型 */
        const GLvoid *pixels );   /* 画像を格納した配列のポインタ */



・levelはMIPMAPを使わなければ 0 でおkです。
・テクスチャの幅高さは2のべき乗になっていなければなりません。
・境界線は基本 0 で。
・テクスチャの形式とピクセルの形式は 通常ではGL_RGBA になります。
・ポインタにビットマップのピクセルが入った配列を渡します。




// 画像をテクスチャに貼り付け。
// テクスチャは2のべき乗。
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, mTexSize.width, mTexSize.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pImageData );




これで終わり!


テクスチャにbitmapを貼りつけたので
後はこれをポリゴンに貼り付けるだけです。



前回のプロジェクトを流用するので
iPhoneの画面全体にテクスチャを描画します。



注意点として、

テクスチャでは幅高さの大きさにかかわらず、
必ず大きさが 0.0 ~ 1.0 の間になります。





アーボッコさんでは ( 320, 480 )の画像 ( 512, 512 ) のビットマップに生成し直し、

それを( 512, 512 )のテクスチャに貼り付けました。



となると、テクスチャ座標系では

512 が 1.0  となります。



( 512, 512 ) のテクスチャから ( 320, 480 ) を切り出したいので、、、


( 幅 ) 320 / 512 = 0.625;
( 高 ) 480 / 512 = 0.9375;  





アーボッコさん画像全体のテクスチャ座標になります。




この数値を描画時に使用します。



ポリゴンを描画する前に、頂点ごとにテクスチャの座標を指定して、
使用するテクスチャを設定すればポリゴンにテクスチャが貼り付けられます。




どんな画像サイズが来てもいいように数値を直書きではなく

 「画像サイズ ÷ テクスチャサイズ」 をプログラム上に書きます。


// テクスチャ座標
GLfloat tx = 0.0f;
GLfloat ty = 0.0f;
GLfloat tw = mImageSize.width/mTexSize.width;
GLfloat th = mImageSize.height/mTexSize.height;

const
GLfloat texCoords[] =
{
    tx, ty, // 左上
    tx + tw, ty, // 右上
    tx, ty + th, // 左下
    tx + tw, ty + th, // 右下
};

//
テクスチャ機能を有効にする
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, mTexture );



注意点としては


  glEnable で テクスチャを有効にし、
 glBindTexture で使用するテクスチャをコンテキストにバインドします。


これを行わなければポリゴンにテクスチャが貼れずに困惑します。




後はポリゴンの頂点座標と頂点色みたいにテクスチャ座標をOpenGL ESに教えます。


//** テクスチャ座標をOpenGL ESに教える
//**     座標の数、 型、 オフセット値, テクスチャ座標が入った配列
glTexCoordPointer( 2, GL_FLOAT, 0, texCoords );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );





こんな結果に。





下のポリゴン色と混じってます(´・ω・`)




まぁ、コレでもいいんですが出来れば混ざってない物がいいですね。

ポリゴンとテクスチャの色をまぜまぜ操作するのが glTexEnvi 関数です。



void glTexEnvi(
    GLenum target,    /** GL_TEXURE_ENV 固定 **/
    GLnum pname,     /** GL_TEXTURE_ENV_MODE 固定 **/
    GLint param );      /** 合成方法 **/



三番目の引数の param を変更します!
※初期設定は GL_MODULATE になっています。


・GL_MODULATE
・GL_DECAL
・GL_REPLACE
・GL_BLEND



が指定できます。






----『 GL_REPLACE 』----

テクスチャ色でポリゴンを塗りつぶします



これが欲しい結果ですね!




----『 GL_DECAL 』----

テクスチャでアルファ値が 1.0 以下 の部分のみ ポリゴン色と混ざります。








しかし、
基本この関数は使わないと思います。



ポリゴン色を全部 ( 1.0, 1.0 1.0 1.0 ) の真っ白にしておくのが普通だと思います。




2Dでポリゴン食と混ぜることなんて殆ど無いですよねー・・・・  ?

ですよね?(不安)








後、2Dのテクスチャで使うといえば

アルファブレンドじゃないですかね。


アルファ値を持ったテクスチャと元々あった色を混ぜます。

これは


//** アルファブレンド
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );



この設定を利用するだけでいいと思います。


アルファ値が 0 ならば 完全に元々あった色が出てきて、 
0.5 ならば テクスチャの色と元々の色が半分ずつ混ざって表に出てきます。

これは最初に一回宣言しとけばおkです。




今回は↓







しゃー の所のアルファ値が 0 だったので完全に元々あった色が表に出てきています。




説明ベタなので今回の記事全てにおいて
よくわからなかったと思いますが、

ソースコードを見ていただくとわかると存じます!



【( URL ) ソースコード
【( URL ) OpenGLES_Test3




2D では これだけでゲームが作れると思います。
 


OpenGL ES は 3Dを使うと、とても気持ちよくなります。

3Dのためにも2Dをせっせと勉強してみたものの未だにわからない部分が多々あります・・・(´・ω・`)


勉強って大事ですね-・・・