ひっきぃのメモ帳

趣味で作るプラモデル製作の過程と作品、日々の資格取得へ向けての活動、Apple中心のIT関連ネタを書いています。

iOS SDK4.2 の環境で OpenGL ES1 を利用するには

ただいま勉強中です。少し間違った情報が混じっても許して下さい。

iOSOpenGLの環境について勉強しました。

古い機種への対応も視野にいれるなら、機能は少ないが ES1 を選択するべき。
書籍でも ES1ベースの説明になっているようなので、これから勉強するにもES1の方が楽そうです。
うちにあるのは、iPhone3GSiPod touch 第1世代なので、その意味でもES1が最適です。

巷に溢れている書籍(といっても2冊しか見てませんが)は SDK3.x をベースに書かれている様子で、サンプルプロジェクトを作成しても同じコードができないようです。
となれば選択肢は2つ

  • あきらめて SDK3.x を使って作成する(既にダウンロードしたものはもっている)
  • SDK4.2の内容を解読して書き換える。

後者の解読をして、SDK4.2の環境でOpenGL ES1で開発できるようにしました。


ベースになるファイルは ◯◯◯◯ViewController.m
              ◯◯◯◯は作成したプロジェクト名

awakeFromNibが初期化ルーチン

 - (void)awakeFromNib
{
    EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    
   if (!aContext)
    {
        aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
    }
    
    if (!aContext)
        NSLog(@"Failed to create ES context");
    else if (![EAGLContext setCurrentContext:aContext])
        NSLog(@"Failed to set ES context current");
    
	self.context = aContext;
	[aContext release];
	
    [(EAGLView *)self.view setContext:context];
    [(EAGLView *)self.view setFramebuffer];
    
    if ([context API] == kEAGLRenderingAPIOpenGLES2)
        [self loadShaders];
    
    animating = FALSE;
    animationFrameInterval = 1;
    self.displayLink = nil;
}

赤字部分でES2があればES2用のコンテキストを作成して、作れなければES1用のコンテキストを作成しています。
赤字部分を次の1行だけに変更

  EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 ];

これで ES1のコンテキストが必ず作成されます。


drawFrameが描画ルーチン

 - (void)drawFrame
{
    [(EAGLView *)self.view setFramebuffer];
    
      (略)

    if ([context API] == kEAGLRenderingAPIOpenGLES2)
    {
        // Use shader program.
        glUseProgram(program);
        
        // Update uniform value.
        glUniform1f(uniforms[UNIFORM_TRANSLATE], (GLfloat)transY);
        transY += 0.075f;	
        
        // Update attribute values.
        glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
        glEnableVertexAttribArray(ATTRIB_VERTEX);
        glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, 1, 0, squareColors);
        glEnableVertexAttribArray(ATTRIB_COLOR);
        
        // Validate program before drawing. This is a good check, but only really necessary in a debug build.
        // DEBUG macro must be defined in your debug configurations if that's not already the case.
#if defined(DEBUG)
        if (![self validateProgram:program])
        {
            NSLog(@"Failed to validate program: %d", program);
            return;
        }
#endif
    }
    else
    {

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0f, (GLfloat)(sinf(transY)/2.0f), 0.0f);
        transY += 0.075f;
        
        glVertexPointer(2, GL_FLOAT, 0, squareVertices);
        glEnableClientState(GL_VERTEX_ARRAY);
        glColorPointer(4, GL_UNSIGNED_BYTE, 0, squareColors);
        glEnableClientState(GL_COLOR_ARRAY);
   
    }
    
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    
    [(EAGLView *)self.view presentFramebuffer];
}

赤字部分が ES2用のコード、緑字部分が ES1用のコードです。
このままでもその都度判定して、ES1用のコードが動くようになりますが、そもそもES2用のコードはつかわないので判定と赤字部分は消しても良いでしょう。

 - (void)drawFrame
{
    [(EAGLView *)self.view setFramebuffer];
    
      (略)
        

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0f, (GLfloat)(sinf(transY)/2.0f), 0.0f);
    transY += 0.075f;
        
    glVertexPointer(2, GL_FLOAT, 0, squareVertices);
    glEnableClientState(GL_VERTEX_ARRAY);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, squareColors);
    glEnableClientState(GL_COLOR_ARRAY);
   
   
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    
    [(EAGLView *)self.view presentFramebuffer];
}

これでSDK3.x用に書かれた書籍の情報もそのまま使えるんじゃないでしょうか。
私もこれから勉強です。