2012年02月07日

うにばな(ライトマップに関するアレ)

今回は意外に多い”ライトマップ”の検索をまとめてみました

さいしょに なぜUnity3Dがライトマップ機能(ビーストライトマップ)を搭載するに至ったかを考えてみます。

Unity3Dの場合はUV値がひとつしかモデルに対し扱えないようなんですね
↑これちょっと待って下さい 自分が古い情報だったかも知れません
訂正です: ライトマップシェーダー関連は2番目のUV値をひろってくれるようです。ただしLegacyシェーダーの
扱いになるので、あたらしいバージョンのUnityだと最初からシェーダーがついてこないのかな?
古いバージョンのLightmapシェーダーを導入すれば問題なく複数UVがいけるようです。 ということは
ライトマップを参考にシェーダーをいじれば複数のUVでマッピングが可能なんですね やるな!Unity てへぺろw




高級な3Dアプリだと複数のUVに対応が普通なのですが、リーズナブルな3Dアプリの場合まだ
UV値がモデルに対してひとつしか与えられないようです。
たとえば 背景で質感のテクスチャをタイリングにしたい場合 影(陰影含む)は別のUVにしてやらないと
見た目がおかしくなります。 ライトマップは今までも外部で焼き付けることで実現は可能だったわけですけど
テクスチャのタイリング部分も一枚のテクスチャとしてUVを取らなければならないので
全体のテクスチャ解像度をあげてやらないとクオリティが得られませんでした。

それから 
たとえば背景のモデルを配置しなおしたりライトを変更したりの調整を入れた場合 
外部に背景データを焼き付けるためにいちいち取り出すのは手間がかかるため 
内部にライトマップ機能を持ったほうが作業効率はいいです。
また内部にライトマップ機能を搭載することでプロシージャルな影のベイクが可能になるわけです。
背景を自動生成して影をライトマップにベイクしてしまうことができるので汎用性の高いゲームのシステムを
組むことができます。

などの理由からUnity3Dでは内部データにあえてUVを複数持たずに ライトマップのベイク機能を搭載したと
考えるわけです。
他の高級ゲームエンジンでは複数UVを扱うことができライトマップも実現できますますが 個人的には調整の
時間を短縮できる組み込み型ライトマップのほうが効率が良いと思います。


■ライトマップ作成の流れ(パラメータの説明)
lightmap7lightmap3


●上左画像 モデルをインポートする場合『FBXImporter』の『Generate Lightmap UVs』にチェックを入れます
●上右画像 ライトマップしたいオブジェクトモデルに対して『Static』にチェックを入れます

●画像下 ライトマップウィンドウをひらいて『Bake』のボタンを押すだけでライトマップは作成されます。
シーンにライトを配置することを忘れないようにしてください。

lightmap6

■パラメータの説明1(一部リファレンスからの意訳含む)

◯Mode  デュアルライトマップモードでは、nearとfarライトマップの両方をベイクします。 リファレンスページ http://unity3d.com/support/documentation/Manual/LightmappingInDepth.html を参照していただけると
わかると思いますが。ベイクしたシャドウと通常光源によるシャドウのブレンドが効率化されます。
シングルマップモード時にはfarテクスチャのみレンダリングされます。
◯Quality ハイとロー2種類のレンダリング品質プリセットが登録されています。ファイナルギャザーとアンチエイリアス設定のいくつかに影響を与えます。
◯Bounces GI(グローバルイルミネーション(大域照明))での間接照明として反射する光量です。0の場合は反射が無視されライトの直接光のみのレンダリングとなります。
◯SkyLightColor 空からの光のシュミレートで屋外のシーンで降り注ぐ光とその色を表現するのに適します
  ●SkyLightIntensity 空の光の強度
