SceneKit日和(2)

どうも、吉村です。

今回はSceneKitの2回目の記事として、10.9から新しく追加された、

「shaderModifiers」

というもので遊んでみましょう。
これはどういう機能かというと、
SceneKitの既定のシェーダーに、GLSLコードを挟み込んだり、上書きしてしまうものです。

数種類の定数によって、どのように書き換えを行うのか?を定義します。
今回はわかりやすく、WWDC2013で紹介されている、

SCNShaderModifierEntryPointGeometry

を試してみます。

これは頂点シェーダーを通過する際に、計算を挟み込むことができるものです。
使える変数としては、
ヘッダーファイルに以下のような記述がありました。

| struct SCNShaderGeometry {
| vec3 position;
| vec3 normal;
| vec4 tangent;
| vec2 texcoords[kSCNTexcoordCount];
| } _geometry;
|
| Access: ReadWrite
| Stages: Vertex shader only

今回は、これを使って、

「平面をねじる」

エフェクトにチャレンジします。

今回はインターフェースビルダーと、ソースを以下のような構成にします。
Banners_and_Alerts_と_SceneKitStudy_—_SceneController_m

さて、いきなりシェーダーをやるまえに、
少し今回構築するSceneKitのクラスの構造を紹介します。

Scene構造

結構階層が深いのですが、
SCNNodeが基本となり、
そこにカメラや、SCNPlane等の頂点情報がくっつき、
その下に色を確定するためのシェーダーやらなんやらが、バインドされている、
というように理解します。
これをふまえ、初期化コードを以下のように記述します。

コードのほとんどは前述の図の構造を構築するコードです。

一部補足説明すると、
_planeMaterial.diffuse.contents = [NSImage imageNamed:@”Bahamas Aerial.png”];
では平面に貼付ける画像を設定しています。
これはちょっと見た目単色だとちょっとわかりにくいためです。
contentsにはいろいろなものが入ることができ、
驚くべきことに、CALayerなんかもcontentsに入れることができます。
驚愕ですね。
さらっとこういうことをやってくるところがSceneKitの凄いところだったりします。
planeGeometry.widthSegmentCount = 200;
planeGeometry.heightSegmentCount = 200;
はポリゴンの分割数です。
ねじるのに、頂点が少ないと綺麗に見えないため、ちょっと多めに設定します。
SCNPlaneというのはSCNGeometryのサブクラスであり、
基本図形の生成のためのクラスで、他にもいくつか種類があります。

さて、今回の重要ポイントはシェーダーです。
テキストリテラルとして書いているので改行の関係みにくいので下にかくと、

となります。

x軸を基準に、zy成分を回転させるコードになっています。
ひねりぐあいを制御するために、
uniform float u_twist;
を宣言します。

GLSLが分かる人なら想像がつくのですが、
uniformというのは、シェーダーから見てのグローバル変数のようなものです。
GLSLの記事ではないので、今回は華麗にスルーします。

u_twistに値をセットするには以下のように記述します。

NSSliderの数値は、0-3に設定してあります。
この辺は自由に設定しましょう。

これで準備は万端です。
これを実行すると、見事にねじれた平面が表示されます。

デモ動画はこちらです。

Twist from wowdev on Vimeo.

SceneKitを使えば、
もし本来フルスクラッチで書いていたらとても大変なことが、
こんなにもお手軽に、快適にかけてしまう、
というのが分かって頂けたかと思います。

まだまだSceneKitの強大なパワーを紹介しきれていないので、
次回へ続きます。