OpenGL ESテンプレート(10)~GLFunViewControllerクラス(9)

2012. 02. 14
19)loadShadersメソッド

- (BOOL)loadShaders
{
    GLuint vertShader, fragShader;
    NSString *vertShaderPathname, *fragShaderPathname;

    // Create shader program.

    program = glCreateProgram();

    // Create and compile vertex shader.

    vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader"
     ofType:@"vsh"];
    if (![self compileShader:&vertShader type:GL_VERTEX_SHADER
     file:vertShaderPathname])
    {
        NSLog(@"Failed to compile vertex shader");
        return FALSE;
    }

    // Create and compile fragment shader.

    fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader"
     ofType:@"fsh"];
    if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER
     file:fragShaderPathname])
    {
        NSLog(@"Failed to compile fragment shader");
        return FALSE;
    }

    // Attach vertex shader to program.
    glAttachShader(program, vertShader);

    // Attach fragment shader to program.
    glAttachShader(program, fragShader);

    // Bind attribute locations.
    // This needs to be done prior to linking.

    glBindAttribLocation(program, ATTRIB_VERTEX, "position");
    glBindAttribLocation(program, ATTRIB_COLOR, "color");

    // Link program.
    if (![self linkProgram:program])
    {
        NSLog(@"Failed to link program: %d", program);

        if (vertShader)
        {
            glDeleteShader(vertShader);
            vertShader = 0;
        }
        if (fragShader)
        {
            glDeleteShader(fragShader);
            fragShader = 0;
        }
        if (program)
        {
            glDeleteProgram(program);
            program = 0;
        }

        return FALSE;
    }

    // Get uniform locations.
    uniforms[UNIFORM_TRANSLATE] = glGetUniformLocation(program, "translate");

    // Release vertex and fragment shaders.
    if (vertShader)
        glDeleteShader(vertShader);
    if (fragShader)
        glDeleteShader(fragShader);

    return TRUE;
}

@end

loadShadersメソッドでは、以下の処理を行っています。

・シェーダプログラムの生成
・頂点とフラグメントシェーダの生成とコンパイル
・頂点とフラグメントシェーダをプログラムへアタッチ
・属性場所のバインド
・プログラムのリンク
・uniform変数の場所の取得
・頂点とフラグメントシェーダの解放

シェーダプログラムの生成)

最初にglCreateProgramでプログラムオブジェクトprogramを生成します。

glCreateProgram

プログラムオブジェクトを生成します。

GLuint glCreateProgram(void);

glCreateProgramは空のプログラムオブジェクトを生成し、参照できるように非ゼロ値を返します。

プログラムオブジェクトは、シェーダオブジェクトをアタッチすることができるオブジェクトです。

これはプログラムを生成するためにリンクされるシェーダオブジェクトを指定する機構を提供します。

また、(例えば、頂点シェーダとフラグメントシェーダ間の互換性をチェックするなど)プログラムの生成に使用されるシェーダの互換性をチェックするための手段も提供します。

プログラムオブジェクトの一部として不要になった時は、シェーダオブジェクトをデタッチすることができます。

glCompileShaderでシェーダオブジェクトのコンパイルが成功し、glLinkProgramでプログラムオブジェクトのリンクが成功し、glAttachShaderでシェーダオブジェクトのアタッチが成功することによって、プログラムオブジェクト内で一つ以上の実行可能オブジェクトが生成されます。

これらの実行可能オブジェクトは、glUseProgramを呼び出した時に、現在の状態の一部となります。

プログラムオブジェクトは、glDeleteProgramを呼び出すことによって削除することができます。

プログラムオブジェクトに関連付けられているメモリは、コンテキストの現在のレンダリング状態の一部でなくなった時に削除されます。

テクスチャオブジェクトと同様に、プログラムオブジェクトの名前空間はコンテキストのセット間で共有されることがあり、その場合コンテキストのサーバ側と同じアドレス空間を共有します。

