2013年3月24日日曜日

[Unity]Shader上で深度値を取得する方法


Shaderから深度値を取得する方法
チュートリアルの「Shader Replacement」が良い教材

◆Edge Detection

・カメラ上で以下のコードを追加する
取得できるのはモードにより異なる
  • 深度のみ
  • 深度と法線

void OnEnable() {
    camera.depthTextureMode = DepthTextureMode.Depth;
    camera.depthTextureMode = DepthTextureMode.DepthNormals;
}



・Shader上の処理
深度バッファ値を格納してあるテクスチャー情報を取得する。
そのためには以下のようにShader用のグローバルな固定変数がある
sampler2D _CameraDepthTexture;
sampler2D _CameraDepthNormalsTexture;

デプスバッファはプラットフォーム毎に異なる実装方法なので、
リンクを参照する。
あとは、差異をなるべく少なくするためのマクロも実装されているので活用する。


◆Glowing Things

RenderWithShader -> 特定のレンダリングパスにシェーダーを適応する処理
そのデモが「Glowing Things」である。

・オブジェクトに適応するShaderのレンダリングタイプを設定する
Hierarchy上のCylinderオブジェクトには「VertexLit Funky」というShaderが適応されている。
ポストエフェクト時に演出していることがわかる。


以下、Unity Script からの抜粋
OnPreCull is called before a camera culls the scene.
OnPreRender is called before a camera starts rendering the scene.
OnPostRender is called after a camera finished rendering the scene.
OnRenderObject is called after camera has rendered the scene.
OnWillRenderObject is called once for each camera if the object is visible.
OnGUI is called for rendering and handling GUI events.
OnRenderImage is called after all rendering is complete to render image






[Blender]3D View FullからDefaultに戻る方法

Blender(v2.64a)を使用しているとき、
Screen Layoutの3D View Fullから戻れなくて困ったのでメモ。

◆手順

 1. 3D View Full画面に移動する
 2. 画面右下の+ボタンを押す、するとヘッダー画面が出現
 3. ヘッダー画面の表示タイプを「info」に変更する
 4. スクリーンビュータイプを「Default」(3D View Full)以外に変更する











いやー、戻れなくて困った困った。
検索すると、Blenderの操作感に違和感がある方が多くてびっくり。

◆参考

http://blenderartists.org/forum/showthread.php?268127-Delete-2-64-Screen-Layout-3D-View-Full-(Solved)

2013年3月3日日曜日

[Android]Rajawaliフレームワークについて

パーティクルを簡単に実装して確認できるものはないかと探していると、
こちらの記事で紹介されていたものが目に留まった。
「Rajawali」というのはAndroid用のOpenGLベースのフレームワーク。

触ってみた感じだが、非常によくできている。
サンプルデモを触りながらソースを見る限り、3Dモデルの表示やシェーダーなども簡単に実装できるし、FBX形式のモデルにも対応している。
サンプルも豊富なので、組み合わせるだけで大抵のゲームを表現することが可能な気がする。
もし、クロスプラットフォーム開発を見越していないのなら、使ってみて絶対に損は無い一品だと思われる。


が、デモ版だからなのか、Galaxy S2でデモを動かそうとすると動作しなかった。
どうやらメモリが不足してエラーが発生しているようだ。
その他にもいくつか不具合をみつけた。
デモの作りに問題が有るのか、フレームワーク自体に問題があるのかは調査していないのでなんとも言えないのだが、その辺は実装時にうまいこと隠蔽できるのかもしれない。

ちなみにデモ版は Google Play からダウンロードした。

◆注意点

 - iPhone版が存在しない
 - インポート時、「Rajawali」プロジェクトをインポートする必要が有ること
サンプル見たさに、先にサンプルプロジェクトをインポートしてしまい、とんでもない数のエラーが発生してしまったので、こちらの注意点は備忘録としてメモ。

◆参考

http://www.rozengain.com/blog/2011/08/23/announcing-rajawali-an-opengl-es-2-0-based-3d-framework-for-android/

・Github
https://github.com/MasDennis/Rajawali/wiki/Importing-Rajawali-and-RajawaliExamples

[Unity]UnityのJSONObjectで発生するエラー


Unityでjsonを扱う際に使用するライブラリの一つである「JSONObject」を使用したが、Unity4以降で「TryParse Error」というエラーが発生する。
気持ち悪いので修正した。

◆JSONObject.cs


以下の部分を画像の様に修正すれば問題がなくなる
なお、コード部分はwikiからの引用

