blog

OpenGL ESの単純な場合:GLKitは画像をロードする

まず、OpenGL ESとGLKitフレームワークに慣れるための簡単なケースを通して。 あなたは、これは単純な画像表示であることがわかりますが、使用して実現することができますが、今日は画像のレンダリン...

May 8, 2020 · 7 min. read
シェア

OpenGL ESとGLKitフレームワークに慣れるために、簡単な例から始めましょう。

その効果を以下に示します:

これはUIImageViewを使って実現できる単純なイメージ表示ですが、今日はGLKitを使ったイメージレンダリングについて説明します。

準備

  • ViewController.hファイルにGLKitフレームワークのヘッダーファイルをインポートします。#import <GLKit/GLKit.h>
  • ViewController.mファイルにOpengl ES関連のヘッダーファイルをインポートします:#import <OpenGLES/ES3/gl.h> #import <OpenGLES/ES3/glext.h>
  • ローカルイメージのインポート

実装フローチャート

フローの具体的な実装

ヘッダファイルの読み込み

#import <OpenGLES/ES3/gl.h> #import <OpenGLES/ES3/glext.h>

グローバル変数の宣言

{
 EAGLContext *context;
 GLKBaseEffect *cEffect;
}

setUpConfig

  1. コンテキストの初期化
  2. 現在のコンテキストの設定
  3. GLKViewの取得、コンテキストの設定
  4. ビューが作成するレンダーバッファの設定
  5. 東京カラーの設定

GLKViewによるカラーバッファと深度バッファの設定

drawableColorFormat: カラーバッファのフォーマット

OpenGL ESには、画面に表示される色を保存するためのバッファがあります。そのプロパティを使用して、バッファ内の各ピクセルのカラーフォーマットを設定できます。

  • GLKViewDrawableColorFormatRGBA8888 = 0、デフォルト。バッファ内の各ピクセルの最小成分は8ビットを使用します。

  • GLKViewDrawableColorFormatRGB565, あなたのAPPがより小さい色の範囲を許す場合、これを設定してください。アプリが消費するリソースが少なくなります。

  • GLKViewDrawableColorFormatSRGBA8888

drawableDepthFormat: 深度バッファのフォーマット

  • GLKViewDrawableDepthFormatNone = 0, 深度バッファが全くないことを意味します。
  • GLKViewDrawableDepthFormat16,
  • GLKViewDrawableDepthFormat24,
-(void)setUpConfig{
 //コンテキストの初期化
 /*
 EAGLContext これはApple iOS用のOpenGLESレンダリングレイヤーの実装である。.
 kEAGLRenderingAPIOpenGLES1 = 1, 固定パイプライン
 kEAGLRenderingAPIOpenGLES2 = 2,
 kEAGLRenderingAPIOpenGLES3 = 3,
 */
 context =[[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES3];
 //コンテキストが正常に作成されたかどうかを判断する
 if (!context) {
 NSLog(@"Create ES context fialed");
 }
 //現在のコンテキストを設定する 複数のコンテキストを作成することは可能だが、現在のコンテキストは1つだけである。
 [EAGLContext setCurrentContext:context];
 //GLKViewを取得する
 GLKView *view =(GLKView *)self.view;
 view.context = context;
 //ビューが作成するレンダーバッファを設定する
 view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
 view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
 //背景色を設定する
 glClearColor(1, 0, 0, 1);
}

setUpVertexData

  1. 頂点配列の設定
  2. 頂点バッファを開く
  3. チャンネルを開く

頂点データの作成

頂点データには、頂点座標と頂点テクスチャが含まれます。

//頂点配列を設定する
 /*
 テクスチャ座標系の値域[0,1];原点は左下隅(0,0);
 つまり、テクスチャイメージの左下、ドットが右上になる。.
 */
 GLfloat vertexData[] = {
 0.5, -0.5, 0.0f, 1.0f, 0.0f, //右下
 0.5, 0.5, 0.0f, 1.0f, 1.0f, //右上
 -0.5, 0.5, 0.0f, 0.0f, 1.0f, //左上
 0.5, -0.5, 0.0f, 1.0f, 0.0f, //右下
 -0.5, 0.5, 0.0f, 0.0f, 1.0f, //左上
 -0.5, -0.5, 0.0f, 0.0f, 0.0f, //左下
 };

頂点バッファを開く

  • 頂点配列:開発者は、drawメソッドを呼び出す際に、頂点データをメモリから直接渡すように関数ポインタを設定することができます。

  • 頂点バッファ: より高性能な方法として、ビデオメモリのブロックをあらかじめ割り当て、そこに頂点 データをあらかじめ格納しておく方法があります。メモリのこの部分は頂点バッファと呼ばれます。

頂点配列データを頂点バッファステップにコピーします:

//頂点バッファを開く
 //1.頂点バッファ識別子IDの作成
 GLuint bufferID;
 glGenBuffers(1, &bufferID);
 //2\. 頂点バッファをバインドする
 glBindBuffer(GL_ARRAY_BUFFER, bufferID);
 //3\. 頂点配列データを頂点バッファにコピーする。
 glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);

