メモ代わり

Feed Rss

OpenGL ES2 の GLSL 準備

07.05.2011, know how, by .

シェーダ生成手順

GLES2 では固定描画機能が無くなり、シェーダプログラムを用意する必要があります。また、 OpenGL の特徴として、ドライバ実装がメーカー毎にザルなので僅かでも API の呼び出し順序やパラメータが違っていると正しく動作しないことがあります。

大まかな流れは、バーテックスシェーダ生成、フラグメントシェーダ生成、バーテックスシェーダへの引数設定、リンク。となります。


GLuint vs; // vertex shader
GLuint fs; // fragment shader 
GLuint po; // program object


const char *vs_program;
const char *fs_program;

GLint compile_status;

glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs,1,&vs_program,NULL);
glCompileShader(vs);
glGetShaderiv(vs,GL_COMPILE_STATUS,&compile_status);
if(!compile_status);----err

glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs,1,&fs_program,NULL);
glCompileShader(fs)
glGetShaderiv(fs,GL_COMPILE_STATUS,&compile_status);
if(!compile_status);----err

po=glCreateProgram
glAttachShader(po,vs);
glAttachShader(po,fs);

glBindAttribLocation(po,0,"in_position");
glBindAttribLocation(po,1,"in_normal");
glBindAttribLocation(po,2,"in_uv");

glLinkProgram(po)

GLint link_status;
glGetProgramiv(po,GL_LINK_STATUS,&link_status);
if(!link_status);----err

先に述べたような順に実行します。

ポイント

まず重要なのはエラー処理です。各ポイントでのエラーは当然実行時に出る事になります。シェーダ自体は非常に小さなプログラムですが、アプリケーション内に文字列としてプログラムを用意している場合は、ここでしかコンパイルエラーを受け取れません。エラー内容は次のようにして取り出せます。

int log_length, chars_written;
glGetShaderiv(vs, GL_INFO_LOG_LENGTH, &log_length);
char *info_log = new char[log_length];
glGetShaderInfoLog(vs, log_length, &chars_written, info_log);
....
delete[]info_log;

info_log にエラー内容が含まれているので、ちゃんと見るようにしましょう。

次に glBindAttribLocation です。バーテックスシェーダの値と後に設定する頂点配列内での位置の関連付けをします。 HLSL 内での float3 in_position:POSITION; とするのとは違い、 API から設定します。また glCreateProgram と glLinkProgram 間でなくてはなりません。

シェーダコンパイラには複数の文字列を設定できるようですが、あまり使う機会はないでしょう。適切な文字列を処理できるコンテナがあればそちらを利用し、文字列や定数などを事前に連結してしまうのが良いと思います。

後始末

glDeleteProgram(po);
glDeleteShader(fs);
glDeleteShader(vs);

以上です。