最終更新: mikk_ni3_92 2010年02月08日(月) 17:36:50履歴
現在地:メニュー >> GLSL >> GLSL編01
INDEX:GLSL編00 << GLSL編01 >> GLSL編02
GLSLを使用するには「.cppファイル」で次の事を行う。
「fopen」でも、「fstream」でもなんでもいいから
とにかく「.vert」や「.frag」にかかれたソースコードを読み込んで、「char *」に格納する。
そして、「glShaderSource関数」を使ってシェーダオブジェクトに渡す。
【例】
「glCompileShader関数」を使う。
【例】
glAttachShader関数を使う。
【例】
「.vertファイル」で最初に行く関数は「void main(){... ..}」である。
また、出力となる頂点座標は「gl_Position」というvec4変数があるのでそこに入れればよい。
【例】:glsl.vert
「vec4 ftransform()」はGLSLの関数で「固定機能パイプライン」と同様に入力頂点を変換してくれる。
(※GLSL 1.40とGLSL ES 1.0からはサポートされないが,GL_ARB_compatibilityがあれば使える)
この頂点シェーダは
固定機能パイプラインで変換したものを「gl_Position」に格納して、出力としてフラグメントにわたしているだけ。
INDEX:GLSL編00 << GLSL編01 >> GLSL編02
GLSLを使用するには「.cppファイル」で次の事を行う。
- シェーダオブジェクトを作成
- シェーダファイル(.vertや.frag)を読み込んで、シェーダオブジェクトへ渡す
- シェーダオブジェクトをコンパイル
- プログラムオブジェクトを作成
- プログラムオブジェクトにシェーダプロジェクトを接続する
- プログラムオブジェクトをリンクし、使用する事を伝える
シェーダオブジェクトは「glCreateShader」で作成する。
【例】
【例】
GLuint vShaderId; GLuint fShaderId; … … //---- 頂点シェーダオブジェクトの作成 ----// vShaderId = glCreateShader(GL_VERTEX_SHADER);); … … //---- フラグメントシェーダオブジェクトの作成 ----// fShaderId = glCreateShader(GL_FRAGMENT_SHADER); … …▲返り値は扱うシェーダに割り振られたIDみたいなもの。
「fopen」でも、「fstream」でもなんでもいいから
とにかく「.vert」や「.frag」にかかれたソースコードを読み込んで、「char *」に格納する。
そして、「glShaderSource関数」を使ってシェーダオブジェクトに渡す。
【例】
GLuint vShaderId; … … //.vertファイルの中身を全て読み込む std::ifstream inputFile1("glsl.vert"); std::istreambuf_iterator<char> vdataBegin(inputFile1); std::istreambuf_iterator<char> vdataEnd; std::string fileData1(vdataBegin,vdataEnd); const char *vfile = fileData1.c_str(); //ソースコードをシェーダオブジェクトに変換 glShaderSource(vShaderId, 1, &vfile,NULL);▲NULLを入れると文字列がNULL終端(null terminated)であることを意味する。
「glCompileShader関数」を使う。
【例】
GLuint vShaderId; ShaderId = glCreateShader(GL_VERTEX_SHADER); … … //ソースコードをシェーダオブジェクトに変換 glShaderSource(vShaderId, 1, &vfile,NULL); glCompileShader(vShaderId);//コンパイル
glAttachShader関数を使う。
【例】
GLuint vShaderId; GLuint fShaderId; GLuint programId; … … //---- 頂点シェーダオブジェクトの作成 ----// vShaderId = glCreateShader(GL_VERTEX_SHADER);); … … //---- フラグメントシェーダオブジェクトの作成 ----// fShaderId = glCreateShader(GL_FRAGMENT_SHADER); … … //プログラムオブジェクトの作成 programId = glCreateProgram(); glAttachShader(programId,vShaderId); glAttachShader(programId,fShaderId); … …▲接続を外すのは、「glDetachShader関数」
glLinkProgram関数でリンク、glUseProgram関数で使用する事を伝える。
【例】
【例】
GLint linked; glLinkProgram(programId);//リンクする glGetProgramiv(programId, GL_LINK_STATUS, &linked); if(linked == GL_FALSE) { std::cerr << "Link Err.\n"; } glUseProgram(programId);//プログラム使用を伝える▲リンクできているかは「glGetProgramiv関数」で確認。
【1】〜【6】をまとめると次のようになる。
あとはプログラムを動かせば「.vertファイル」「.fragファイル」に処理が進んでいく。
//GLSLのセットアップ void setUpGLSL() { //---- 頂点シェーダオブジェクトの作成 ----// vShaderId = glCreateShader(GL_VERTEX_SHADER); //.vertファイルの中身を全て読み込む std::ifstream inputFile1("glsl.vert"); std::istreambuf_iterator<char> vdataBegin(inputFile1); std::istreambuf_iterator<char> vdataEnd; std::string fileData1(vdataBegin,vdataEnd); const char *vfile = fileData1.c_str(); //ソースコードをシェーダオブジェクトに変換 glShaderSource(vShaderId, 1, &vfile,NULL); glCompileShader(vShaderId);//コンパイル //---- フラグメントシェーダオブジェクトの作成 ----// fShaderId = glCreateShader(GL_FRAGMENT_SHADER); //.fragファイルの中身を全て読み込む std::ifstream inputFile2("glsl.frag"); std::istreambuf_iterator<char> fdataBegin(inputFile2); std::istreambuf_iterator<char> fdataEnd; std::string fileData2(fdataBegin,fdataEnd); const char *ffile = fileData2.c_str(); //ソースコードをシェーダオブジェクトに変換 glShaderSource(fShaderId, 1, &ffile,NULL); glCompileShader(fShaderId);//コンパイル //プログラムオブジェクトの作成 programId = glCreateProgram(); glAttachShader(programId,vShaderId); glAttachShader(programId,fShaderId); GLint linked; glLinkProgram(programId); glGetProgramiv(programId, GL_LINK_STATUS, &linked); if(linked == GL_FALSE) { std::cerr << "Link Err.\n"; } glUseProgram(programId); }
あとはプログラムを動かせば「.vertファイル」「.fragファイル」に処理が進んでいく。
「.vertファイル」で最初に行く関数は「void main(){... ..}」である。
また、出力となる頂点座標は「gl_Position」というvec4変数があるのでそこに入れればよい。
【例】:glsl.vert
//頂点シェーダ void main(void) { gl_Position = ftransform(); }【解説】
「vec4 ftransform()」はGLSLの関数で「固定機能パイプライン」と同様に入力頂点を変換してくれる。
(※GLSL 1.40とGLSL ES 1.0からはサポートされないが,GL_ARB_compatibilityがあれば使える)
この頂点シェーダは
固定機能パイプラインで変換したものを「gl_Position」に格納して、出力としてフラグメントにわたしているだけ。
「.fragファイル」で最初に行く関数も「void main(){... ..}」である。
【例】:glsl.frag
出力は「gl_FragColor」にいれる。この例では(r,g,b,a)=(0,1,0,1)を入れている。
【例】:glsl.frag
void main(void) { gl_FragColor= vec4(0.0, 1.0, 0.0, 1.0); }【解説】
出力は「gl_FragColor」にいれる。この例では(r,g,b,a)=(0,1,0,1)を入れている。