◯BounceBoost 間接光をブースト(向上)することでレンダリング時に光の減衰を押さえることで 反射する量を押し上げます。
◯BounceIntensity 間接光の強度の乗数。
◯FinalGatherRaysファイナルギャザーポイントから放射される光線の数 で値が高いほど高品質になります。
  ●ContrastThreshold 新しいファイナルギャザーポイントが適応サンプリングアルゴリズムによって作成される色のコントラストのしきい値。値が高いほどスムーズ。
  ●Interporation ファイナルギャザーポイントで色補間される方法を制御。高度、勾配に基づく補間。
  ●InterpolationPoints 補間するファイナルギャザーポイントの数。値が大きいほど滑らかな結果を与え、照明の詳細をスムーズにします。

◯AmbientOcclusion ライトマップテクスチャーにベイクするアンビエントオクルージョンの量。
  ●MaxDistance この距離を越えた場合に計算を除外。
  ●Contrast オクルージョン境界の遷移を制御します。
◯Lock Atras  ロックアトラスが有効時、自動アトラスが実行されず、ライトマップ・インデックスは、タイルとオブジェクトにオフセットが変更されません。
◯Resolution Unityワールド内の単位当たりのテクセルでライトマップの解像度です。値が50で10unit。10unitは、ライトマップで500x500ピクセルを占有している平面になります。


■ファイナルギャザーて?
パストレーシング法によって光線追跡をするレンダリング方法です。ラジオシティの一種で 視線からカメラを通して伸ばした点とオブジェクトとの衝突点を算出してそこから空間中にレイを拡散して飛ばします。そのレイを遮る物体があった場合そのオブジェクトの色と輝度を計算に加味する方法です。 周囲のオブジェクトからの影響がレンダリングに反映されるため よりリアルな表現が可能となります。
ファイナルギャザーの解説→http://area.autodesk.jp/column/tutorial/3ds_max_kitchen_stadium/7_so-blog_finalgather/

■アンビエントオクルージョンて?
物体表面を明るく物体同士の接合部やひび、エッジが立った部分を暗くコントラストする技術です。 
下の参照画像を見てイメージを掴んでいただければと思います。 それってラジオシティじゃないのと思い出す方 それと考え方は同じです。
アンビエントオクルージョンは直訳で環境遮蔽です。 ラジオシティが光源に対してサーフェス面から複数の
レイを出して何本が通るかにより明るさを表現するのに対して、アンビエントオクルージョンはさらに何本が
物体によって遮られるかを暗さ加味してコントラストを上げ絵としてリアルなハーフシャドウを実現するものです。

素材はこちらからお借りしました 
http://me.autodesk.jp/wam/maya/docs/Maya2009/index.html?url=mrfMS_Ambient_occlusion_concepts.htm,topicNumber=d0e506995
comp_occlusion_rays_2


素材はこちらからお借りしました 
http://fallenexile.blogspot.com/2011_01_01_archive.html 
mb



アンビエントオクルージョンに関する説明はここがわかりやすく解説してありました
http://ff14.miya-bi.com/archives/189




■パラメータの説明2
lightmap4

●画像上段 比較用の通常のベイク処理
●画像中段 『Skylight Intensity』は『SkyLightColor』で指定した大域光源の空の色が全体に加味されます
●画像下段 『Bounce Intensity』は物体同士の表面反射による光の映り込み影響をシュミレートします

大きく影響が出るパラメータはこの2種類ぐらいでしょうか


■ライトマップのテクスチャの配列ほか
lightmap5

ベイクされたライトマップは画像右のように配列に取られます。近距離にブレンドされる『near』と
遠方表示される『far』の2種類ができます。
配列のインデックスは ライトマップの解像度指定とアトラスのロック指定に応じて変化します。

作業ウィンドウ左上のドロップダウンセレクトで『Lightmap Resolution』を選択すると 『Static』指定をした
オブジェクトにライトマップの解像度を示すグリッドが表示されます。
右下に『Lightmap Display 』のチェックボックスがでますので『Show Resolution』にチェックを入れてください。
『Shadow Distance』はカメラからの距離に応じてライトマップ表示する距離だったり(near farのマップの切り替わり)をコントロールできます。