try {
 n = System.Convert.ToDouble(str);
 type = Type.NUMBER;
} catch(System.FormatException) {
}





型変換に失敗していたので、返還前に型チェックを行ってくれるTryParseメソッドを使用した。
しかし、強引にエラーを起こしていたとはなかなか……。

◆参照

2013年2月11日月曜日

[MonoDevelop]Snippetsを使って記述を楽にする方法

Snippetsをご存知だろうか。
端的に言えば、Snippetsとは、何度も同じことを入力する場合、その作業が面倒なので短い単語で呼び出せるようにしちゃおう!ということ。
HashKeyの概念でとらえると分かりやすいかもしれない(というかまんまHashです)。

だが、正直にいうと僕はSnippetsという言葉を知らなかった。
しかし、Snippetsという言葉を知らなくても恩恵に授かっていたことに気づく。
多くのプログラマーなら恩恵を授かったことが有るはず。
最も基本的なもので言えば、if文やfor文、while文やclass構文などでも使用されており、恩恵を授かったことの無いプログラマーなどは居ないはずだ。

と、どうでもいい言い訳がましいことはさておいて、早速使ってみた。

今回はUnityScript上での例で、タッチイベントの処理が毎度毎度記述するのが面倒なのでCode Snippets化した。

UnityScript上でタッチイベントを取得する際、下記のように記述するだろう。


foreach (Touch item in Input.touches) {
 switch( item.phase ) {
 case TouchPhase.Began:
  break;
 case TouchPhase.Canceled:
  break;
 case TouchPhase.Ended:
  break;
 case TouchPhase.Moved:
  break;
 case TouchPhase.Stationary:
  break;
 }
}


このようなコードを毎回記述するのは面倒だろう。
そこで、Snippetsの出番。
まずは「MonoDevelopEditor」上の[Preference]を開く。




◆[TextEditor] -> [Code Templates]を開くと、各言語毎に設定されているテンプレートコードがあるのが分かる。
今回は「Unity C#」なので、「C#」にSnippetsを追加する。




◆[Add]ボタンを押すと、テンプレート作成画面になる。



[Shoutcut] : TemplateTextを呼び出す際に記述するコード
[Group] : どのテンプレートグループなのかを判別
[Description] : snippetsの説明文
[Mime] : どの言語で使用されるものかを判別

[Shoutcut]に「TouchTemp」と記述し、[Group]は「C#」、
[Description]には「template for touch event」、[Mime]に「text/x-csharp」を入力し、大きい空欄の[Template Text]にコードを記述する。
今回はタッチイベント用のコードを記述しておく。

すると、コード上で「TouchTemp」と記述した後に「tab」キーを押すと、先ほど[Template Text]に記述しておいたコードが呼ばれるようになる。

※Descriptionの説明が記述もきちんとある



確かにこれは……いいものだ!


[Unity]Quaternionについて

UnityScriptでオブジェクトの回転に関する計算をするのが面倒な場合、Quaternionを使用すれば処理も高速になるし幸せになれるので実際に動かしながら実験したときのメモ。


◆概念

今回はUnity Script上のコードでどういう挙動になるかの調査なので、概念はwikiなどにお任し、割愛させていただく。



◆ソース
using UnityEngine;
using System.Collections;

/**
 * Quaternionを体系的に学ぶためのテストクラス
 * Quaternionは四元数と呼ばれ、回転をごくごく簡単に扱うことができる
 * なお、Quaternionは原点を中心に回転軸を考慮してしまうので、原点以外からの回転軸の計算を行いたい場合は事前に座標計算をしておく必要がある
 **/
public class QuaternionTest : MonoBehaviour {
 
 public Vector3 point;
 public Vector3 angle;
 
 public bool isAnimation;
 public int animationCounter;
 public int ANIMATION_FPS = 24;

 // Use this for initialization
 void Start () {
  // if target os is iPhone ~
  // change value from "#define kFPS 30 of AppController.mm"
  Application.targetFrameRate = 60;
 }
 
