I. GLSL
GLSLはOpenGL Shading Languageの略で、OpenGLでシェーディングをプログラミングするために使用される言語です。
GLSLはグラフィックスカードのGPU上で実行され、レンダリングパイプラインの固定部分を置き換え、ビュー遷移など、レンダリングパイプラインの異なるレベルをプログラム可能にします。GLSLのシェーダコードは2つの部分に分かれています:頂点シェーダとフラグメント、時にはジオメトリシェーダ。例えば、ビュー遷移、投影遷移などです。GLSLのシェーダコードは、頂点シェーダとフラグメントの2つに分かれており、ジオメトリシェーダの場合もあります。GLSLは、アセンブリ言語やハードウェア仕様言語のような複雑さを避けるため、C言語を基本的な高レベルシェーディング言語として使用します。
II. GLSLの共通データ型
GLSLを使う場合、ベクトルや行列、変数など、システムで定義されているデータ型を使うのが一般的です:
ベクトルデータ型
行列データ型
変数格納修飾子
III.GLSL
xcodeでは、コンパイラ自体がGLSLのコンパイルとリンクをサポートしていません。そのため、手動でGLSLファイルを作成し、手動でコンパイルしてアプリケーションにリンクする必要があります。
GLSLファイルの作成はとても簡単で、xcodeで2つの空のファイルを作成し、サフィックスを変更するだけです。その後、頂点シェーダファイルとスライスシェーダファイルが作成されます。通常、サフィックスには vsh/fsh が使われますが、これは開発者が定義できます。
GLSLデータ修正タイプ
GLSLには3種類のデータ修飾子があります:
- uniform
- attribute
- さまざま(後の章で説明)
uniform: 主に、アプリコードから頂点シェーダ変数とスライ スシェーダ変数を渡すために使用します。シェーダファイルでは、この修飾子を持つ変数だけが使用され、変更を通りません。
属性: アプリコードから渡される頂点シェーダでのみ使用でき、スライ スシェーダには直接使用できません。一般的に、頂点データ、テクスチャ左などを変更するために使用されます。
varying: varying 変数は、バーテックスシェーダとフラグメントシェーダ 間のデータ転送に使用されます。通常、バーテックスシェーダが varying 変数の値を変更し、フラグメントシェーダが varying 変数の値を使用します。したがって、vari varying 変数の宣言は、バーテックスシェーダとフラグメントシェーダの間で一貫していなければなりません。
IV. GLSLを使ったイメージの読み込み
前回の記事ではGLKitを使ってイメージを読み込みました。ここではGLSLを使ってイメージを読み込みます。
vsh と fsh
まず、vsh ファイルと fsh ファイルを書きましょう。 vsh バーテックスシェーダには、スライスシェーダに渡す必要があるバー テックスデータ、テクスチャデータ、テクスチャデータが必要です:
attribute vec4 position;//頂点座標
attribute vec2 textCoordinate;//テクスチャ座標
varying lowp vec2 varyTextCoord;//テクスチャ座標の転送
void main() {
varyTextCoord = textCoordinate;//受け渡し処理
gl_Position = position;//に頂点データをコミットする。
}
次に fsh スライスシェーダーファイルです:
precision highp float;//浮動小数点精度を定義する
varying lowp vec2 varyTextCoord;//頂点シェーダからテクスチャ座標を渡す。
uniform sampler2D colorMap;//
int main() {
//texture2D(テクスチャ、テクスチャ座標)、カラー値を返す
gl_FragColor = texture2D(colorMap, varyTextCoord);//カラー値を送信する
}
GLSLのコンパイルとリンク
コンパイルとリンクは主に6つのステップに分かれています:
- ピースワイズシェーダオブジェクトで頂点シェーダオブジェクトを作成
- 各シェーダーオブジェクトにリンクされたソースコード
- シェーダーオブジェクトのコンパイル
- プログラムオブジェクトの作成
- プログラム・オブジェクトにリンクされたコンパイル済みシェーダー・オブジェクト
- 連結プログラムオブジェクト
GLSL関連関数
プログラムで使用される機能は以下の通りです:
GLuint glCreateShader(GLenum type)
シェーダーオブジェクトハンドルの作成
- type: シェーダタイプ
- return: シェーダオブジェクトハンドルを返します。
void glDeleteShader(GLuint shader)
シェーダーオブジェクトハンドルの削除
- shader: 削除するシェーダーオブジェクトへのハンドル
void glShaderSource(GLuint shader, GLSize count, const GLChar * string, const GLint * length)
ソースコードとシェーダーオブジェクトのリンク
- shader: シェーダーオブジェクトハンドル
- count: シェーダー・ソース文字列の数
- string: カウント数を保持するシェーダーソース文字列の配列へのポインタ。
- length: 各シェーダー文字列のサイズを保持する整数配列へのポインタ。
void glCompileShader(GLuint shader)
シェーダーオブジェクトのコンパイル
- shader: コンパイルされるシェーダオブジェクト
GLuint glCreateProgram()
プログラムオブジェクトの作成
- return: 実行プログラムオブジェクトのハンドルを返します。
void glDeleteProgram(GLuint program)
プログラムオブジェクトの作成
- program: 削除されたプログラム・オブジェクトのハンドル
void glAttachShader(GLuint programme, GLuint shader)
シェーダーとプログラミングのリンク
- program: プログラム・オブジェクトへのハンドル
- shader: シェーダーオブジェクト
void glDetachShader(GLuint program)
切断
- program : プログラムオブジェクトへのハンドル
- shader: 切断されたアプリケーションを指すシェーダーオブジェクトへのハンドル。
void glLinkProgram(GLuint program)
リンク手順
- program: プログラム・オブジェクトへのハンドル
*
リンクが成功したかどうかの確認
- program : プログラムオブジェクトへのハンドル
- pname: 情報を取得するパラメータ
- params: クエリ結果の整数が格納される場所へのポインタ。
シェーダーのコンパイルとリンク
カスタムメソッドはvsh/fshファイルを読み込み、ソースコードをシェーダにアタッチし、コンパイルします:
//ソースコードをシェーダにリンクし、コンパイルする。
- (void)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file {
//パスを読み込む
NSString *content = [NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil];
const GLchar * source = (GLchar *)[content UTF8String];
//対応するシェーダーを作成する。
*shader = glCreateShader(type);
//ソースコードをシェーダにアタッチする。
glShaderSource(*shader, 1, &source, NULL);
//
glCompileShader(*shader);
}
カスタムメソッドを使用してコンパイルメソッドを呼び出し、2つのシェーダーをコンパイルし、プログラムにシェーダーをアタッチしてprogramprogramを返します:
//シェーダーをプログラムにリンクする。
- (GLuint)loaderShaders:(NSString *)vert withFrag:(NSString *)frag {
//頂点、スライスシェーダオブジェクト
GLuint verShader, fragShader;
//program
GLuint program = glCreateProgram();
//頂点シェーダ、ピースワイズシェーダをコンパイルする。
[self compileShader:&verShader type:GL_VERTEX_SHADER file:vert];
[self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:frag];
//プログラムに付属するコンパイル済みシェーダ
glAttachShader(program, verShader);
glAttachShader(program, fragShader);
//シェーダーを削除する
glDeleteShader(verShader);
glDeleteShader(fragShader);
return program;
}
プログラムオブジェクトのリンク
カスタム・メソッドを通して処理されたプログラム・プログラムを取得し、プログラム・オブジェクトをリンクし、リンクが成功したかどうかを判断して使用します。
テクスチャデータを処理した後、テクスチャデータをfsh内部に渡します:
- (void)renderLayer {
// ...(色をクリアし、ビューポート関連を設定する)
//頂点を読む/スライスシェーダ
NSString *vertFile = [[NSBundle mainBundle] pathForResource:@"shaderv" ofType:@"vsh"];
NSString *fragFile = [[NSBundle mainBundle] pathForResource:@"shaderf" ofType:@"fsh"];
self.myPrograme = [self loaderShaders:vertFile withFrag:fragFile];
//プログラムをリンクする
glLinkProgram(self.myPrograme);
//リンクステータスを取得する
GLint linkStatus;
glGetProgramiv(self.myPrograme, GL_LINK_STATUS, &linkStatus);
if (linkStatus == GL_FALSE) {
GLchar message;
glGetProgramInfoLog(self.myPrograme, sizeof(message), 0, &message[0]);
NSString *messageString = [NSString stringWithUTF8String:message];
NSLog(@"Program Link Error: %@", messageString);
return;
}
NSLog(@"Program Link Success!");
//プログラム・オブジェクトへの参照
glUseProgram(self.myPrograme);
// ...(頂点データをセットし、テクスチャ関連をロードする)
//テクスチャを渡す
glUniform1i(glGetUniformLocation(self.myPrograme, "colorMap"), 0);
//
glDrawArrays(GL_TRIANGLES, 0, 6);
//画面にレンダリングする
[self.myContext presentRenderbuffer:GL_RENDERBUFFER];
}