名前空間がコンテキスト間で共有されている場合、全てのアタッチされているオブジェクトとそれらのアタッチされているオブジェクトに関連するデータも、同様に共有されます。

アプリケーションは、オブジェクトが異なる実行スレッドからアクセスする場合に、APIの呼び出し間での同期を提供する責任があります。

プログラムオブジェクトの生成でエラーが発生した場合、この関数は0を返します。

頂点シェーダの生成とコンパイル)

mainBundleメソッドでアプリケーションのバンドルを指定し、pathForResource:ofType:で頂点シェーダのプログラムファイルShader.vshのパスを取得します。

取得したファイルパスを使用してcompileShader:type:file:メソッドを呼び出し、頂点シェーダプログラムをコンパイルします。

コンパイルに失敗した場合はNSLogでエラーログを出力します。

フラグメントシェーダの生成とコンパイル)

頂点シェーダと同様に、フラグメントシェーダのプログラムファイルShader.fshをコンパイルします。

プログラムへの頂点シェーダのアタッチ)

glAttachShaderでプログラムオブジェクトに頂点シェーダオブジェクトをアタッチします。

glAttachShader

プログラムオブジェクトにシェーダオブジェクトをアタッチします。

void glAttachShader(GLuint program, GLuint shader);

実行可能オブジェクトを生成するには、一緒にリンクするもののリストを指定する方法が必要になります。

プログラムオブジェクトはこの機構を提供します。

プログラムオブジェクト内で一緒にリンクされるシェーダは、最初にプログラムオブジェクトにアタッチする必要があります。

glAttachShaderは、programによって指定されたプログラムオブジェクトに、shaderによって指定されたシェーダオブジェクトをアタッチします。

これは、シェーダがprogram上で実行されるリンク操作内に含まれることを示します。

シェーダオブジェクト上で実行できる全ての操作は、シェーダオブジェクトがプログラムオブジェクトにアタッチされているかどうかに関わらず有効です。

これは、シェーダオブジェクトがソースコードを読み込む前、またはシェーダオブジェクトがコンパイルされる前に、プログラムオブジェクトにシェーダオブジェクトがアタッチすることを許容しています。

同じタイプの複数のシェーダオブジェクトが、単一のプログラムオブジェクトにアタッチすることはできません。

しかし単一のシェーダオブジェクトが一つ以上のプログラムオブジェクトにアタッチすることはできます。

プログラムオブジェクトにアタッチされていたシェーダオブジェクトが削除された場合、削除フラグが立てられますが、アタッチされていた全てのプログラムオブジェクトから、glDetachShaderを呼び出すことによってデタッチされるまでは削除されません。

programまたはshaderが、OpenGLによって生成された値でない場合、GL_INVALID_VALUEが発生します。

programがプログラムオブジェクトでない場合、GL_INVALID_OPERATIONが発生します。

shaderがシェーダオブジェクトでない場合、GL_INVALID_OPERATIONが発生します。

shaderが既にprogramにアタッチされている、またはshaderと同じタイプの他のシェーダオブジェクトが既にprogramにアタッチされている場合、GL_INVALID_OPERATIONが発生します。

program:シェーダオブジェクトをアタッチするプログラムオブジェクトを指定します。

shader:アタッチするシェーダオブジェクトを指定します。

プログラムへのフラグメントシェーダのアタッチ)

頂点シェーダと同様に、プログラムオブジェクトにフラグメントシェーダオブジェクトをアタッチします。

属性場所のバインド)

この処理はリンクの前に行う必要があります。

glBindAttribLocationで、プログラムオブジェクト内にあるシェーダプログラムのattribute変数と、drawFrameメソッドで定義したOpenGL ESの頂点配列のインデックスを関連付けをし、頂点配列データの受け渡しができるようにします。

glBindAttribLocation

名付けられたattribute変数で汎用頂点属性インデックスを関連付けします。