 // Update is called once per frame
 void LateUpdate () {
  if ( !isAnimation ) return;
  
  // カメラのQuaternionを取得
  // 今回の場合、カメラの座標 to 原点の向きが取得できる
  Quaternion targetQuaternion = Camera.mainCamera.transform.rotation;
  
  // 特定の座標点から座標点への向きを取得できる
  //targetQuaternion = Quaternion.FromToRotation( new Vector3(1,1,1), new Vector3(-1,-1,-1));
  
  // この例だと、カメラから物体の座標点
  //targetQuaternion = Quaternion.FromToRotation( transform.position, Camera.mainCamera.transform.position );
  
  // Quaternionを反転させる
  // 用途例としては、自分(敵)のQuaternionを敵(自分)に反転させて反映させることで向き合うことができる、など
  //targetQuaternion = Quaternion.Inverse(Camera.mainCamera.transform.rotation);
  
  // 原点 to 座標点の向きが取得できる
  //targetQuaternion = Quaternion.LookRotation( new Vector3(1,1,1) );
  
  // こちらの例だと、カメラの座標点 - 物体の座標点 を計算してから行っているので、
  // 物体の座標点 to 座標点の向きが取得できる
  Vector3 relativePos = Camera.mainCamera.transform.position - transform.position;
        targetQuaternion = Quaternion.LookRotation(relativePos);
  
  animationCounter++;
  if ( animationCounter >= ANIMATION_FPS ) {
   animationInit();
   return;
  }
  //transform.rotation = Quaternion.Slerp( transform.rotation, Camera.mainCamera.transform.rotation, Time.deltaTime );
  float mountTime = (float)animationCounter / ANIMATION_FPS;
  
  // Slerpは球面線形補間と呼ばれるアルゴリズムで、
  // QuaternionからQuaternionへの移動をスムーズに行うことができるヘルパー関数
  // 3つめの引数に、変化量を指定することで、なめらかな変化が実現できる( 0.0f 〜 1.0f )
  transform.rotation = Quaternion.Slerp( transform.rotation, targetQuaternion, mountTime );
 }
 
 public void animationStart() {
  animationInit ();
  isAnimation = true;
 }
 
 private void animationInit() {
  isAnimation = false;
  animationCounter = 0;
 }
}


◆参照
http://www015.upp.so-net.ne.jp/notgeld/quaternion.html http://ja.wikipedia.org/wiki/%E5%9B%9B%E5%85%83%E6%95%B0 http://marupeke296.com/DXG_No10_Quaternion.html http://docs.unity3d.com/Documentation/ScriptReference/Quaternion.html

2013年1月24日木曜日

[Unity]モバイル向けのShaderのメモ


Shaderの勉強のためのメモ
モバイル向けに使用できるものを中心にメモしていく。
まずは基本から。

◆バーテックスシェーダー
頂点データを使用して算術的に3D空間のデータに特殊効果を与えるグラフィックス機能。
Cg、GLSL、HLSLなどで扱える。

◆フラグメントシェーダー
ピクセルシェーダーとも呼ばれる。
ピクセル操作に特化したシェーダー。
基本的に頂点シェーダの情報を元にピクセルを操作するので、バーテックスシェーダーと同時に使用することが多い。
Cg、GLSL、HLSLなどで扱える。

◆ジオメトリシェーダー
プリミティブシェーダーとも呼ばれる。
プリミティブを作成できる。
バーテックスシェーダーの実行後にジオメトリシェーダーが実行される。
アセンブリ言語、Cg、GLSL、HLSLで扱える。

◆Unity内のシェーダー言語
Cg/HLSLを合わせて拡張したようなもの。
なので、基本的にはCg/HLSLが扱えれば問題ない。
Shader言語は初なのでまずは基本的なところから学習。
データ型
float - 32bit浮動小数点型
half - 16bit浮動小数点型
int - 32bit整数型
fixed - 12bit固定小数点型
bool - 論理型
sampler - テクスチャーオブジェクト型

その他にfloat3、float4x4などがあり、
ベクトルや行列を扱う型も存在する。

◆参照


◆実行順
Vertex Shader
Fragment Shader

の順番で実行される。

下位のシェーダーはモバイルでは使用できない
というかDirectX11向けに改良された点が多いので、モバイルは制限が多く感じられるのかもしれない。
 - geometory
 - hull
 - domain

◆セマンティクス
Shader言語で関数を記述する際に使用することがよくある。
関数宣言の構文についてと合わせて参照するとよい。
関数の戻り値に対しても、引数の型に対しても、使用目的の識別子として扱われる。
↓関数宣言の構文について

↓セマンティクスについて

よく使われるセマンティクス
シェーダー毎に挙動が異なることが多いので、使用する際にシェーダーとセマンティクスがどういう挙動になるか確認をした方が良い。

POSITION - オブジェクトの頂点位置を読み取る
SV_POSITION - オブジェクトの頂点位置の読み込みと書き込みが可能(DirectX10以降)