■ライトマップの解像度の変更
lightmap2

オブジェクトモデルを選択して『Object』タブで 『Scale in Lightmap』の値を変更することでオブジェクト単位での
ライトマップテクセルのスケール(ライトマップの解像度)を変更することができます。
解像度が足りない(ライトマップテクスチャが荒いとき) または 解像度が高すぎる(遠方に表示されるモデル)
などに状況に応じてスケールの値を変更してやります。

■ライト調整による影のクオリティ変更
lightmap1

ライトを選択した場合は『Object』タブがライトの属性に変更されます。ポイントライトかディレクションライトに限り
ソフトシャドウに値が表示されると思います。『Shadow Angle』はライトによりできる影のボケ度合い 
『Shadow Sample』が影のクオリティだと考えて良いと思います。


と ここまで書いてきて何ですが Youtubeにチュートリアルがありました。これを見て流れを掴んでみてください。

上の動画はビーストライトマップの室内の環境設定でこれで操作はわかると思います。
下の動画はビーストライトマップが搭載される前のライトマップの作成方法で今のところUnity内部で作成された
ライトマップ情報を書き出すことはできない?ようなので 例えばUnityでシーンの仮組みをして他のエンジンに移植
などという場合には下の動画の外部プラグインを使用したマッピングが有効になると思います。






さらに設定について深く知りたい方はこちらへ
http://unity3d.com/support/documentation/Manual/LightmappingInDepth.html
http://unity3d.com/support/documentation/Manual/LightmappingCustomSettings.html



今後の予定ですが背景作成のチュートリアル記事を書くときに またライトマップに関して触れたいと思います。
それではまた 

akinow at 12:24|PermalinkComments(0)TrackBack(0)この記事をクリップ!Unity3d 

2012年02月02日

今日の美人さん2012

120202

形を変えながら 続いていくコーナー すごく久しぶりですが『今日の美人さん』でございます。
こんな稚拙なコーナーでも楽しみにしてくださる方がいらっしゃるのですYO 

今回は新津田沼近辺の女子中学生。
女子中学生を描くときは芯があるけど柔らかい関節にしてあげると それらしくなります。 が
描いたあとで気づいたんですけど この子たち小柄だけど高校生だったん  管弦楽部か何からしくて
一緒にいる人の背中にそういうプリントが入ってました。 服装はかなりうろ覚えなんですが雰囲気は
あってるはず。 やっぱりショートカットは良いですねー描くのが楽でw じゃなくて かわいいは正義ですよw

120127A

なにか更新ついでに落書きを載っけておきます。 時間ができたら ひさしぶりにマンガ描きたいんですけどね
なかなか時間が取れないんで こうやって描きたい気持ちをタブレットにぶつけるわけです。
あ 関係ないですが 『こなぁー雪ー ♪』を歌ったバンドさんが活動休止だそうですね その曲しか知らないんですが イッパツを出すのって大変なんですよ。 この世の中の殆どの人が何者にもなれないんですから。

簡易更新でしたが、うにばなも数日中に記事にしますので また見に来てやってください。
それではまたー

akinow at 22:43|PermalinkComments(10)TrackBack(0)この記事をクリップ!日記 | 

2012年01月26日

うにばな(配列に関する)

Unity3Dでの配列に関しての検索が多かったので記事を書きました。

具体的にどのような場面で使用するかといえばやはり配列とそのソートでしょうか
ゲーム中でアイテムの登録やアイテムの整理やらのデータの並べ替えなどが問題になることが多いです。

どんなことに使用するの?ということで いちおう例をあげておきます。

現在作成中のDota系ゲームではミニオンのジェネレート地点から敵のベースまでの移動経路に配置された
waypointデータをソートするのに配列ソートを使用しています。
まず最初にwaypointにwaypoint本体の値(Transform)と敵のベースまでの距離をclass作成して
距離をキーとしてwaypointの並べ替えを行なっています。
Inspectorで一個づつ近い順に登録してももちろん有効ですけど データが変わるたびにその労力はいやでしょ?w

