OpenGL de プログラミング - GLSL編01
現在地メニュー >> GLSL >> GLSL編01
INDEX:GLSL編00 << GLSL編01 >> GLSL編02

目次

GLSLの使用手順


GLSLを使用するには「.cppファイル」で次の事を行う。
  1. シェーダオブジェクトを作成
  2. シェーダファイル(.vertや.frag)を読み込んで、シェーダオブジェクトへ渡す
  3. シェーダオブジェクトをコンパイル
  4. プログラムオブジェクトを作成
  5. プログラムオブジェクトにシェーダプロジェクトを接続する
  6. プログラムオブジェクトをリンクし、使用する事を伝える

【1】:シェーダオブジェクトを作成

シェーダオブジェクトは「glCreateShader」で作成する。

【例】
GLuint vShaderId;
GLuint fShaderId;
… …
//---- 頂点シェーダオブジェクトの作成 ----//
vShaderId = glCreateShader(GL_VERTEX_SHADER););
… …
//---- フラグメントシェーダオブジェクトの作成 ----//
fShaderId = glCreateShader(GL_FRAGMENT_SHADER);
… …
▲返り値は扱うシェーダに割り振られたIDみたいなもの。

【2】:シェーダファイル(.vertや.frag)を読み込んで、シェーダオブジェクトへ渡す


「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)であることを意味する。

【3】:シェーダオブジェクトをコンパイル


「glCompileShader関数」を使う。
【例】
GLuint vShaderId;
ShaderId = glCreateShader(GL_VERTEX_SHADER);
… …
//ソースコードをシェーダオブジェクトに変換
glShaderSource(vShaderId, 1, &vfile,NULL);

glCompileShader(vShaderId);//コンパイル

【4】:プログラムオブジェクトを作成

glCreateProgram関数を使う。

【例】
GLuint programId;
… …
programId = glCreateProgram();

【5】:プログラムオブジェクトにシェーダプロジェクトを接続する


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関数」

【6】:プログラムオブジェクトをリンクし、使用する事を伝える

glLinkProgram関数でリンク、glUseProgram関数で使用する事を伝える。

【例】
GLint linked;
glLinkProgram(programId);//リンクする
glGetProgramiv(programId, GL_LINK_STATUS, &linked);
if(linked == GL_FALSE)
{
	std::cerr << "Link Err.\n";
}

glUseProgram(programId);//プログラム使用を伝える
▲リンクできているかは「glGetProgramiv関数」で確認。

まとめ(GLSLのセットアップ)

【1】〜【6】をまとめると次のようになる。
//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
void main(void)
{
    gl_FragColor= vec4(0.0, 1.0, 0.0, 1.0);
}
【解説】
出力は「gl_FragColor」にいれる。この例では(r,g,b,a)=(0,1,0,1)を入れている。

サンプルコード