忍者ブログ
  • 2024.10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 2024.12
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

【2024/11/22 19:16 】 |
OpenGL周りのコード
OpenGLを使用する際の大まかな流れ。
最低限必要なことだけ抜き出しています。
エラーチェックなどは一切省いてあります。

XCodeで、OpenGLプロジェクトとして作成すると自動で作られるコードです。


ViewController
シェーダ周りの初期化を行う。
シェーダの中身に何が書いてあるか、ゲーム側でどう描画するかなどは関知しない。


-(void) awakeFromNib
{
[self loadShaders];
}

-(BOOL) loadShaders
{
//プログラムの生成
GLuint program = glCreateProgram();

//シェーダの生成
GLuint vertShader, fragShader;
[self compileShader:&vertShader type:GL_VERTEX_SHADER file:@"Shader.vsh"];
[self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:@"Shader.fsh"];

//シェーダをアタッチする
glAttachShader(program, vertShader);
glAttachShader(program, fragShader);

//プログラムをリンクする
[self linkProgram:program];

//シェーダを解放
glDeleteShader(vertShader);
glDeleteShader(fragShader);
}

-(BOOL) compileShader:(GLuint*)shader type:(GLenum)type file:(NSString*)file
{
//シェーダソースを取得
const GLchar *source = (GLchar *)[[NSString stringWithContentsOfFile:file] UTF8String];

//シェーダ生成
*shader = glCreateShader(type);

//シェーダソースを渡す
glShaderSource(*shader, 1, &source, NULL);
//引数:シェーダハンドル、ソース数、ソース文字列へのポインタ配列、
//ソース文字数の配列(NULLの場合、文字列はすべてNULLで終わると仮定する)

//コンパイル
glCompileShader(*shader);
}

-(BOOL) linkProgram:(GLuint)prog
{
glLinkProgram(prog);
}


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

glClearColor(0.5f, 0.5f, 1.0f, 1.0f); //わざと黒でない中間色にしておく
glClear(GL_COLOR_BUFFER_BIT);

glUseProgram(program);

//ゲームの描画処理
draw();

[(EAGLView*)self.view presentFramebuffer];
}




GLDraw
ゲーム側。
シェーダの中身を記述する。



//シェーダ関連変数の置き場
struct UserData{
//プログラム
GLuint programObject;

//アトリビュート
GLint positionLoc;
GLint colorLoc;
GLint texCoordLoc;

//サンプラー
GLint samplerLoc;

//テクスチャ
GLuint textureId[16];
};

//シェーダ変数の取得と、テクスチャ関係の初期化
void initProgram(GLuint program)
{
userData = new UserData;

userData->programObject = program;
userData->positionLoc = glGetAttribLocation( program, "position");
userData->colorLoc = glGetAttribLocation( program, "color");
userData->texCoordLoc = glGetAttribLocation( program, "texCoord");
userData->samplerLoc = glGetUniformLocation( program, "s_texture");

//テクスチャのアライメント指定. グローバルな指定なので、ここで行う
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

//テクスチャ生成
glGenTextures(16, &userData->textureId[0]);
}

//テクスチャの登録
bool registerTexture(NSString *file, GLuint *hTexture)
{
GLuint textureId = userData->textureId[0];

//テクスチャをターゲットにバインドして有効化
glBindTexture(GL_TEXUTRE_2D, textureId);

//テクスチャデータを取得
GLubyte *bits;
GLfloat width, height;
loadTextureFromFile(file, &bits, &width, &height);

//テクスチャデータをロード
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bits);

//フィルタリングモードをセット
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

//後始末
glBindTexture(GL_TEXTURE_2D, 0);

*hTexture = textureId;

return true;
}

//テクスチャ描画
void drawTexture(GLuint textureId, GLfloat *vertices, GLfloat *texCoord)
{
//座標
glVertexAttribPointer(userData->positionLoc, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(userData->positionLoc); //頂点配列頂点属性を使用する

//色
glVertexAttribPointer(userData->texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(userData->texCoordLoc); //頂点配列頂点属性を使用する

//テクスチャをバインド
glActiveTexture(GL_TEXTURE0); //カレントのテクスチャユニットを設定
glBindTexture(GL_TEXTURE_2D, texutreId); //カレントのテクスチャユニットにテクスチャをバインド

//サンプリング対象にするテクスチャユニットのインデックスを指定
glUniform1i(userData->samplerLoc, 0);
//glActiveTexture(GL_TEXTURE**)と同じ値にする

//インデックスバッファ
GLushort indices[] = { 0,1,2, 0,2,3};

//描画
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
}

//プリミティブの描画
void drawRectFull(GLfloat *vertices, Color color)
{
//座標
glEnableVertexAttribArray(userData->positionLoc);
glVertexAttribPointer(userData->positionLoc, 2, GL_FLOAT, GL_FALSE, 0, vertices);

//色指定
glEnableVertexAttribArray(userData->colorLoc);
glVertexAttrib4f(userData->colorLoc, color.r, color.g, color.b, color.a);

//描画
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}



テクスチャを使用してもしなくても描画できるように一応してある。
その場合、シェーダの中でどちらの色を使うか(指定した頂点カラーそのままなのか、テクスチャを使うのか)を見分ける必要がある。
そのためにアトリビュートをもう一つ使うようなのはきれいじゃない。

カラー減算する仕組みを乗せておき、常時真っ白いテクスチャを用意しておくようにするのがスマートではないかと思う。
PR
【2011/01/23 15:59 】 | 開発日記 | 有り難いご意見(0) | トラックバック()
<<可変引数とPOD | ホーム | iPadアプリにする方法>>
有り難いご意見
貴重なご意見の投稿














虎カムバック
トラックバックURL

<<前ページ | ホーム | 次ページ>>