void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name);

glBindAttribLocationは、汎用頂点属性インデックスでprogramによって指定されたプログラムオブジェクト内のユーザ定義attribute変数に関連付けるために使用されます。

ユーザ定義attribute変数は、name内のヌル終端文字列として渡されます。

この変数にバインドする汎用頂点属性インデックスは、indexによって指定されます。

programが現在の状態の一部の場合、汎用頂点属性indexを介して提供された値は、nameによって指定されたユーザ定義attribute変数の値に変更されます。

nameが行列attribute変数を参照している場合、indexは行列の最初の列を参照します。

他の行列の列は、その後にタイプmat2の行列の場合はindex+1、タイプmat3の行列の場合はindex+1とindex+2、そしてタイプmat4の行列の場合はindex+1、index+2、index+3の場所へ自動的にバインドされます。

このコマンドは、0からGL_MAX_VERTEX_ATTRIBS -1までの番号付けをした汎用変数ではなく、attribute変数のための記述的な名前を使用した頂点シェーダを作成できます。

各汎用属性インデックスに送信される値は、ちょうど色、法線、頂点位置などの標準的な頂点属性と同じように、現在の状態の一部です。

異なるプログラムオブジェクトがglUseProgramを呼び出すことによって現在作成している場合、汎用頂点属性は同じ値がindexにバインドされている新しいプログラムオブジェクト内の属性によって観測されるような方法で追跡されます。

attribute変数名から汎用属性インデックスのプログラムオブジェクトのバインディングは、glBindAttribLocationを呼び出すことによって、いつでも明示的に割り当てることができます。

属性のバインディングは、glLinkProgramが呼び出されるまで影響しません。

プログラムオブジェクトがリンクに成功した後、汎用属性のインデックス値は次のリンクコマンドが発行されるまで固定されたままになり(その値を照会することができるようになり)ます。

アプリケーションは、必要な時に自動的にバインドするものとしており、このコマンドを使用して標準OpenGL頂点属性のいずれかをバインドすることを許可していません。

プログラムオブジェクトがリンクされた後に発生する属性のバインディングは、次の機会にプログラムオブジェクトがリンクされるまで影響しません。

glBindAttribLocationは、頂点シェーダオブジェクトが指定されたプログラムオブジェクトにバインドされる前に呼び出すことができます。

これは頂点シェーダ内で使用されることが無いattribute変数名に、汎用頂点属性インデックスをバインドすることが許可されています。

nameが以前にバインドされている場合、その情報は失われます。

したがって、複数のインデックスにユーザ定義attribute変数をバインドすることはできませんが、同じインデックスに複数のユーザ定義attribute変数をバインドすることはできます。

アプリケーションは、同じ汎用頂点属性インデックスに一つ以上のユーザ定義attribute変数をバインドすることができます。

これはエイリアシングと呼ばれ、エイリアス属性の一つが実行可能プログラム内でアクティブな場合、またはシェーダを介していないパスが同じ場所に属性エイリアスのセットの一つ以上の属性を消費しない場合のみ許可されます。

コンパイラとリンカはエイリアシングが行われず、エイリアシングの無い状態でのみ動作する最適化を使用して解放すると想定して許可しています。

OpenGLの実装は、エイリアシングを検出するエラーチェックをする必要はありません。

なぜなら標準属性をバインドする方法が無いため、(汎用属性0を除いて)通常のもので汎用属性をエイリアスにすることは不可能です。

明示的にバインドされていないアクティブな属性は、glLinkProgramが呼び出された時に、リンカによってバインドされます。

場所の割り当ては、glGetAttribLocationを呼び出すことによって照会することができます。

glBindAttribLocationが呼び出された時、OpenGLはname文字列をコピーするので、アプリケーションは関数が帰って来た直後にname文字列のコピーを解放することができます。

indexがGL_MAX_VERTEX_ATTRIBS以上の場合、GL_INVALID_VALUEが発生します。