なのであらかじめ
WaypointMasterというスクリプトを親につけて複数のwaypointをその子供にして 

■WaypointMasterの冒頭

class Destination{


var distance:float;
var trans:Transform;

}

function Start(){
for( var trans:Transform in transform){
distination = new Destination();

destination.distance = Vector3.Distance(trans.transform.position,DestinationPoint);
destination.trans = trans;

DistinationArray.Push(new DestinationResult(distination));
}
         ・
         ・
         ・

}


これをdistanceをキーにしてソートするなどというように使用しています。 
まあ細かいところはそのうち解説いたしますので 今回は配列のお話を。。


■Unity3Dで扱える配列

http://robotduck.wordpress.com/2009/11/04/88/   //配列に関する記事
この記事を読めばほとんどわかってしまう内容なのですが、リンク先の記事を眺めてから読んでみてください。

Unity3Dであつかえる配列には以下のようなものがあります

■ビルトイン配列
■Javaスクリプトタイプの配列
■ハッシュテーブル
■ArrayLists(辞書型配列)
■Generic配列
■2次元配列 など



■ビルトイン配列
ビルトイン配列(builtin_Array)は大きさが決まっていない配列で高速に処理できるものです。
var values : int[]];
var values : float[];
var values : String[];
var values : GameObject[];


などのようにほとんどの型がこの指定で配列化できます。ただしこのまま使用するとエラーが出ると思います。
なぜならばデータに大きさがないため初期化のプロセスが必要だからです。
これはAwake()またはStart() のfunctionで


var values:int[];

