前回の投稿で 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 の二つのファイルを用意して、
プロジェクトの左のインスペクタ>ファイル追加で二つのファイルをビルドアプリのターゲットに追加します。
以下 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 でなぜかコンパイルできなかったので後で試します。
以上