nameが予約接頭辞『gl_』で始まっていない場合、GL_INVALID_OPERATIONが発生します。

programがOpenGLによって生成された値でない場合、GL_INVALID_VALUEが発生します。

programがプログラムオブジェクトでない場合、GL_INVALID_OPERATIONが発生します。

program:関連付けされるプログラムオブジェクトのハンドルを指定します。

index:バインドされる汎用頂点属性のインデックスを指定します。

nameindexがバインドされる、ヌル終端文字を含む頂点シェーダのattribute変数の名前を指定します。

プログラムのリンク)

linkProgramメソッドを呼び出して、プログラムオブジェクトをリンクします。

リンクに失敗した場合はNSLogでエラーログを出力し、頂点とフラグメントのシェーダオブジェクトをglDeleteShaderで、プログラムオブジェクトをglDeleteProgramで削除します。

uniform変数の場所を取得)

glGetUniformLocationで、プログラムオブジェクト内にあるuniform変数の場所を取得し、drawFrameメソッドで定義したOpenGL ESの変換行列用のインデックスに設定し、図形移動用変数の受け渡しができるようにします。

glGetUniformLocation

uniform変数の場所を返します。

GLint glGetUniformLocation(GLuint program, const GLchar *name);

glGetUniformLocationは、プログラムオブジェクト内の指定されたuniform変数の場所を表す整数を返します。

nameは、空白を含まないヌル終端の文字列である必要があります。

nameは構造体ではなく、構造体の配列、またはベクトルや行列のサブコンポーネントで、program内のアクティブなuniform変数名である必要があります。

この関数は、nameprogram内のアクティブなuniform変数と一致しない、またはnameが予約接頭辞『gl_』で始まらない場合、-1を返します。

構造体または構造体の配列であるuniform変数は、構造体の各フィールドにglGetUniformLocationを呼び出すことによって照会することができます。

配列要素演算子『[ ]』と構造体フィールド演算子『.』は、配列内の要素または構造体内のフィールドを選択するためのnameに使用することができます。

これらの演算子を使用した結果は、別の構造体、構造体の配列、またはベクトルや行列のサブコンポーネントに使用することはできません。

nameの最後の部分がuniform変数の配列を示す場合を除き、配列の最初の要素の場所は、配列の名前を使用する、または『[0]』を付けた名前を使用することによって取得することができます。

uniform変数に割り当てられている実際の場所は、プログラムオブジェクトがリンクに成功するまでは不明です。

リンクの実行後、コマンドglGetUniformLocationはuniform変数の場所を取得するために使用することができます。

この場所の値は、uniform変数を設定するためにglUniformに渡したり、uniform変数の現在の値を照会するためにglGetUniformに渡すことができます。

プログラムオブジェクトがリンクに成功した後、uniform変数のインデックス値は、次のリンクコマンドが発行するまで固定されます。

uniform変数の場所と値は、リンクが成功した後でのみ照会することができます。

programがOpenGLによって生成された値でない場合、GL_INVALID_VALUEが発生します。

programがプログラムオブジェクトでない場合、GL_INVALID_OPERATIONが発生します。

programがリンクに成功しなかった場合、GL_INVALID_OPERATIONが発生します。

program:照会するプログラムオブジェクトを指定します。

name:場所を照会する、uniform変数の名前を含むヌル終端の文字列へのポインタを指定します。

頂点とフラグメントシェーダの解放)

glDeleteShaderで不要になったシェーダオブジェクトを削除します。



参考文献

iOS OpenGL ESプログラミングガイド

OpenGL ES 2.0 Reference Pages






Lifestyle 650 home entertainment system
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
10 | 2017/11 | 12
Sun Mon Tue Wed Thu Fri Sat
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 - -
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ。

Wish List
WACOM


ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
BOSE

