Yaminabe

らくがきぶろぐ

てすと:Yaminabeちゃんは生まれたばかりのブログです みんなで仲よく使ってね

カテゴリ: シリーズ講座




今回は次世代機などで使用されているパーティクル描画の最適化手法である大量のパーティクルを描画するオフスクリーンパーティクルについてのまとめです。
ディファードレンダリングリアルタイムのテクスチャレンダリング のサポートが必要になりますので

プロバージョンの使用が前提です。そして現在Unityはモバイルのディファードレンダリングをサポートしていません。

ですのでPCでの使用に限られていまいますが、プロ版をお持ちでない方も こういう高速化技術があることを覚えておいていずれ活用していただければと思います。



デイファードレンダリングがどのようなものかを知っておく必要があります 。 日本語でわかりやすかったのが

■ 西川善司の3Dゲームファンのための「KILLZONE 2」グラフィックス講座(前編)

PS3のハイクオリティグラフィックスはDeferred Shadingでキマリ!?

http://game.watch.impress.co.jp/docs/series/3dcg/20090417_125909.html

ディファードレンダリング(遅延レンダリング)とは 同時に最大8枚のバッファに 法線データ、 カラーデータ、など様々なレンダリングに必要なデータをリアルタイムレンダリングして 合成の後フレームバッファに書き込むことで高品質なクオリティの映像を得るためのテクニックです。 各バッファに加工を施すことで多用なエフェクトなどを表現出来ます。 フレームバッファに書きこむだけのフォワードレンダリングに対して 合成後に遅れて表示バッファに書きこむため 遅延レンダリングと呼ばれます。




■GPU Gems 3:Chapter 23. High-Speed, Off-Screen Particles


http://http.developer.nvidia.com/GPUGems3/gpugems3_ch23.html

Nvidiaの公式サイトのデベロッパーセクションで無料公開されているGPUGems3内容に基づいて解説します。
パーティクルシステムは、多くの場合パフォーマンスの問題につながり、オーバードローを大量に消費するとレート
に影響します パーティクルシステムのエフェクトでは、たいていが多量のポリゴン、数百または数千が必要になります。
パーティクルエフェクトは多くの場合、あいまいでソフトな形状です。 例えば煙や霧のイメージは鋭いエッジなしで、低周波数のみを持っています。これらは視覚的な品質を損なうことなく 小さなサンプルで表すことができます(小さくレンダリングしても絵的にはあまり影響がない)。つまり低解像度のフレームバッファは十分有効ということが言えます。



■オフスクリーンレンダリング


パーティクルのサイズはメインフレームバッファのサイズの割合であるオフスクリーンレンダリングターゲットにレンダリングされます。ですが必ずしも同じサイズのバッファを必要とせず DX10から搭載されたダウンサンプリングの機能によって必要な品質のトレードオフに応じアプリケーションによってバッファの比率を選択することができます. 例えば、1/1、1/2、1/4、1/8 倍のスケールを選択できます(スケールは2の累乗に限定されません)

■オフスクリーン深度テスト

正確にシーン内の他の項目に対してパーティクルを閉塞するには深さのテストとそのサイズはオフスクリーンレンダリングターゲットと一致する深度バッファを必要とします

オフスクリーンレンダリングターゲットと一致する深度テストのための深度バッファ はメインのZバッファをダウンサンプルすることで取得します


  1. Deapth書き込みで通常通りにシーン内のすべてのソリッドオブジェクトをレンダリングします。

  2. 1の結果の深度バッファをダウンサンプリング。

  3. 小さなデプスバッファに対してテスト、オフスクリーンレンダリングターゲットにパーティクルをレンダリングします。

  4. パーティクルの描き込まれたテクスチャをアップサンプリング、メインフレームバッファに戻ってターゲットをレンダリングします。



【図1】
23fig02.jpg

【図2】





float4 particlePS(VS_OUT vIn): COLOR

float myDepth = vIn.depth;

float sceneDepth = tex2D(depthSampler, vIn.screenUV).x;

float zFade = saturate(scale * (myDepth - sceneDepth));

/ /Compute (r,g,b,a), etc.

return float4(r,g,b, a * zFade);




【図1】ゲームのスクリーン解像度に対して パーティクルのレンダリング解像度を1/4でダウンサンプリングした場合

(a) ゲーム画面解像度に対しZバッファの解像度が1:1の場合 パーティクルとオブジェクトのZ値は(0、1)で比較するが解像度が同等なので輪郭に影響は出ない

(b) ダウンサンプルしたZバッファでオブジェクトとパーティクルのZを比較する場合(0 or 1 =表示するしない)で判定すると輪郭部分に図のようなジャギーが出てしまう

(c) 画面解像度 4×4ピクセル=16ピクセル中にオブジェクトが専有するピクセル数 / 16 として平均値を求め平均値 からフェード値を得る コード中では zFade = saturate(scale * (myDepth - sceneDepth)); の部分

レンダリング時にカラー成分のアルファ値に a * zFade として境界部分のピクセルをぼかすことでエッジが目立たなくなります。





■ “High-Speed, Off-Screen Particles” in Unity

http://technology.blurst.com/off-screen-particle-optimization/


オフスクリーンパーティクルのUnityでの実例を検索してみたところ 最も早期に実現しているブログが有りましたが
このブログのコードはコード全体の一部分でしかなく再現することができませんでした

aaa





var blendMaterial:Material = PostProcessingHelper.GetMaterial(Shader.Find(“Hidden/Off-Screen Particles Composite”));

var texelOffset:Vector2 = Vector2.Scale(source.GetTexelOffset(), Vector2(source.width, source.height));

Graphics.BlitMultiTap(particlesRT, source, blendMaterial, texelOffset);



上記コードが問題の部分 ブログのコメント欄でも書かれていますが

PostProcessingHelper.GetPPCamera();

PostProcessingHelper.GetMaterial();


という見慣れないメソッドがありますが これがおそらく本人用にカスタマイズしたライブラリのメソッドではないかなということですね。その部分は以下のサイトでも触れられています。

Unity Community: http://forum.unity3d.com/threads/41177-High-speed-Off-screen-Particles-in-Unity

Unity3D по-русски:http://www.unity3d.ru/distribution/viewtopic.php?f=18&t=5665



ほかにもチャレンジしたプロジェクトはないのかと検索をしたところUnityAnserのほうに寄せられていた質問の中にサンプルのプロジェクトをアップされてる方がおられました。



■UnityAnser:Question about the off screen particle rendering

Hi,

I am trying to show the smoke particles in low resolution texture and then blend back with other parts in the scene. I read the article http://technology.blurst.com/off-screen-particle-optimization/ and make a simple test project inhttps://docs.google.com/open?id=0B1nYEeuWnX0DVHRaaS1uMG1EXzA

But unfortunately, the alpha transparent of particle textures seem not working correctly, they are just showing black. Anyone can help me how to correct this?

Thank you.

Q: オフスクリーンパーティクルを試しているんだけど パーティクルに黒い縁がついてしまうので誰か直してくれない?(意訳


ということらしいです。 ※リンク先からUnityプロジェクトのアーカイブがダウンロードできます




■オフスクリーンパーティクルの手順



no title




1.パーティクル専用のカメラを生成して パーティクルシステムをレイヤー分けして専用カメラのみに描画されるようにします。

2. リプレースメントシェーダー(Off-Screen Particles Replace.shader)によってパーティクルをテクスチャにレンダリングしzバッファともにダウンサンプリングします。 ダウンサンプリングされたZバッファはデプスバッファとしてメインフレームバッファとの合成時に背景と深度比較するために活用します。

これらのコードは OnPostRender() 内に記述します。OnPostRender()はフレームバッファへのレンダリングが終わったあとに呼ばれるメソッドです。

・コンポジットシェーダーOff-Screen Particles Composite.shader)で背景とパーティクルのバッファを合成します。