チャンネルを開く

iOS のデフォルトでは、パフォーマンス上の理由から、すべてのバー テックスシェーダのアトリビュート変数はオフになっています。これは、頂点データがシェーダ側で利用できないことを意味します。 たとえglBufferDataメソッドを使って頂点データをメモリから頂点バッファにコピーしたとしてもです。

  • チャネルは glEnableVertexAttribArray メソッドによってオープンされている必要があります。アクセス属性を指定します。頂点シェーダが CPU から GPU にコピーされたデータにアクセスでき るようにするためです。
  • 注:GPU 側でデータが見えるかどうか、つまりシェーダがデータを読み出 すことができるかどうかは、対応するアトリビュートが有効になっているかど うかで決まり、glEnableVertexAttribArray の機能によって頂点シェーダが GPU データを読み出せるようになります。

頂点データをメモリにアップロードするメソッド:glVertexAttribPointer

glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)

機能:頂点データをビデオメモリにアップロードするメソッド

 //頂点座標データ
 glEnableVertexAttribArray(GLKVertexAttribPosition);
 /*
 index,変更する頂点属性のインデックス値を指定する 
 size, 一度に読み込む数カラーは4、テクスチャは2である。.)
 type,配列の各構成要素のデータ型を指定する.使用可能な記号定数は GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, とGL_FLOAT,初期値はGL_FLOAT。
 normalized,アクセス時に固定小数点データ値を正規化するかどうかを指定する(GL)_TRUE)または、固定小数点値(GL)に変換するだけである。_FALSE)
 stride,連続する頂点属性間のオフセットを指定する。0を指定すると、頂点アトリビュートは密接に並んでいるかのように解釈される。初期値は0である。
 ptr配列の最初の頂点プロパティの第1成分へのポインタを指定する.初期値は0である。
 */
 glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 0);
 //テクスチャ座標データ
 glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
 glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 3);

setUpTexture

  • テクスチャイメージパスの設定

  • テクスチャパラメータの設定

  • cEffectセットアッププロパティの初期化

    //2.テクスチャパラメータを設定する
    //テクスチャ座標の原点は左下だが、イメージ表示の原点は左上にする。.
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:@(1),GLKTextureLoaderOriginBottomLeft, nil];
    GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
    //3.AppleのGLKitを使ってGLKBaseEffectを提供し、シェーダー作業を完了させる。
    cEffect = [[GLKBaseEffect alloc]init];
    cEffect.texture2d0.enabled = GL_TRUE;
    cEffect.texture2d0.name = textureInfo.name;
    

    }

GLKViewDelegate

図面ビューの内容

  • カラーバッファのクリア

  • 描画準備

  • 描き始め

    // ビューの内容を描画する /* GLKViewオブジェクトは、そのOpenGL ESコンテキストを現在のコンテキストにし、そのフレームバッファをOpenGL ESレンダーコマンドのターゲットにバインドします。そして、デリゲートメソッドはビューの内容を描画しなければなりません。*/

    }

イメージの引き伸ばし問題

viewDidLoadで上記のメソッドを一度呼び出し、プログラムを実行すると、上記のようなエフェクトイメージが表示されますが、設定された座標が正方形で、イメージが引き伸ばされてしまいます。

この理由は、ビューポートのアスペクト比による伸縮ですが、これは透視投影行列を設定することで解決できます。繰り返しになりますが、透視投影の表示範囲のため、携帯電話の画面上でより適切なサイズで表示するには、頂点を4.0単位後ろにパンする必要があります。

 CGFloat aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height);
 GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(60.0), aspect, 0.1, 100.0);
 cEffect.transform.projectionMatrix = projectionMatrix;
 GLKMatrix4 modelviewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, -5.0);
 cEffect.transform.modelviewMatrix = modelviewMatrix;

どう動くか見てみましょう。

デモ用アドレス

02-OpenGL-ES-ロードイメージ

Read next