function Awake(){

values = new int[10];


として配列を確保してやる必要があります。
初期化と同時に数値を代入したい場合は

var values:int[]=[0,0,0,0,0,0,0,0,0,0]

としてやると配列宣言と初期化を同時にしていることになります。

まだこのブログでは解説していませんがclassを使用する場合


var CLASSArray : CLASS[];

class CLASS{

 var1:int;
var2:float;
var3:String;


function Awake(){

CLASSArray = new CLASS[1]; // 配列の領域確保

CLASSArray[0] = new CLASS(); // 空のクラスを代入

CLASSArray[0].var1 = 5;
CLASSArray[0].var2 = 5.0;
CLASSArray[0].var3 = "test";



クラスを代入のところを私は

for(i=0; i<CLASSArray.length; i++){

CLASSArray[i] = new CLASS();

}

なんて風に書いてるんですけど他の書き方があったらだれかヘルプミーです。



■Javaスクリプトタイプの配列

リファレンスの解説を翻訳(意訳)しました

function Start () {
var arr = new Array ();
  
 arr.Push ("Hello");    // elementの追加
arr.length = 2;      // arrayのリサイズ
 arr[1] = "World";     // セカンドエレメントの追加

  for (var value : String in arr) {  // 配列から値を取り出す
print(value);
}
}



/////////////////////////////////////////////

var values : float[]; // インスペクタで値を登録します

function Start () {

for (var value in values) {  // forループを使用してvaluesからvalueに値をひとつづつコピー
print(value);
}

values = new float[10]; //valuesに10個分の領域を確保

values[1] = 5.0;   //valuesの2番目の値(インデックスは0が初めで2番目が1)
}


/////////////////////////////////////////////

●配列のビルトイン配列への変換方法


function Start () {
var array = new Array (Vector3(0, 0, 0), Vector3(0, 0, 1));
array.Push(Vector3(0, 0, 2));
array.Push(Vector3(0, 0, 3));


var builtinArray : Vector3[] = array.ToBuiltin(Vector3); //配列をビルトイン配列に変換  <.ToBuiltinを使用して変換 型は 左側=右側にあわせる

var newarr = new Array (builtinArray); //ビルトイン配列を配列に変換


print (newarr);
}



■配列型のリファレンス

●Variables
length 配列の長さを返す

●Constructors
Array 配列型の指定

●Functions
Concat    配列の結合
Join      値をひとつだけ結合
Push   配列の最後に値を追加する
Add      同上
Pop      配列の最後の値を取り出す
Shift       配列の最初の値を取り出して返す
RemoveAt インデックス(0,1,2‥)で指定した値を削除する
Unshift   配列先頭にひとつ以上の値を追加?配列の長さを更新する。
Clear    配列の値を0に初期化する
Reverse    配列並びを反転する
Sort      配列を規則にそってソートする(abc順、値が小さい順など)


Q.ビルトイン配列にArrayみたいに値を追加したいときはどうすんの?

話が前後しますがビルトイン配列には通常の配列操作のような機能(function)がついていないようです。
それで一度新しく配列をつくってそちらで操作する方法があるようです。

var builtinArray : MyClass[];

function Start () {
var enemies = new Array(builtinArray);
enemies.push(new MyClass());
}


でここまで覚えた所でビルトイン配列のソートですが↓のリンク
http://answers.unity3d.com/questions/22261/sorting-builtin-arrays.html

例の中ではクラスを使ったものが使いやすかったです。

import System;

class RaycastResult implements IComparable
{
var distance : float;
var collider : Collider;

function RaycastResult(hit : RaycastHit)
{
distance = hit.distance;
collider = hit.collider;
}

function CompareTo(other : System.Object) : int
{
if (!(other instanceof RaycastResult)) return;
var raycastResultOther : RaycastResult = other;
return distance.CompareTo(raycastResultOther);
}
}

var raycastResults : Array = new Array();

function SortDistances()
{
raycastResults = new Array();
var hits : RaycastHit[] = Physics.RaycastAll(transform.position, transform.forward, 100.0);

for(var hit : RaycastHit in hits)
{
raycastResults.push(new RaycastResult(hit));
}
raycastResults.sort();

}

これは一度にPhysics.RaycastAll()を使用してオブジェクト前方に例キャストしてヒットしたものを配列hitsに
格納してしまっています。
それをraycastResultsにpushで登録して ソートするわけですが。
CompareTo()のファンクションの中のdistance.CompareTo(raycastResultOther)が距離distanceをほかの値と比較して
小さい方を返す部分です。 distanceを他の値に変えれば条件が変わります。

■ArrayList


ArrayListクラス
http://msdn.microsoft.com/ja-jp/library/7x4b0a97(v=vs.80).aspx

Javaの配列に操作が似ているけれどJavaとC#両方からつかえる点が異なるようです。
リンク先のメンバの解説を読んでつかってみてください。 なげやりw
 

■ハッシュテーブル

http://msdn.microsoft.com/ja-jp/library/system.collections.hashtable.aspx
http://msdn.microsoft.com/ja-jp/library/system.collections.hashtable_methods.aspx


ハッシュテーブルは連想配列とも呼ぶようで辞書の一種ですね 普通の配列と少し違って
『キー と 値』の 2つでワンセットに格納されます。

import System.Collections.Hashtable; //JavaScriptの場合importでC#の場合はusingでライブラリ仕様宣言します


myhash = {"name":"John", "occupation":"programmer"};

Debug.Log( myhash["name"] ); //displays "John"


ハッシュテーブルのメソッド
Count ハッシュテーブルの長さ


Clear     値をクリアー テーブル長さを0に
Remove     キーと値の削除
ContainsValue  与える値と同じ値がテーブルに入っているか確認
ContainsKey   与えるキーと同じキーががテーブルに入っているか確認
Contains      キーか値の確認でいいのかな?.
Add        キーと値をテーブルに追加


●ハッシュテーブル(辞書)のソート

http://forum.unity3d.com/threads/6335-associative-arrays-hashtables



function SortHashtable (inpHash : Hashtable) {

var iVal; var key; var arrayValues = new Array(); var valuesKeysHash = new Hashtable(); var returnArray = new Array();



for (key in inpHash.Keys) {

arrayValues[arrayValues.length] = inpHash[key];

valuesKeysHash.Add(inpHash[key], key);

}


arrayValues.Sort();


for (iVal in arrayValues)

returnArray[returnArray.length] = valuesKeysHash[iVal];

return returnArray;

}




■Generic配列

かなり様々な操作が行える上に早いので なれれば使いやすい?
C#のひとは断然これをつかうんでしょうね

●参照
http://answers.unity3d.com/questions/166789/iterate-through-generic-list.html

http://msdn.microsoft.com/ja-jp/library/6sh2ey19(v=vs.80).aspx

Listのメソッド
http://msdn.microsoft.com/ja-jp/library/s6hkc2c4(v=vs.80).aspx


■基本仕様例

var myList = new List.<型>();

myList.Add(値);

myList[インデックス] = 値;

myList.RemoveAt(インデックス);




例)

import System.Collections.Generic; // ライブラリのインポート

var phraseList = new List.();

function OnGUI () {

var i : int = 0;
for (str in phraseList) {
if (GUI.Button (Rect (100, 20 * i, 200, 20), str)) {
Debug.Log ("Box #" + i + " is working!");
}
i++;
}

}

function Update () {
if (Input.GetKeyUp ("z")) {
phraseList.Add("Test string 1");
phraseList.Add("Test string 2");
phraseList.Add("Test string 3");

}

}




■2次元配列

2次元の配列ですよ 指定方法はカンマで区切って宣言するだけです。

var myArray = new string[0,1];

var width = myArray.GetUpperBound(0); //2次元配列の次元の上限を返す
var length = myArray.GetUpperBound(1);//2次元配列の次元の下限を返す




調べていたらちょっと特殊な2次元配列の使い方をみつけたのでピックアップ
GameObject型に2次元配列を使用してステージを作るやり方ですかね なんかにつかえそう。

http://answers.unity3d.com/questions/168822/2d-array-of-gameobjects.html


public var spawn = 15;
public var rows = 10;
public var cols = 10;
public var gemObject: GameObject;
public var pieces: GameObject [,];
public var gems: Object [];

function Start () {
//Initializing variables
pieces = new GameObject[rows, cols];

//load's gems from the resources Gem folder to this object array
gems = Resources.LoadAll("Gems", GameObject);

for (i = 0; i < gems.Length; i++)
Debug.Log("gems #" + i + "is: " + gems[i].name);

for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++){
pieces[i,j] = Instantiate (gems[i], Vector2(i,j), Quaternion.identity);
}
}
}