TestMainCamera.cs


using UnityEngine;
using System.Collections;

public class TestMainCamera : MonoBehaviour
{
public int factor = 2;
public Material blendMaterial;
public Shader HiddenReplaceShader;
public Shader CompositeShader;
public GameObject shaderCamera;
public Camera cam;
public RenderTexture particlesRT;
public RenderTexture source;

void Awake()
{

camera.depthTextureMode = DepthTextureMode.Depth;

particlesRT = RenderTexture.GetTemporary(Screen.width / factor, Screen.height / factor, 0);

}

void OnPostRender()
{

if (!enabled || !gameObject.active || !HiddenReplaceShader)

return;

if (!shaderCamera)
{

shaderCamera = new GameObject("ShaderCamera",typeof(Camera));

shaderCamera.camera.enabled = false;

//shaderCamera.hideFlags = HideFlags.HideAndDontSave;

}

cam = shaderCamera.GetComponent();
cam.CopyFrom (camera);
cam.cullingMask = 1 << LayerMask.NameToLayer("Test");
cam.backgroundColor = Color.black;
cam.clearFlags = CameraClearFlags.SolidColor;
cam.depthTextureMode = DepthTextureMode.None;
cam.targetTexture = particlesRT;
cam.RenderWithShader (HiddenReplaceShader, "RenderType");

Shader.SetGlobalVector("_CameraDepthTexture_Size", new Vector4(camera.pixelWidth, camera.pixelHeight, 0f,0f));    

blendMaterial.shader = CompositeShader;

Vector2 texelOffset = Vector2.Scale(new Vector2(0f,0f), new Vector2(Screen.width, Screen.height));

Graphics.BlitMultiTap(particlesRT, null, blendMaterial, texelOffset);
}


}




Off-Screen Particles Replace.shader



Shader "Hidden/Off-Screen Particles Replace" {
Category {

Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }

AlphaTest Greater .01

Cull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) }

CGINCLUDE

// Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it uses non-square matrices

#pragma exclude_renderers gles
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"

struct appdata {
float4 vertex:POSITION;
float4 texcoord:TEXCOORD0;
float4 color:COLOR;
};

struct v2f {
float4 pos:POSITION;
float3 uvz:TEXCOORD0;
float3 depth:TEXCOORD1;
float4 color:COLOR;
};

uniform sampler2D _MainTex : register(s0);
uniform sampler2D _CameraDepthTexture;
uniform float4 _CameraDepthTexture_TexelSize, _CameraDepthTexture_Size;
uniform float4 _TintColor;

v2f vert(appdata v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.color = v.color;
o.uvz.xy = MultiplyUV(UNITY_MATRIX_TEXTURE0, v.texcoord);

COMPUTE_EYEDEPTH(o.uvz.z);

float3x4 mat = float3x4 (
0.5, 0, 0, 0.5,
0, 0.5, 0, 0.5,
0, 0, 0, 1
);

o.depth = mul(mat, o.pos);

#ifdef SHADER_API_OPENGL
o.depth.xy *= _CameraDepthTexture_Size.xy;
#endif

return o;

}

half4 frag(v2f i):COLOR {
half4 texCol = tex2D(_MainTex, i.uvz.xy);
half4 outCol = i.color * _TintColor * texCol * 2;
#ifdef SHADER_API_D3D9
// Directx is off by half a texel
// so we need to do the projection seperately
i.depth.xy = i.depth.xy/i.depth.z;
// then offset the uvs by 0.5*TexelSize
i.depth.xy += 0.5 * _CameraDepthTexture_TexelSize.xy;
// we also need to flip the y if in directx
i.depth.y = 1 - i.depth.y + _CameraDepthTexture_TexelSize.y;
float z = tex2D(_CameraDepthTexture, i.depth.xy).r;
#else
float z = tex2Dproj(_CameraDepthTexture, i.depth).r;
#endif
float sceneDepth = DECODE_EYEDEPTH(z);
float myDepth = i.uvz.z;
if(sceneDepth < myDepth)

discard;

return outCol;

}

ENDCG

SubShader {

Pass {
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGB
CGPROGRAM
ENDCG
}
Pass {
Blend Zero OneMinusSrcAlpha
ColorMask A
CGPROGRAM
ENDCG
}

}

}

}





一応修正を入れてみました バグといえるほどのものではないのですがシェーダーでアルファチャンネルブレンドを
指定していますが テクスチャ自体にアルファが入っていないのでコンポジットをした時に透明バッファに値が渡らないわけです。
テクスチャを変えなくてもブレンド指定で加算かソフト加算を指定していれば結果は正確になるのですが

コードに素直に従って修正します。

no title

左側テクスチャのアルファ抜きをして右のテクスチャに変更をしました 問題点はそこだけです

bbb


Off-Screen Particles Composite.shader


