シェーダ生成手順
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);
以上です。