以上私も全部の機能を使ったわけではないので間違いがあるかも知れませんので ご容赦ください。
で そろそろ本業のビジュアル的な部分や企画的なことなどもやっていこうかなーと 思っています。。。。。。。仕事が入らなければ

akinow at 18:31|PermalinkComments(2)TrackBack(0)この記事をクリップ!Unity3d | シリーズ講座

2012年01月22日

うにばな(どた進捗ですよ)

dota8

Webプレーヤー

定期更新のドタ進捗でございます。
だいたい必要な部分は入った感じです 魔法(能力)も入りましたよ1種類だけですが。
今回はミニオンと呼ばれる雑魚キャラの動きのAI搭載が大きな変更点です。
あとゲームのコンセプトが コントローラーで遊べる と言うのが目標ですのでコントローラーがある方は
コントローラーで動かしてみてください。 無い方はWASDキーで移動できます。
例によって数日間だけアップしておきますので もし動かせなかった方は次の更新をお待ちくださいませ。

今後の目標 
ネットワーク対応は終わりましたので もうあとは各種アイテムの整備とグラフィックまわりのつくりこみ
ですね。 

一山ついたということで ストパンSTGのほうを進める作業に戻りたいと思います。
そのまえに 本業の仕事を片付けましょう。。それではー

akinow at 23:28|PermalinkComments(2)TrackBack(0)この記事をクリップ!日記 | Unity3d