Shader "Hidden/Off-Screen Particles Composite"
{

Properties
{
_MainTex ("Base (RGB)", RECT) = "white" {}
}

SubShader
{
Pass
{
ZTest Always Cull Off ZWrite Off Fog { Mode Off }

Blend One SrcAlpha

SetTexture[_MainTex] {combine texture}

}

}

Fallback Off



最終的な背景との合成は ”Off-Screen Particles Composite.shader” で行われます
(テクスチャーのコンバインだけの処理ですので説明は省きます。)
背景との合成方法はBlend に続く式で制御します パーティクルのアトリビュートではありません※赤文字部分

ccc

詳しは http://docs.unity3d.com/Documentation/Components/SL-Blend.html を参照してください


■パフォーマンスの結果について
ddd


実際にゲームに組み込んでみたところ 描画速度の向上にはかなり効果が高いようです
ゲームのスクリーン解像度が高くなるほど効果は顕著に現れます。


修正後のプロジェクトファイルをアップロードしました。 プロジェクト内でエフェクト用カメラにパーティクルのみを描画させるためのレイヤーを設定しているのですが パッケージではレイヤーの再設定が必要になるためプロジェクトファイルを圧縮してあります。

http://dl.dropbox.com/u/18978109/TestMixingResolution_re.zip


※ テスト用のスクリプトは多少アバウトに制作されていますので、使い勝手を上げるためにはシェーダーを自動検索させたり カメラを自動登録させたりといった処理は入れたほうがいいと思われます。





追記:
コードを見やすくするスクリプトをブログに組み込んではみたものの ものすごくHTMLの行数を稼いでしまうため
またいつものコードベタ張りになってしまいました。 コードはプロジェクトファイルのものをそのまま掲載していますので、そちらを参考にしてください。
あと不明な点や訪ねたいことがありましたら コメントしていただけると 調べて回答しますのでお気軽にどうぞ。
※ 最近グーグル検索に暗号化が施されるようになって検索ワードが読めないので 記事を作成する方針がたてにくくなってしまっています。

あと 記事が検索にかかりやすくと思ってつけた ”うにばな” ですが  ”うに ランク” などで検索があったりして思わぬ落とし穴でした 水産加工関係の方申し訳ありません (´・ω・`) 

ちなみに管理人はウニ大好きです大好きです


Network View


no title

Compnent ⇛Miscellous⇛NetworkViewでゲームオブジェクト(プレーヤー)にアタッチします

 

プロパティ

State Synchronization      ネットワークビューで使用される 同期の種類

Off:
状態の同期は使用されません。

Reliable Delta Compressed:

状態が変わっていない場合には何も追加されずに送信されます。パケット損失の場合、失われたパケットは自動的に再送信されます

Unreliable:
完了状態が送信されます。より多くの帯域幅を使用しますが、パケットロスの影響が最小限に抑えられます

 

Observed:
ネットワークを経由して送信されるデータ

View ID: このネットワークビューの識別子。

Scene ID:このシーンでネットワークビューのID 番号

Type:実行時 ​​に シーンまたは割り当てのいずれかに保存される

 

Reliable Delta Compressed またはUnreliableのデータ観測コンポーネントが自動的にネットワーク経由で送信されます

パケットは 常に送信された順序で受信されます。パケットが廃棄されている場合は、そのパケットが再送信されます。以前のパケットが受信されるまでそれ以降のすべてのパケットがキューに入れられます。最後のトランスミッションの値と現在の値が異なる場合は送信され 差がない場合は何も送信されません。

 

変換、アニメーション、剛体、またはスクリプト。どのような種類のコンポーネントでも観測できます

(インスペクタから値をobservedへドラッグドロップ)

 

NetworkView.isMine

・・・変数を使用してオブジェクトによって制御されるネットワークビューが送信する自分自身かの判別ができます

 

function OnNetworkInstantiate (info : NetworkMessageInfo) {
    if (networkView.isMine)
        Debug.Log("New object instanted by me");
    else
        Debug.Log("New object instantiated by " + info.sender);
}

 

手動でNetworkIDを設定する方法

●Network.AllocateViewID()

時々Network.Instansiateでセットアップがうまく動作しないことがあり そうした場合自分でNetworkViewIDを

割りつけてやる必要があります。

http://docs.unity3d.com/Documentation/ScriptReference/Network.AllocateViewID.html

 

EX)
var cubePrefab : Transform;
function OnGUI () {
if (
GUILayout.Button("SpawnBox")) {
var viewID =
Network.AllocateViewID();
networkView.
RPC("SpawnBox",
RPCMode.AllBuffered,
viewID,
transform.position);
}
}


@RPC
function SpawnBox (viewID : NetworkViewID, location : Vector3) {
// Instantate the prefab locally
var clone :
Transform;
clone = Instantiate(cubePrefab, location,
Quaternion.identity) as Transform;
var nView :
NetworkView;
nView = clone.GetComponent(
NetworkView);
nView.viewID = viewID;
}
 

送信周期の変更

※ “Edit → Project settings → Network”

 

Sendrate: 1秒間に何回のネットワークメッセージが送られるかの設定。 ※RPCメッセージに影響しません。

(ゲームが処理落ちしない最低限のトラフィックに調整してください)

 

スクリプトの変数の同期

OnSerializeNetworkView (stream : BitStream, info : NetworkMessageInfo)

BitStream ・・・ ステータス及び送信データのセット

isReading ・・・BitStreamがデータ読み込み状態か?

isWriting ・・・BitStreamがデータ書き込み状態か?

 

Serialize ・・・bool, char, short, int, float, Quaternion, Vector3 , NetworkPlayer.型などの値が返る

 

NetworkMessageInfo ・・・ 送信相手は誰か 送信された時間などの情報を受け取れます

timestamp ・・・送信されたメッセージの秒単位でのタイムスタンプ

sender ・・・誰からメッセージが送信されたのか 返り値はNetworkPlayer

 

EX)
var currentHealth : int;


function OnSerializeNetworkView(stream : BitStream, info : NetworkMessageInfo) {
var health : int = 0;
if (stream.isWriting) {
health = currentHealth;
stream.Serialize(health);
} else {
stream.Serialize(health);
currentHealth = health;
}
}
トラフィックの限度:スコープとグループの制限

送信するデータの量の制限によりネットワーク性能を大幅に改善することができます。
マルチプレイの環境ではプレーヤーは、情報のすべてのビットを受け取る必要はありません。
networkviewコンポーネントにはSetScope機能とgroup 設定があります

グループまたはプレーヤーに基づいて情報を送信しない機能です。

 

NetworkView.SetScope (player : NetworkPlayer, relevancy : bool) : bool


開始時 すべてのプレーヤーのためのデフォルトはtrueに設定されます。

たとえばプレーヤーからNetworkViewを設定したオブジェクトが十分遠くにあり情報を受け取る必要がない場合

値をfalseに設定すればNetworkViewを通じたデータ送信は行われません。 ※RPCには作用しません。

 

NetworkView.group ※groupナンバーはint型

すべてのネットワーク・メッセージやRPCの呼び出しで、設定されたグループ番号へ送信します。

※グループ番号の最大は32

function Awake() {
// Send everything from this network view through group 1
networkView.group = 1;
}

グループごとの送信を制限するための関数

SetReceivingEnabled (player : NetworkPlayer, group : int, enabled : bool) : void

・・・データ受信の可否

●SetSendingEnabled (group : int, enabled : bool) : void

・・・データ送信の可否


この2つの関数で 送信・受信の制限をすることができます。 たとえばゲームが32のレベルマップにわかれている場合 プレーヤーの周囲8方向のタイルにだけデータを送信することができます。 FPSなどでは必要ないかもしれませんがUnityのライブラリでMMOなどの大規模なゲームを作成する場合はこの機能が必要になってきます。

Unityエディタのオプション

■ “Edit → Project settings → Network”

Sendrate: 1秒間に何回のネットワークメッセージが送られるかの設定。RPCにはメッセージに影響しない。

                 ゲームが処理落ちしない最低限のトラフィックに調整してください

Debug level: ネットワークデバッグ情報のログ表示切替

■“Edit → Project settings → Player”

Run in background : サーバーをバックグラウンドで実行する

ネットワーク接続のセキュリティ

AES 暗号化, CRCs, ランダム暗号化、SYNCookies 、 RSA暗号化

  ひとつのコードで全てのセキュリティが有効になります

function StartServer ()
{
Network.InitializeSecurity();
Network.InitializeServer(32, 25000);
}

InitializeSecurity()をサーバに一度だけイニシャライズするだけです。15バイト分のパケット送信が追加されます。 

チート対策

ゲームを設計する場合、常に最悪のシナリオを仮定するべきです。
プレーヤーをコードに関して自分と同じだけ知っていると仮定します そして彼らは最悪にネットワーク・パケットの値を編集することができるとします。 したがって、受け取る値をすべて常にチェックします。
チートと格闘するためには特別のコードを必要としません  。 賢いゲーム/ネットワーク設計をするだけです。

プロキシの使用

リンク先を参照のこと

http://unity3d.com/support/documentation/ScriptReference/Network-useProxy.html

ラグの解消 : 予測、extrapolation と interpolation

エネミーにプレーヤー予測と同じ原理を適用することは可能です。
extrapolationは、最後に(バッファーされた)既知の位置、速度および方向でプレーヤーが次のフレームでどこに位置するかを予測します。
interpolationはパケットがクライアントへ行く途中にいつ落とされるかということです。相手は通常休止して新しいパケットが到着する時、最新の位置へ移動します。
あるセット量の時間(100ミリセカンドのような)までにゲームの状態を遅らせることによって、新しい最後の位置を挿入することでこれらの2点間の移動はパケットが落ちても滑らかに見えます。


さらにより正確な同期をさせるためにネットワークsendrateオプションを上げることで対応できます。

次回の記事で補足します

 

Network Loading

ネットワーク通信の間すべてのサーバー/クライアントPCの上で滑らかに動きます。
新しいクライアントがゲーム・ロビー場面で接続している一方で、ゲームを実行するサーバーを持つことができることを意味します。
これはサーバーがクライアントにAllBufferdでゲームオブジェクトの生成を送信をする時を以外問題はありません。
ゲームをロードする間には一時的なクライアント上のネットワーク通信をシャット・ダウンできます。
これはクライアント上で、サーバー接続が成功した直後に Network.isMessageQueueRunning = false; を呼ぶことにより行うことができます。
サーバーは、ネットワーク・グループを賢く使えば多数のゲーム・セッション/複数レベル(同じ場面でも)をhostすることができます。

※ 異なるゲーム・セッションでのプレーヤー間の衝突だけ注意してください。

ネットワーク開発のための外部リソース

ネットワークの知識を深めたい人は見てください

  • http://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
  • http://developer.valvesoftware.com/wiki/Lag_Compensation
  • http://developer.valvesoftware.com/wiki/Working_With_Prediction
  • http://www.gamasutra.com/resource_guide/20020916/lambright_01.htm

    ●   http://202.16.132.23/unity3docsj/Documentation/Documentation/Components/net-HighLevelOverview.html

    『Unityで使える非同期処理のクラスライブラリ(iterator-tasks)を公開しました』

      Aimingの開発者さんのブログ http://developer.aiming-inc.com/

    ここに載せるのはちょっと違うような気もするのですが イテレータを使用して処理を複数のコルーチンに分散化して通信処理の遅延を解消する(たぶんそういうことかと)ライブラリだそうです。

    そこまで遅延したことがないのですが巨大なMMOタイプだと必要になるのかな

    Unityのネットワークサーバ

    マスターサーバー

    マスターサーバーは、ゲームマッチする手助けをします。サーバーを起動する際マスターサーバーに接続し、全てのアクティブなサーバーのリストを提供します。

    http://www.unity3d.com/master-server/index.html

    ●要するにUnityのマスターサーバーはマルチプレイゲームのマッチングを行うサーバーで ゲーム自体はそれぞれのプレーヤーをP2P接続するものということみたいです。最初にゲームを立ち上げたプレーヤのPCがHOSTになり その後ゲームにインしたプレーヤがクライアントになるというわけですね。

    マスターサーバーのカスタム記事はここらへん⇓を参考にしてください (力つきました・・

    http://d.hatena.ne.jp/nyakagawan/20110729/1311933651

    http://d.hatena.ne.jp/shinriyo/20110929

    その他のネットワークミドルウェア

    Unityのネットワーク接続に利用できるミドルウェアのリンクです

  • SmartFoxServer: http://www.smartfoxserver.com/             free
  • Netdog: http://www.netdognetworks.com/                             リンク切れ
  • RakNet: http://www.jenkinssoftware.com/                          収入が800万円(10万ドル)超えたらライセンス料?
  • Photon: http://photon.exitgames.com/                                  free (100CCUまで)
  • ElectroServer: http://www.electrotank.com/es5.html           free      (50CCUまで)
  • Badumna: www.badumna.com                                                16000円(200ドル:最大500CCU)ゲーム一本につき
  • こんにちは

    記事を書いてる途中ですが 所用ができたので中断してます で 更新に間があいてしまったので

    とりあえずアップしておきます

    (ブログのエディタにLiveWriterを使用していますが 保存ファイルを読み直すと書式がぶっ壊れてる仕様に泣かされています ある意味MS製品の通常運転)

     

     

    ●M2H

    http://www.m2h.nl/unity/

    現在ダウンロード出来ませんが わたしがUnityを初めたころ2009年末?にはチュートリアルなどのPDFファイルがフリーで公開されていました 現在はアセットストアのほうで$85でご提供なようです。 世の中おカネです

    http://www.scribd.com/doc/38400039/M2H-Unity-Networking-Tutorial

    当時のフリーのPDFと同じ物がここにアップされているようです。今回はこの情報をふまえて加筆修正してみます

     

    http://www.slideshare.net/ShinsukeSugita

    ネットワーク周りに関して こちらのスライドが上手くまとまっているようなので まとめかたを参考にさせていただきました




    その他 くわしくは後日webで



    ネットワークの状態

     

    ●Network.peerType

    ・・・接続状態(ピアタイプ)のステータス、サーバーまたはクライアントで接続しているかの判定をします

    NetworkPeerType. Connecting ・・・ ネットワーク接続中

    NetworkPeerType. Disconnected ・・・ ネットワーク切断中

    NetworkPeerType. Server    ・・・ サーバーとして接続

    NetworkPeerType. Client ・・・ クライアントとして接続

     

    EX)

    function OnGUI() {
    if (Network.peerType == NetworkPeerType.Disconnected)
    GUILayout.Label("Not Connected");
    else if (Network.peerType == NetworkPeerType.Connecting)
    GUILayout.Label("Connecting");
    else
    GUILayout.Label("Network started");
    }
    サーバの初期化

    Network.InitializeServer (connections : int, listenPort : int, useNat : boolean) : NetworkConnectionError

    (接続数、ポート番号, NATパンチスルー機能のオンオフ)

    function LaunchServer () {
    Network.incomingPassword = "HolyMoly";
    var useNat = !Network.HavePublicAddress();
    Network.InitializeServer(32, 25000, useNat);
    }

    接続数は接続が許可された着信接続(一般的にプレーヤーの数と同じではないことに注意)の数です。

    ListenPortは使用したいポート番号です。

    useNatは NATのパンチスルー機能を設定します。NATのパンチスルー機能を使用して接続を受け入れることができるようにしたい場合は、この属性をtrueに設定します。

    NAT接続 (Network.useNat)

    NATのパンチスルーについての解説(英文)

    http://www.raknet.net/raknet/manual/natpunchthrough.html


    NATについての詳細は、次のリンク先を見てください

    http://unity3d.com/support/documentation/Components/net-MasterServer.html

     

    『NAT(Network Address Translation)/NAPT(Network Address and Port Translation)とは』

    http://www.nic.ad.jp/ja/basics/terms/nat_napt.html

    NAT(Network Address Translation)とは、ある範囲のIPアドレスを別の範囲のIPアドレスと対応付け、 送受信する IPパケットのヘッダ部のIPアドレスを、対応付けられた範囲で変換する技術です。 NATは、プライベートアドレスとグローバルアドレスを相互に変換する用途によく使用されます。

    具体的には、IPパケットのヘッダ部の送信元アドレスがプライベートアドレスである場合に、 その送信元アドレスをグローバルアドレスに書き換えます。 また、該当グローバルアドレスを宛先アドレスとする応答パケットについて、 宛先アドレスをプライベートアドレスに変換します。 (以下本文にて

     

    サーバへの接続

     

    サーバ側    

    ●OnServerInitialized()

    ・・・ サーバ初期化され準備が出来た時に実行されます

    ●OnPlayerConnected (player : NetworkPlayer)

    ・・・ クライアントのプレーヤが接続した時に実行されます

    private var playerCount: int = 0;
    function OnPlayerConnected(player: NetworkPlayer) {
    Debug.Log("Player " + playerCount++ +
    " connected from " + player.ipAddress +
    ":" + player.port);
    // Populate a data structure with player information ...
    }

    OnPlayerDisconnected (player:NetworkPlayer)

    ・・・ クライアントのプレーヤが切断した時に実行されます

    function OnPlayerDisconnected(player: NetworkPlayer) {
    Debug.Log("Clean up after player " + player);
    Network.RemoveRPCs(player);
    Network.DestroyPlayerObjects(player);
    }

    クライアント側      

     

    ●Network.Connect (IP : String, remotePort : int, password : String = "")

    ・・・指定されたホスト(IPまたはドメイン名)とサーバー・ポートに接続します。

    function ConnectToServer () {
    Network.Connect("127.0.0.1", 25000);
    }

    ●Network.Disconnect (timeout : int )

    ・・・サーバーからの切断 timeout:切断までの待ち時間

    function OnGUI() {
    if (GUILayout.Button ("Disconnect")) {
    Network.Disconnect();
    MasterServer.UnregisterHost();
    }
    }

    ●OnConnectedToServer()

    ・・・サーバー接続に成功した時に実行されます

    function OnConnectedToServer() {
    Debug.Log("Connected to server");
    // Send local player name to server ...
    }

    ●OnDisconnectedFromServer (mode : NetworkDisconnection)

    ・・・サーバーから切断された時に実行されます

    function OnDisconnectedFromServer(info : NetworkDisconnection) {
    if (Network.isServer) {
    Debug.Log("Local server connection disconnected");
    }
    else {
    if (info == NetworkDisconnection.LostConnection)
    Debug.Log("Lost connection to the server");
    else
    Debug.Log("Successfully diconnected from the server");
    }
    }
    ●OnFailedToConnect (error : NetworkConnectionError)

    ・・・サーバーへの接続失敗

    function OnFailedToConnect(error: NetworkConnectionError) {
    Debug.Log("Could not connect to server: "+ error);
    }
    オブジェクトの生成 と 破壊

    Network. Instansiate()

    ・・・ネットワーク越しのオブジェクトの生成

    Instantiate (prefab : Object, position : Vector3, rotation : Quaternion, group : int) : Object

    EX)
    // Immediately instantiate new connected player's character
    // when successfully connected to the server.

    var playerPrefab : Transform;
    function OnConnectedToServer () {
    Network.Instantiate(playerPrefab, transform.position, transform.rotation, 0);
    }
     

    ●Network. Destroy()

    ・・・ネットワーク越しのオブジェクトの破壊
    EX)
    var timer : float = 0;
    function Awake () {
    timer = Time.time;
    }
    // Network destroy the object which has this script
    // it must have a NetworkView attached
    function Update() {
    if (Time.time - timer > 2) {
    Network.Destroy(GetComponent(NetworkView).viewID);
    }
    }
     
    var timer : float = 0;
    function Awake () {
    timer = Time.time;
    }
    // Network destroy the object which has this script
    function Update() {
    if (Time.time - timer > 2) {
    Network.Destroy(gameObject);
    }
    }
     

    RPC buffer によるネットワーク越しのオブジェクトの破壊:


    function OnNetworkInstantiate(info: NetworkMessageInfo) {
    Debug.Log(networkView.viewID + " spawned");
    if (Network.isServer) {
    Network.RemoveRPCs(networkView.viewID);
    Network.Destroy(gameObject);
    }
    }
    RPC(RemotePrecedureCall) ・・ 遠隔スクリプトの呼び出し
     Unityのネットワークを介してスクリプトをリモートで呼び出すことができます。

    ※この関数は 送信側と供給側の両方に存在する必要があります。

    RPCコールで送ることができる変数の種類

  • int
  • float
  • string
  • NetworkPlayer
  • NetworkViewID
  • Vector3
  • Quaternion

    RPCファンクションを有効にするには javascriptなら”@RPC" C#なら”[RPC]”をファンクションの前につけます

    EX)
    networkView.RPC ("PrintText", RPCMode.All, "Hello world");
    @RPC function PrintText (text : String, info : NetworkMessageInfo) { Debug.Log(text + " from " + info.sender); }
     
    NetworkView.RPC (name : String, mode : RPCMode, params args : object[])

    (”ファンクションネーム”, RPCモード, viewID, transform.positionなどの値)

     
    EX)
    var cubePrefab : Transform;
    function OnGUI () {
    if (GUILayout.Button("SpawnBox")) {
    var viewID : NetworkViewID= Network.AllocateViewID();
    networkView.RPC("SpawnBox", RPCMode.AllBuffered, viewID, transform.position);
    }
    }


    @RPC
    function SpawnBox (viewID : NetworkViewID, location : Vector3) {
    // Instantate the prefab locally
    var clone : Transform;
    clone = Instantiate(cubePrefab, location, Quaternion.identity) as Transform;
    var nView : NetworkView;
    nView = clone.GetComponent(NetworkView);
    nView.viewID = viewID;
    }
     

    RPCModeの種類

    RPCMode.Serverサーバーだけに送信
    RPCMode.Others送信者を除く全体に送信
    RPCMode.OthersBufferedBufferedモードで送信者を除く全体に送信
    RPCMode.All送信者を含む全体に送信
    RPCMode.AllBuffered Bufferedモードで送信者を含む全体に送信
     ●Buffered とは 

    バッファーを用いた送信方法です。新規プレーヤーが接続する場合に 新規プレーヤーがこのメッセージを受け取ります。

    ●たくさんのプレーヤーを生成するのに有用です。

  • Unite2012の講義内容をまとめました

    元ネタは

     

    『Performance Optimization Tips And Tricks For Unity』

                    Jonas Echterhoff & Kim Steen Riber

    unite2012 perfomance

    http://video.unity3d.com/video/6957357/unite-2012-performance

     

    なのですが GPUの最適化に関しては、ほぼ ?にまとまっていました(ただし英語

    http://docs.unity3d.com/Documentation/Manual/OptimizingGraphicsPerformance.html

    シェーダ解説で一度解説したような気もするので 8月頃の記事を参照してください

    忙しくて見れていなかったための自分用まとめですので すでに見た方はスルーしてください

     

     

     

    『Unityのパフォーマンスの最適化 TIPSと方策』

     

    プロファイラを見てピークに注目!

    ●スクリプトの最適化

    ●プログラムのアルゴリズムの最適化101 (ここではすべてを解説しません)

    ●見えているオブジェクトに対してスクリプトを削ることができるかもしれません

    OnBecameVisible,OnBecameInvisible を使用して callbackし無駄にスクリプトを使用しないようにします。

     

    ●毎フレーム必要のないUpdateを呼ぶよりも コルーチンを使用しましょう

    //毎フレーム呼び出し
     
    void Update() {
     
    }
     
    //0.2秒間隔での呼び出し
     
    IEnumrator Start() {
     
       while(true) {
     
            yield return new WaitForSeconds (0.2f);
     
       }
     
    }
     

    ● UnityエンジンのAPIメソッドが毎フレームの呼び出しをする代わりに 結果を保持するように考慮してください

    これは C#におけるゲッタープロパティに当てはまります

    たとえば Transform.positionはグローバルPosition の階層を繰り返し呼び出します

     

    ■メモリーの最適化

    ●メモリの種類

    Mono Memory

    ●Script Object

    ● Wrappers for

    ●Game Object

    ● Asetts

    ●Components

    Garbage collected

    Unity Internal Memory

    ●Asset data

    ●Textures,meshs,animation,etc。

    ●GameObjects

    ●Internals (Rendering,particles,physic,etc)

     

     

    ●Monoが割りつけたヒープブロック

    ●実行時に必要となったヒープサイズのブロックを追加する

    ●フラグメンテーション(メモリの分断)はメモリが消耗していないとしても新しく追加されたヒープブロックによって生じます

    ●ガベージコレクターがクリーンをおこうなうとき

    ヒープブロックを利用可能なメモリのサイズに割付けられなかった時

    System.GC.Collect()ガベージ・コレクタを明示的に動作させます が 処理不可が高いので実行は注意

     

    class MyClass{
     
      public int a,b,c;
     
    }
     
    struct MyStruct{
     
     public int a,b,c;
     
    }
     
    void Update () {
     
      //Bad  アロケートメモリがヒープメモリ上に発生し あとでガベージコレクトをすることになる
     
      MyClass.c    = new MyClass();
     
     // Good アロケートメモリはスタック上に発生し ガベージコレクションが発生しない
     
      MyStruuct  s = new MyStruct();
     
     

          注意) この意味合いは 作業メモリの拡張方法なのですが ヒープメモリの場合はMONOが自由にメモリを管理して

    割り付けることで内部的にはメモリ中の開いたところにバラバラに管理され 作業メモリへのインデックスを保持しています。使用後のメモリはガベージ(ごみ)となって残るために一定時間ごとに圧縮(ヒープソート圧縮)を行ってメモリを開放する必要があります。

    それに対しスタックメモリはレジスタを使用してメモリを格納順に積み上げる(スタック)して使用後は最後に積んだメモリから開放します。そのため大規模なソートを行わないので遅延が発生しません。 一番近いイメージはJavaの配列やジェネリック関数のリスト構造でしょうか ちょっと違う?

     

    ●あなたのやり方でメモリマネージを実装する場合 再利用不能なクラス を割り付ける前にリストを使用してみてください

    ●オブジェクトプールの実例はアセットストアで『Astro Dude』を見つけてください

    ●インスタンス処理は重たいです

    ●オブジェクトの事前読み込みを使用しましょう

    ●再び登場させるオブジェクト(bullet、Explosionなど)GameObject を最適化する時にInstantiateDestroyの代わりに

    inactiveのリストにして保持します。

     

    EX1はint型を何度も宣言していて メモリ効率が悪いで例です。

    EX1)

    Public class AnAllocatingWorker {  
    class WorkData {  
    public int value  = 1; 
    } 
    WorkData CreateWorkData(){    
    return new WorkData(); 
    } 
    void ProcessWorkData(WorkData data){ 
    int[] TempWorkBuffer = new int[128*1024]; TempWorkBuffer[0] = data.value; 
    } 
    public void Update() {  
    ProcessWorkData(CreateWorkData());; 
    } 
    }
     

    EX2)

    Public class AnAllocatingWorker {  
    class WorkData {  
    public int value  = 1; 
    } 
    WorkData CreateWorkData(){    
    return new WorkData(); 
    } 
    int[] TempWorkBuffer = new int[128*1024]; 
    void ProcessWorkData(WorkData data){ 
    TempWorkBuffer[0] = data.value; 
    } 
    public void Update() {  
    ProcessWorkData(CreateWorkData());; 
    } 

     

     

    ●UnityのビルトインGUIシステムをゲームに使用しないでください ガベージコレクションと相性がよくありません

    ●ストリーミングしないゲームではいつもゲーム中にアロケーションが発生するわけではありません

    ●GetRuntimeMemorySize(Object) を使用します。 GetMonoHeapSize と GetMonoUseSize を使用してメモリ使用量を追跡します。

    ●メッシュコライダーよりもプりミティブなコライダーのほうが最適化に良好です

    Time.fixedDeltaTime (project settings ->Time)  の設定をします。おそらくゆっくり動くゲームの時はfixedUpdatesよりも良い結果をもたらします

     

    ●最も一般的なパフォーマンス低下の落とし穴はphysicsです

    ●けして動くことのない静止したコライダー(例えば リジッドボディを伴わないコライダー)

    ●プロファイラーで『Static Collide.Move』で表示されるものですが プロセスは物理演算を行なっています

     

    ●GPUとCPUの限界までスピードをあげられるのか

    ●GPUのパフォーマンスはレンダリングされるピクセルの最大数とメモリの帯域幅で決定されます(フィルレート)

    ●CPUのパフォーマンスは ドローコール処理の上限にしばられることがあります

     

    ●GPUプロファイラはドローコールあたりの消費時間を見つけることに役立ちます

    ●ドローコールを解消することでGPUとCPU両方のレンダリング処理が軽減されます。最初にできる限りのドローコールを削減してみましょう

    ●その結果 オブジェクトを高速にレンダリングするにはどうすればいいいかを知ることができます

     

    ●少数のオブジェクトでレンダリングすることでパフォーマンスは改善します

    ●シーンを簡略化する

    ●積極的にカリング(オクルージョンかリング、円錐台カリング)を使用する

    ●LODを使用する

      注意)現在主流のGPUでは1ピクセル中にあまりに多くのポリゴンが集中すると処理落ちが発生するようです。そこで積極的にLOD

          (少ないポリゴンのモデルを段階ごとに持つ)をすることでカメラから遠距離にポリゴン数の多いモデルが表示されないようにす  る必要があるようです。

    ●パフォーマンス改善のためにシェーダーパスを削減します

    ●シーンセットアップ時にパスの少ないシェーダーを選択する(リフレクション。シャドー。ピクセルライトはフォワードレンダリングにおいてすべてのパスが加算されます)

    ●フォワードレンダーのピクセルライトは低速です。可能なかぎりリアルタイムライティングを避けてライトマッピングを使用しましょう

    ●ピクセルライトの数をクオリティセッティングで調節します。

    ●CPUパフォーマンスはドローコール処理の上限に影響されます

    ●注意:現在のハードウェアではフレームあたりのドローコールはモバイルで数百、デスクトップで数千を超えないようにしてください


    ●ドローコールを減らすために 近接するオブジェクトはひとつのメッシュにまとめ 一緒に描画されるようにします。

    ●手動ではソースアセットの管理

    ●自動ではUnityのドローコールバッチを使用します → ドローコールバッチのリファレンス

    「dynamic batching」について。unity3dfan @ ウィキ http://www38.atwiki.jp/unity3dfan/pages/42.html 

       注意)Unityは自動で900頂点(UV保持時は300頂点)までのポリゴンを自動でひとまとめに処理するダイナミックバッチと呼ばれる機能が搭載されていまあす。 マテリアルとテクスチャはひとつにまとめておくことが条件です。 ほかにスタティックバッチ インスペクタの右上のstaticのチェックをいれることで機能するものもあります。これは背景などの静止物に主に使用します。

    ●メッシュの中に含まれる異なるマテリアルはなるべく少なくしてください

    ●可能ならばテクスチャのアトラス化をしてください  注(アトラス化 複数のテクスチャを一枚のテクスチャにまとめること)

    ●多くのオブジェクトが複数のライトの影響を受けているとか 効率良くカリングを行わないとドローコールバッチはパフォーマンスを悪化させてしまいます 

     

    ●GPUのパフォーマンスはレンダリングされるピクセルの最大数とメモリの帯域幅で決定されます(フィルレート)

     ●フィルレートの限界を知ることは簡単です。高速にゲームを動かした時ディスプレイ解像度が減少しますか? もしそうなるならそれがフィルレートの限界です

     ●同様に、クオリティセッティングでテクスチャクオリティを下げてみます。ゲームをが早くなるときは そこがおそらくメモリの帯域限界です。

     ●フィルレートが限界ならば最適化としてシェーダーを簡略化してみましょう

     

    ●モバイルのGPUの時:アルファテストを除外します。

    ●簡潔で整理されたシェーダコードをつかいましょう(たとえばUnityに付属の『Mobile』シェーダーのような)

     

    ●シェーダーコードの最適化:

    ● 効率の悪い関数を避けます(pow,exp,log,cos,sin,tan,など)。テクスチャ行列の事前計算も考慮してみます

    ●モバイルの場合:可能な限り低精度の変数を使用する(Cgにおけるfloat,half,fixed)

     

    ●もしメモリ帯域の限界ならばテクスチャメモリを減少させます

    ●テクスチャ圧縮を16ビットに

    ●テクスチャサイズを縮小(シーンビューンのレンダーモードのミップマップのチェック)

    ●テクスチャにミップマップを設定する。

    ●複雑なジオメトリによってもGPUのパフォーマンス限界はもたらされます

    ●必要以上のポリゴントライアングルは使用しない

    ●UV継ぎ目とハードエッジ(頂点に複数の法線)は可能な限り減らす

    ●シンプルなシェーダーを使用しましょう

     

     

    ■最適化に関する下記の項目も参照してみてください

    Draw Call Batching

    Shader Performance page.

    Modeling Characters for Optimal Performance




    ※2014 8.16 うにばな 講座みたいなもの番外編(高速化(最適化)について3 モバイル系                      投稿しました よろしければ参考にどうぞ 

    Cgでシェーダのプロパティにアクセスする


    シェーダは、プロパティブロック内でプロパティを宣言します。それらのプロパティにアクセスする場合は、Cgのシェーダプログラムを、同じ名前と一致するタイプでCg変数を宣言する必要があります。


    例は提供されている頂点プログラムとフラグメントプログラム:シェーダーチュートリアル


    http://docs.unity3d.com/Documentation/Manual/ShaderTut2.html


    たとえば、これらのシェーダのプロパティは:


    _MyColor ("Some Color", Color) = (1,1,1,1) 
    _MyVector ("Some Vector", Vector) = (0,0,0,0)
    _MyFloat ("My float", Float) = 0.5
    _MyTexture ("Texture", 2D) = "white" {}
    _MyCubemap ("Cubemap", CUBE) = "" {}

    としてCgコードにアクセスするために宣言されます。


    float4の_MyColor
    float4の_MyVector
    floatの_MyFloat;
    sampler2Dの _MyTexture
    samplerCUBEの _MyCubemap

    Cgはまた必須ではありませんが uniformを受け入れることができ、


    uniform float4 _MyColor。

    Cgは変数の型は、この方法にShaderLabマップのプロパティの型:



    • ColorとVectorのプロパティにマップするfloat4。

    • RangeとFloatプロパティにマップするfloat。

    • Textureのプロパティにマップするsampler2D 通常の2Dテクスチャのための変数。

    • CUBEとRECTtexturesマップのための samplerCUBEとsamplerRECTそれぞれの変数。


    頂点プログラムに頂点データを転送


    http://docs.unity3d.com/Documentation/Components/SL-ShaderPrograms.html


    Cgの頂点プログラム、頂点データは構造体として渡される必要があります。いくつかの一般的に使用される頂点の構造体で定義されている UnityCG.cgincファイルが含まれており、ほとんどのケースでは、それらを使用するだけで十分です。構造は次の通りです。



    • appdata_base:頂点座標と、法線と ひとつのテクスチャ座標で構成されています。

    • appdata_tan:頂点座標、接線、法線と ひとつのテクスチャ座標で構成されています。


    たとえば、このシェーダの色は、メッシュはそれの法線に基づいておりappdata_baseを頂点プログラム入力として:


    Shader "VertexInputSimple" {
    SubShader {
    Pass {
    CGPROGRAM
    #pragma vertex vert
    #include "UnityCG.cginc"
    struct v2f {
    float4 pos : SV_POSITION;
    fixed4 color : COLOR;
    };
    v2f vert (appdata_base v)
    {
    v2f o;
    o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    o.color.xyz = v.normal * 0.5 + 0.5;
    return o;
    }
    ENDCG
    }
    }
    }

    別の頂点データにアクセスしたい場合は、頂点の構造を自分で宣言する必要があります。構造体のメンバーがでなければなりません


    以下 構造体のリスト:



    • float4 vertex 頂点の位置

    • float3 normal 頂点の法線

    • float4 texcoord 最初のUV座標

    • float4 texcoord1 第二のUV座標

    • float4 tangent 接線ベクトル(法線マッピングに使用されます)

    • float4 color 頂点単位の色


    ShaderLab構文:Pass


    Passブロックはオブジェクトのジオメトリを一度レンダリングします。


    構文


    Pass { [Name and Tags] [RenderSetup] [TextureSetup] }
    基本的なパス・コマンドは、、レンダリングのセットアップコマンドのオプションのリストに続いて使用するテクスチャのオプションのリストが含まれています。

    Name and tags


    パスは名前と任意の数のタグで定義することができます。名前/値の文字列はPassをレンダリングエンジンに渡す意図で使用されます。


    Render Setup


    パスは、グラフィックスハードウェアのさまざまな状態を設定します。例えば、アルファブレンディングは、フォグが使用されるときオンにする必要があります。それぞれコマンドは以下のとおりです。


    Material { Material Block }
    頂点ライティングパイプラインで使用するマテリアルを定義します。詳細についてはマテリアルのページを参照 http://docs.unity3d.com/Documentation/Components/SL-Material.html
    Lighting On | Off
    頂点ライティングをオンまたはオフにします。詳細についてはマテリアルのページを参照
     Cull Back | Front | Off
    ポリゴンカリングモードを設定します。
    ZTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always)
    深さのテストモードを設定します。
    ZWRITE ON | OFF
    深さ(Zデプス)の書き込みモードを設定します。
    Fog { Fog Block }
    フォグのパラメータを設定します。
    AlphaTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always) CutoffValue
    アルファテストが有効になります。
    Blend SourceBlendMode DestBlendMode
    アルファブレンディングモードを設定します。
    Color Color value
    頂点ライティングがオフになっている場合に使用する色を設定します。
    ColorMask RGB | A | 0 | any combination of R, G, B, A
    色書き込みマスクを設定します。ColorMask 0書き込むとすべてのカラーチャンネルのレンダリングをオフにします。
    Offset OffsetFactor , OffsetUnits
    オフセットの深さを設定します。
    SeparateSpecular ON | OFF
    頂点ライティングのための独立したスペキュラカラーをオンまたはオフにします。詳細についてはマテリアルのページを参照。 http://docs.unity3d.com/Documentation/Components/SL-Material.html
    ColorMaterial AmbientAndDiffuse | Emission
    頂点ライティングを計算するときに頂点単位の色を使用します。詳細についてはマテリアルのページを参照。http://docs.unity3d.com/Documentation/Components/SL-Material.html

    テクスチャーのセットアップ


    レンダリングステートの設定後に、SetTextureのコマンドを使用して適用するテクスチャとそのコンバインモードの数を指定することができますhttp://docs.unity3d.com/Documentation/Components/SL-SetTexture.html


    SetTexture texture property { [Combine options] }


    テクスチャーのセットアップは固定機能マルチテクスチャパイプラインを設定しますが、カスタムのフラグメントシェーダが使用されている場合無視されます。http://docs.unity3d.com/Documentation/Components/SL-ShaderPrograms.html


    細部


    Per-pixel Lighting (ピクセル単位のライティング)

    ピクセル単位のライティングパイプラインは複数のパスでオブジェクトをレンダリングすることによって動作します。Unityは、環境光との任意の頂点ライトを取得するために一度オブジェクトをレンダリングしそれから、別々に追加されたパス内のオブジェクトに影響を与える各ピクセルのライティングをレンダリングします。パイプラインのレンダリング詳細を参照してください。http://docs.unity3d.com/Documentation/Components/SL-RenderPipeline.html


    Per-vertex Lightig (頂点単位のライティング)

    頂点単位のライティングは、各頂点に対して計算されている標準Direct3D/OpenGL照明モデルです。


    Lighting onでON状態になります。照明によって影響されるMaterialブロックColorMaterialとSeparateSpecularコマンドを使用します。詳細についてはマテリアルのページを参照。


    以下も参照してください


    共通の機能を再利用したり、さまざまなハイエンドなエフェクトを実装するために使用できるいくつかの特別なパスがあります。



    • UsePass 別のシェーダから指定された名前のパスが含まれています。


    http://docs.unity3d.com/Documentation/Components/SL-UsePass.html



    • GrabPass 後のパスで使用するために、テクスチャに画面の内容をつかむ。


    http://docs.unity3d.com/Documentation/Components/SL-GrabPass.html 


    ShaderLab syntax: SubShader Tags




      • Background -このレンダーキューは、任意の他の人の前にレンダリングされます。これは、スカイボックスなどに使用されます。

      • Geometry (デフォルト) -ほとんどのオブジェクトに使用されます。不透明なジオメトリは、このキューを使用しています。

      • AlphaTest -アルファテストされたジオメトリはこのキューを使用しています。すべてのジオメトリオブジェクトが描画された後、アルファテストされたオブジェクトをレンダリングする方が効率的なのです。

      • Transparent -このレンダリング・キューはGeometry とAlphaTestの後に描画され 後ろから手前に向かって描画されます。アルファブレンド(深度バッファへの書き込みのないもの 例えばガラス、パーティクルエフェクト)がここに書き込まれます。

      • Overlay -このレンダーキューはオーバーレイ効果を意図しています。最後にレンダリングされたもの(レンズフレアなど)はここに書き込まれる必要があります。



    Shader "Transparent Queue Example" {
    SubShader {
    Tags {"Queue" = "Transparent" }
    Pass {
    //シェーダの本体 }
    }
    }

    シェーダのパフォーマンス向上


    必要なものだけを計算するようにします。たとえば マテリアルごとに色を割りつけられるようにすれば柔軟なシェーダになりますが、常に白に設定しておくことで計算が軽くなりレンダリング能力が向上します。

    頂点シェーダに比べてピクセルシェーダは大変多くのピクセルを演算しなければならないため頂点シェーダの中でピクセルシェーダの計算を移動して行ったほうが処理負荷が軽減できます。 またシェーダ外部のスクリプトで計算された値をシェーダに設定することでも同様に処理が軽くなります。


    一般的なサーフェスシェーダ

    サーフェスシェーダは照明との対話シェーダを書くために最適です。しかし、そのデフォルトのオプションは、 "一般的ケース"に調整されています。多くのケースでは、シェーダの実行速度を向上させたり、サイズを小さくするために、それらを調整することができます。

    approxview ビュー方向(鏡面など)を使用してシェーダのディレクティブは、ビュー方向ではなく、ピクセルごとの正規化された頂点ごとになります。これは時に十分良い効果があります。

    halfasview スペキュラシェーダタイプも速くなります。ハーフベクトル(照明の方向とビューベクトルとの中間のベクトル)を計算され頂点ごとに正規化されます。ライティング機能はビューベクトルの代わりにハーフベクトルを受け取ります。

    noforwardadd シェーダが完全に前方レンダリングでディレクショナルライトを一つだけサポートするようになります。残りのライトは頂点ごとに光や球面調和関数としての効果を持つことができます。これは、シェーダを小さくし、複数のライトが存在して 1パスでレンダリングを確認するために最適です。


    noambientは、周囲の照明や シェーダ上の球面調和ライトを無効にします。これは若干速くなる可能性があります。


    ●計算の精度
    CG / HLSLでシェーダを作成するとき、3つの基本的な種類の数値があります:float、harfとfixed(同様に、それらのベクトル・行列、例えばhalf3、float4x4 など)

    ●float:高精度浮動小数点。一般的に32ビット、普通のプログラミング言語のfloat型。

    ●half:培地精度浮動小数点。精度は-60000から60000 3.3桁の範囲で、一般的に16ビット。

    ●fixed:低精度の固定小数点。-2.0から2.0の範囲と256分1の精度で、一般的に11ビット。

    可能な限り最小の精度を使用します。これは、iOSやAndroidなどのモバイルプラットフォーム上で特に重要です。例えば以下のとおり

    ●色と単位長さベクトルについては、fixedを使用。
    ●範囲と精度が良好である場合はharfを使用、それ以外の場合floatを使用します。
    モバイルプラットフォームでは、フラグメントシェーダ内で可能な限り低精度を維持することです。ほとんどのモバイルGPU上で、(lowp /fixed)低精度型にswizzleを適用する場合 fixed/ lowpと高精度タイプ間の変換の場合などは非常に演算コストがかかります。

    swizzleの動作は"xy" を "xyyy", "wz" を "wzzz”に変換するなど

    ●アルファテスト

    固定機能であるAlphaTestや同等な機能clip()はプラットフォームによりパフォーマンスに差異があります。

    一般的にはほとんどのプラットフォームでは完全に透明なピクセルをカリングすることは小規模な利点ですが IOSおよびいくつかのAndroidデバイスで採用されているPowerVRの GPU上でのアルファテストは非常に負荷が高いです。そこで "パフォーマンスの最適化"としてこれを使用しないと描画が遅くなります。

    ●カラーマスク

    いくつかのプラットフォーム(モバイルGPUなど)上で使用して、ColorMaskを用いていくつかのチャネルを除外することで、描画速度の向上が期待できます。





    ShaderLab 組み込みの値


    Unityは、シェーダのための組み込みの値をいくつか提供しています。現在のオブジェクトの変換行列、時間などです。


    あなたが他のプロパティを使用したようにするだけでShaderLabでそれらを使用することができます、唯一の違いは、組込されている値のためを宣言する必要がないことです。
    組み込み値を使用する際プログラマブルシェーダに”UnityCG.cginc”を含む必要があります


    http://docs.unity3d.com/Documentation/Components/SL-ShaderPrograms.html


    ●Transformations


    float4x4 UNITY_MATRIX_MVP現行モデル*ビュー*射影行列
    float4x4 UNITY_MATRIX_MV現在のモデル*ビュー行列
    float4x4 UNITY_MATRIX_P現在の射影行列
    float4x4 UNITY_MATRIX_T_MVモデル*ビュー行列の転置
    float4x4 UNITY_MATRIX_IT_MVモデル*ビューの逆行列
    float4x4 UNITY_MATRIX_TEXTURE0 to UNITY_MATRIX_TEXTURE3テクスチャ変換行列
    float4x4 _Object2World現在のモデル行列
    float4x4 _World2Object現在のワールド行列の逆行列
    float3 _WorldSpaceCameraPosカメラのワールド空間の位置
    float4 unity_Scalexyzのコンポーネントが使用されていない; 。wは、一様にスケーリングされたオブジェクトのスケールを含んでいます。

    ●Lighting

    例えばライトモデル*ライトカラーは次のとおりです。プレーンShaderLabでは、末尾にゼロを付加することにより、次のプロパティにアクセスする_ModelLightColor0。Cgのシェーダで、それらは単一の要素を持つ配列として公開され、Cg同じように_ModelLightColor [0]



    UNITY_LIGHTMODEL_AMBIENT
    現在のアンビエントカラー。

    Name Type Value


    _ModelLightColor float4 Materialのメインカラー * Lightカラー


    _SpecularLightColor float4 Materialのスペキュラカラー * Lightカラー


    _ObjectSpaceLightPos float4 オブジェクト空間でのライトの位置. wコンポーネント


    は ディレクショナルライトの場合0、それ以外のライトは1 。


    _Light2World float4x4 ワールド空間行列でのライト座標


    _World2Light float4x4 ライト空間行列へワールド座標


    _Object2Light float4x4 ライト空間行列へのオブジェクト座標


    Various



    • float4 _Time : Time (t/20, t, t*2, t*3),シェーダ内でアニメーションをするために使用

    • float4 _SinTime : Sine of time: (t/8, t/4, t/2, t)

    • float4 _CosTime : Cosine of time: (t/8, t/4, t/2, t)

    • float4 _ProjectionParams :

      xは反転射影行列を使用してレンダリングする場合は負、1.0または-1.0 、yはカメラのnearplaneでzはカメラのfarplaneであるwは1/FarPlaneです。

    • float4 _ScreenParams :

      xは現在のレンダーターゲットのピクセル単位の幅です。yは現在のレンダーターゲットのピクセル単位の高さzは、 1.0 + 1.0/widthですwは 1.0 + 1.0/heightです。


    GLSLシェーダプログラム


    CG / HSLシェーダプログラムの使用に加えて、OpenGLシェーディング言語(GLSL)シェーダを直接書き込むことができます。


    しかし、GLSLの使用は、Mac OS XやOpenGL ES 2.0互換のモバイルデバイスを対象としています。たいていの場合、Unityは、CG / HLSLを最適化されたGLSLにクロスコンパイルします(これはモバイル・プラットフォームのデフォルトで行われ、必要に応じてデスクトッププラットフォーム用に#pragma GLSLを記述することでオンにすることができます)。


    GLSLスニペット


    GLSLプログラムのスニペットは、GLSLPROGRAMとENDGLSLキーワードの間に書かれています


    GLSLでは、シェーダ関数のエントリポイントはmain()関数で定義されます。


    UnityがGLSLシェーダをロードするとき、各GLSLスニペットで#ifdef VERTEX .. #endifと#ifdefのFRAGMENT .. #endifの。頂点プログラムとフラグメントプログラムの両方を含める必要があります。


    インクルードファイルは、.glslinc拡張子で提供される UnityCG.glslincファイルです。



    その他: Unityに内蔵されているシェーダのソースに関しては↓からダウンロードしてください。

    http://www.unity3d.com/support/resources/assets/built-in-shaders

    ↑このページのトップヘ