[Swift SceneKit] SCNShadableでシェーダープログラムメモ(2)

- 2014-09-24

IuMwB2ZqUk

 

前回の投稿で SCNProgram によってフレーム毎の計算をバインドする方法があると書きましたが、

今回はその方法で SCNShabable を使ってみましょう。

なぜか OSX の 10.9 SDK で SCNProgramDelegate がうまく動かなかったので、iOS の SDK でコンパイルする事にしました。

iOSアプリのテンプレートの方で同じく GameViewController を書き換える方法で行きます。

File > Project.. で OS X ではなく iOS の Application > Game プロジェクトテンプレートを準備します。

シェーダー用のコードの用意 今回はリソースファイルとして Vertex Shadeer / Fragmental Shader をロードするので、

myShader.vert / myShader.frag の二つのファイルを用意して、

プロジェクトの左のインスペクタ>ファイル追加で二つのファイルをビルドアプリのターゲットに追加します。

icFsJq-t_s

以下 myShader.vert / myShader.frag の内容

GameViewController.swiftの書き換え 以下 GameViewController.swift の内容

テクスチャーを貼っていないためか、Fragmental Shader を空にしているためか分かりませんが、

表面が赤と青の面になってしまっています...。

 

18行目

let program = SCNProgram() SCNProgram インスタンスを作り、ここにシェーダープログラムをセットしていきます。

 

21行目

let vertexShader = NSString(contentsOfURL: vertexShaderURL!, encoding: NSUTF8StringEncoding, error: nil) program.vertexShader = vertexShader let fragmentalShader = NSString(contentsOfURL: fragmentalShaderURL!, encoding: NSUTF8StringEncoding, error: nil) program.fragmentShader = fragmentalShader program インスタンスに

バンドルリソースとしてロードした vertex / fragmental それぞれのコード(NSString)を渡します。

 

25行目

program.setSemantic(SCNModelViewTransform, forSymbol: "position", options: nil) program.setSemantic(SCNModelViewProjectionTransform, forSymbol: "modelViewProjection", options: nil) setSemanticでシェーダーコードの方で宣言した attribute と uniform をバインドします。

引数に使う Constants ですが、Vertex Shader に渡すデータセットとして SCNGeometrySource が用意されていて、

自動でバインドしてくれます。詳しくは Appleのドキュメントを参照してください。

 

67行目

material.handleBindingOfSymbol("time") { programID, location, renderedNode, renderer in glUniform1f(GLint(location), GLfloat(CFAbsoluteTimeGetCurrent() - startTime)) } 最後に SCNMaterial にフレームレンダリング毎に呼ばれるブロックを handleBindingOfSymbol でセットします。

ここで uniform / Attribute をバインドします。

これで 'time' Attributeには CFAbsoluteTimeGetCurrent でアプリ起動時からの差分のカウントが渡されると思います。

 

本来であれば SCNProgramDelegate を使ってバインドしたかったのですが現在の SDK でなぜかコンパイルできなかったので後で試します。

 

以上