Lifestyle 650 home entertainment system
Reference
NSApplicationDelegateプロトコル
NSArrayクラス
NSAutoreleasePoolクラス
NSBundleクラス
NSBundle UIKit追加分
NSCalendarクラス
NSCoderクラス
NSCodingプロトコル
NSCopyingプロトコル
NSDataクラス
NSDateクラス
NSDateFormatterクラス
NSDictionaryクラス
NSEntityDescriptionクラス
NSEnumeratorクラス
NSErrorクラス
NSExceptionクラス
NSFetchRequestクラス
NSFileHandleクラス
NSFileManagerクラス
NSIndexPathクラス
NSIndexPath UIKit追加分
NSKeyedArchiverクラス
NSKeyedUnarchiverクラス
NSKeyValueCodingプロトコル
NSLocaleクラス
NSManagedObjectクラス
NSManagedObjectContextクラス
NSManagedObjectModelクラス
NSMutableArrayクラス
NSMutableCopyingプロトコル
NSMutableDictionaryクラス
NSMutableSetクラス
NSNotificationクラス
NSNotificationCenterクラス
NSNullクラス
NSNumberクラス
NSObjectクラス
NSObject UIKit追加分
NSObjectプロトコル
NSPersistentStoreクラス
NSPersistentStoreCoordinatorクラス
NSPredicateクラス
NSPropertyListSerializationクラス
NSRunLoopクラス
NSSetクラス
NSStringクラス
NSString UIKit追加分
NSTimerクラス
NSTimeZoneクラス
NSURLクラス
NSURLProtectionSpaceクラス
NSURLRequestクラス
NSUserDefaultsクラス
NSValueクラス

UIActionSheetクラス
UIActionSheetDelegateプロトコル
UIActivityIndicatorViewクラス
UIAlertViewクラス
UIAlertViewDelegateプロトコル
UIApplicationクラス
UIApplicationDelegateプロトコル
UIBarButtonItemクラス
UIBarItemクラス
UIButtonクラス
UIColorクラス
UIControlクラス
UIDatePickerクラス
UIDeviceクラス
UIEventクラス
UIFontクラス
UIGestureRecognizerクラス
UIImageクラス
UIImageViewクラス
UIKit Function
UILabelクラス
UINavigationControllerクラス
UINavigationItemクラス
UIPickerViewクラス
UIPickerViewDataSourceプロトコル
UIPickerViewDelegateプロトコル
UIPinchGestureRecognizerクラス
UIResponderクラス
UIScreenクラス
UIScrollViewクラス
UISearchBarクラス
UISearchBarDelegateプロトコル
UISegmentedControlクラス
UISliderクラス
UISwipeGestureRecognizerクラス
UISwitchクラス
UITableViewクラス
UITableViewCellクラス
UITableViewControllerクラス
UITableViewDataSourceプロトコル
UITableViewDelegateプロトコル
UITapGestureRecognizerクラス
UITextFieldクラス
UITextFieldDelegateプロトコル
UITextInputTraitsプロトコル
UITextViewクラス
UITextViewDelegateプロトコル
UIToolbarクラス
UITouchクラス
UIViewクラス
UIViewControllerクラス
UIWebViewクラス
UIWebViewDelegateプロトコル
UIWindowクラス

AVAudioPlayerクラス
AVAudioPlayerDelegateプロトコル

CADisplayLinkクラス
CAEAGLLayerクラス
CALayerクラス

CGAffineTransform
CGBitmapContext
CGColor
CGColorSpace
CGContext
CGGeometry
CGImage
CGPath

EAGLContextクラス
EAGLDrawableプロトコル

Foundation Constants
Foundation Data Types
Foundation Functions

MPMediaItemクラス
MPMediaItemArtworkクラス
MPMediaPlaylistクラス
MPMediaPropertyPredicateクラス
MPMediaQueryクラス
MPMusicPlayerControllerクラス

Randomization Services

System Sound Services
Amazon


OpenGL ES
SQLite
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
Visitors
QR Code
QR