70
ShadowGun Sample Level かかかかかかかかかかかか かかかか Aiming かかかかかかかかかかかかかか かかかか 2012/06/01

Shadow gunのサンプルから学べるモバイル最適化

Embed Size (px)

Citation preview

Page 1: Shadow gunのサンプルから学べるモバイル最適化

ShadowGun Sample Level から学べるモバイル最適化

株式会社 Aimingリードソフトウェアエンジニア

牧野克俊2012/06/01

Page 2: Shadow gunのサンプルから学べるモバイル最適化

自己紹介• オンラインゲームを長年作ってきま

した• 主にサーバや通信部分担当です!• クライアントや 3D は自信ないです

Page 3: Shadow gunのサンプルから学べるモバイル最適化

でもがんばって解説します!

Page 4: Shadow gunのサンプルから学べるモバイル最適化

• 基本的に多くの情報はすでに英語で Unity の Web サイトに出ています–http://blogs.unity3d.com/2012/03/23/shad

owgun-optimizing-for-mobile-sample-level/–http://blogs.unity3d.com/2011/08/18/fast-

mobile-shaders-talk-at-siggraph/

Page 5: Shadow gunのサンプルから学べるモバイル最適化

ShadowGun

Page 6: Shadow gunのサンプルから学べるモバイル最適化

概要

• データを見てみよう• シェーダから学ぶ• テクニックを解説してみる

Page 7: Shadow gunのサンプルから学べるモバイル最適化

データを見てみよう

Page 8: Shadow gunのサンプルから学べるモバイル最適化

Scene 内データ数

• GameObject : 795• メッシュ (MeshFilter) : 429–不透明 : 369–半透明 : 60

Page 9: Shadow gunのサンプルから学べるモバイル最適化

Scene 内データ数

• マテリアル : 40• シェーダ : 17• ライト : 92–Directional : 1–Point : 91

Page 10: Shadow gunのサンプルから学べるモバイル最適化

テクスチャ枚数

• 64 × 1 枚• 128 × 1 枚• 256 × 7 枚• 512 × 10 枚• 1024 × 10 枚• 2048 × 3 枚

Page 11: Shadow gunのサンプルから学べるモバイル最適化

テクスチャ用途• 64 、 128– 光の表現、 God Ray 、 BRDF LookUpTexture

• 256– 遠景(月、山)、煙、床、水面

• 512– 彫像、床、旗、空、 NormalMap

• 1024– 敵、シャトル、壁、窓

• 2048– 壁、オブジェクト用アトラス

Page 12: Shadow gunのサンプルから学べるモバイル最適化

テクスチャフォーマット• 64 、 128–RGBA 32 、 RGB 16

• 256–RGBA 32 、 RGB 16 、 Compressed

• 512 、 1024 、 2048–Compressed

Page 13: Shadow gunのサンプルから学べるモバイル最適化

ポリゴン数• ポリゴン数–毎フレーム : 20k 〜 30k 描画–敵1体 : 約 2k–Draw-call : 30 〜 50–Batched : 120 〜 150

Page 14: Shadow gunのサンプルから学べるモバイル最適化

レンダリングオブジェクト数

• 不透明 : 349

• 半透明 : 49

Page 15: Shadow gunのサンプルから学べるモバイル最適化

レンダリングオブジェクト数

• 不透明 : 349–5 種類のマテリアルで約 300–この 5 種類は同じシェーダ

• 半透明 : 49–3 種類のマテリアルで約 30

Page 16: Shadow gunのサンプルから学べるモバイル最適化

処理時間• physx: 0.3• animation: 0.3• culling 0.0• skinning: 2.6• batching: 0.7• render: 1.8• fixed-update-count: 1 .. 4• update: 0.2• fixedUpdate: 0.4• coroutines: 0.0

Page 17: Shadow gunのサンプルから学べるモバイル最適化

処理時間• physx: 0.3• animation: 0.3• culling 0.0• skinning: 2.6• batching: 0.7• render: 1.8• fixed-update-count: 1 .. 4• update: 0.2• fixedUpdate: 0.4• coroutines: 0.0

結構重い!

Page 18: Shadow gunのサンプルから学べるモバイル最適化

シェーダから学ぶ

Page 19: Shadow gunのサンプルから学べるモバイル最適化

Case 1v2f vert (appdata_full v) {

v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);o.uv = v.texcoord;float3 worldNormal = mul((float3x3)_Object2World, v.normal);float3 viewNormal = mul((float3x3)UNITY_MATRIX_MV, v.normal);float4 viewPos = mul(UNITY_MATRIX_MV, v.vertex);float3 viewDir = float3(0,0,1);float3 viewLightPos = _SpecOffset * float3(1,1,-1);float3 dirToLight = viewPos.xyz - viewLightPos;float3 h = (viewDir + normalize(-dirToLight)) * 0.5;float atten = 1.0 - saturate(length(dirToLight) / _SpecRange);o.spec = _SpecColor * pow(saturate(dot(viewNormal, normalize(h))), _Shininess * 128) * 2 * atten;o.SHLighting = ShadeSH9(float4(worldNormal,1)) * _SHLightingScale;return o;

}

fixed4 frag (v2f i) : COLOR {fixed4 c = tex2D (_MainTex, i.uv);c.rgb *= i.SHLighting;c.rgb += i.spec.rgb * c.a;return c;

}

頂点シェーダ

フラグメントシェーダ

Page 20: Shadow gunのサンプルから学べるモバイル最適化

Case 2v2f vert (appdata_full v) {

v2f o;float3 viewPos = mul(UNITY_MATRIX_MV,v.vertex);float dist = length(viewPos);float nfadeout = saturate(dist / _FadeOutDistNear);float ffadeout = 1 - saturate(max(dist - _FadeOutDistFar,0) * 0.2);ffadeout *= ffadeout;nfadeout *= nfadeout;nfadeout *= nfadeout;nfadeout *= ffadeout;float4 vpos = v.vertex;vpos.xyz -= v.normal * saturate(1 - nfadeout) * v.color.a *

_ContractionAmount;o.uv = v.texcoord.xy;o.pos = mul(UNITY_MATRIX_MVP, vpos);o.color = nfadeout * v.color * _Multiplier;return o;

}

fixed4 frag (v2f i) : COLOR {return tex2D (_MainTex, i.uv.xy) * i.color;

}

頂点シェーダ

フラグメントシェーダ

Page 21: Shadow gunのサンプルから学べるモバイル最適化

• フラグメントシェーダが超シンプル!

Page 22: Shadow gunのサンプルから学べるモバイル最適化

• フラグメントシェーダが超シンプル!–なぜ?

Page 23: Shadow gunのサンプルから学べるモバイル最適化

• フラグメントシェーダが超シンプル!–なぜ?•計算量を減らすため•ピクセル数 >>> 頂点数

Page 24: Shadow gunのサンプルから学べるモバイル最適化

• Virtual Gloss Per-Vertex Additive (Supports Lightmap)–壁とか床–一番使用量が多い

Page 25: Shadow gunのサンプルから学べるモバイル最適化

Pass {CGPROGRAMpragma vertex vert#pragma fragment frag#pragma fragmentoption

ARB_precision_hint_faste

fixed4 frag (v2f i) : COLOR{

・・・

Page 26: Shadow gunのサンプルから学べるモバイル最適化

Pass {CGPROGRAMpragma vertex vert#pragma fragment frag#pragma fragmentoption

ARB_precision_hint_faste

fixed4 frag (v2f i) : COLOR{

・・・

精度を可能な限り落して実行時間を

短くする

Page 27: Shadow gunのサンプルから学べるモバイル最適化

fixed4 frag (v2f i) : COLOR {fixed4 c = tex2D (_MainTex, i.uv);fixed3 spec = i.spec.rgb * c.a;c.rgb += spec;fixed3 lm = DecodeLightmap(tex2D(

unity_Lightmap, i.lmap));c.rgb *= lm;return c;

}

Page 28: Shadow gunのサンプルから学べるモバイル最適化

fixed4 frag (v2f i) : COLOR {fixed4 c = tex2D (_MainTex, i.uv);fixed3 spec = i.spec.rgb * c.a;c.rgb += spec;fixed3 lm = DecodeLightmap(tex2D(

unity_Lightmap, i.lmap));c.rgb *= lm;return c;

}

明示的に精度を落とす

Page 29: Shadow gunのサンプルから学べるモバイル最適化

精度• fixed– 通常 11 bit– -2.0 〜 +2.0– 精度 1 / 256

• half– 通常 16 bit– -60000 〜 +60000– 精度おおよそ 3 桁

• float– 32 bit

Page 30: Shadow gunのサンプルから学べるモバイル最適化

精度• fixed– 通常 11 bit– -2.0 〜 +2.0– 精度 1 / 256

• half– 通常 16 bit– -60000 〜 +60000– 精度おおよそ 3 桁

• float– 32 bit

速い

遅い

Page 31: Shadow gunのサンプルから学べるモバイル最適化

精度• fixed–色、単位ベクトル

• half–その他

• float–half で精度が足りないとき

Page 32: Shadow gunのサンプルから学べるモバイル最適化

精度• こんな宣言もできます– lowp 、 mediump 、 highp

Page 33: Shadow gunのサンプルから学べるモバイル最適化

精度• こんな宣言もできます– lowp 、 mediump 、 highp

あくまでヒントでハードウェアによってどの精度が使われるか違ってくる

Page 34: Shadow gunのサンプルから学べるモバイル最適化

テクニックを学ぼう

Page 35: Shadow gunのサンプルから学べるモバイル最適化

描画順

1. 不透明2. Skybox–空、地面–月、遠景の山

3. 半透明

Page 36: Shadow gunのサンプルから学べるモバイル最適化

ライティング

• ライト–Directional: 1–Point : 91

Page 37: Shadow gunのサンプルから学べるモバイル最適化

ライティング

• ライト–Directional: 1–Point : 91

リアルタイムで計算なんか無理!

Page 38: Shadow gunのサンプルから学べるモバイル最適化

ライティング

• 静的オブジェクト→   Lightmap

• 動的オブジェクト→   LightProbe

Page 39: Shadow gunのサンプルから学べるモバイル最適化

静的オブジェクトのライティング

Lightmap+

Per Vertex Specular Maps

Page 40: Shadow gunのサンプルから学べるモバイル最適化

Per Vertex Specular Maps

1. テクスチャの α に鏡面反射強度を格納しておく

2. 頂点シェーダでスペキュラ計算3. フラグメントシェーダで上記計算結

果と強度を掛けて足す

Page 41: Shadow gunのサンプルから学べるモバイル最適化

コードv2f vert (appdata_full v) {

・・・o.spec = _SpecColor *

pow(saturate(dot(viewNormal,normalize(h))), _Shininess * 128)* 2 * atten;

・・・}

Page 42: Shadow gunのサンプルから学べるモバイル最適化

コード

half4 frag (v2f i) : COLOR {half4 c = tex2D (_MainTex, i.uv);half3 spec = i.spec.rgb * c.a;

Page 43: Shadow gunのサンプルから学べるモバイル最適化

動的オブジェクトのライティング

LightProbe+

BRDF

Page 44: Shadow gunのサンプルから学べるモバイル最適化

BRDF とは

Bidirectional ReflectanceDistribution Function= 双方向反射率分布関数

Page 45: Shadow gunのサンプルから学べるモバイル最適化

BRDF とは

物質の質感をあらわすパラメータで、物質に光が入射してきたときに、どのように反射するのか記述したもの

Page 46: Shadow gunのサンプルから学べるモバイル最適化

BRDF

• 事前に LookupTexture を作成– RGB にディフューズ– α にスペキュラ

• ライトとビュー方向から LookupTexture から値を取得

• アルベドと上記値を乗算

Page 47: Shadow gunのサンプルから学べるモバイル最適化

コードvoid surf (Input IN, inout MySurfaceOutput o) {

fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);o.Albedo = tex.rgb;o.Gloss = tex.a;o.Alpha = tex.a;o.Normal = tex2D(_BumpMap, IN.uv_BumpMap).rgb * 2.0 - 1.0;

}

Page 48: Shadow gunのサンプルから学べるモバイル最適化

コードixed4 LightingPseudoBRDF (MySurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten){

fixed3 halfDir = normalize (lightDir + viewDir);// N.Lfixed NdotL = dot (s.Normal, lightDir);// N.Hfixed NdotH = dot (s.Normal, halfDir);

// remap N.L from [-1..1] to [0..1]fixed biasNdotL = NdotL * 0.5 + 0.5;・・・

Page 49: Shadow gunのサンプルから学べるモバイル最適化

コード・・・

fixed4 l = tex2D (_BRDFTex, fixed2(biasNdotL, NdotH));

fixed4 c;c.rgb = s.Albedo * (l.rgb + s.Gloss * l.a) * 2;c.a = 0;

return c;} s.Gloss ( = tex.a )

Page 50: Shadow gunのサンプルから学べるモバイル最適化

GodRay

Page 51: Shadow gunのサンプルから学べるモバイル最適化

Godray

• ポストプロセスで実装されることが多い

• モバイルでポストプロセスはコストが高い

Page 52: Shadow gunのサンプルから学べるモバイル最適化

Godray

• ポストプロセスで実装されることが多い

• モバイルでポストプロセスはコストが高い–板ポリとテクスチャ–距離に応じて縮小、透明度を上げる

Page 53: Shadow gunのサンプルから学べるモバイル最適化

Godray

• ポストプロセスで実装されることが多い

• モバイルでポストプロセスはコストが高い–板ポリとテクスチャ–距離に応じて縮小、透明度を上げる• 画面いっぱいに広がると負荷が高い• それっぽく見せるため

Page 54: Shadow gunのサンプルから学べるモバイル最適化

コードv2f vert (appdata_full v) {

v2f o;float3 viewPos = mul(UNITY_MATRIX_MV,v.vertex);float dist = length(viewPos);float nfadeout = saturate(dist / _FadeOutDistNear);float ffadeout = 1 - saturate(max(dist - _FadeOutDistFar,0)

* 0.2);

ffadeout *= ffadeout;

・・・

距離に応じての減衰率を出す

Page 55: Shadow gunのサンプルから学べるモバイル最適化

コード・・・

float4 vpos = v.vertex;vpos.xyz -= v.normal * saturate(1 - nfadeout) * v.color.a

* _ContractionAmount;

o.uv   = v.texcoord.xy;o.pos = mul(UNITY_MATRIX_MVP, vpos);o.color = nfadeout * v.color * _Multiplier;return o;

}

頂点を法線方向に移動

Page 56: Shadow gunのサンプルから学べるモバイル最適化

Page 57: Shadow gunのサンプルから学べるモバイル最適化

旗• 頂点カラーの α に風の影響を受ける

かを格納してある• 上記と各種パラメータを使って頂点

シェーダで計算して直接頂点の位置を変更

Page 58: Shadow gunのサンプルから学べるモバイル最適化

Page 59: Shadow gunのサンプルから学べるモバイル最適化

煙• 通常はパーティクルで作成

Page 60: Shadow gunのサンプルから学べるモバイル最適化

煙• 普通はパーティクルで作成• 少しでも軽くするために–テクスチャの 2 重スクロール–頂点カラーとブレンド–端っこの頂点カラーを透明にする

Page 61: Shadow gunのサンプルから学べるモバイル最適化

コードv2f vert (appdata_full v) {

v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);o.uv.xy = TRANSFORM_TEX(v.texcoord.xy,_MainTex) +

frac(float2(_ScrollX, _ScrollY) * _Time);o.uv.zw = TRANSFORM_TEX(v.texcoord.xy,_DetailTex)

+ frac(float2(_Scroll2X, _Scroll2Y) *

_Time);

・・・

テクスチャ座標移動

Page 62: Shadow gunのサンプルから学べるモバイル最適化

コード・・・

o.uv.x += sin(_Time * _SineFreqX) * _SineAmplX;o.uv.y += sin(_Time * _SineFreqY) * _SineAmplY;

o.uv.z += sin(_Time * _SineFreqX2) * _SineAmplX2;o.uv.w += sin(_Time * _SineFreqY2) * _SineAmplY2;

o.color = _MMultiplier * _Color * v.color;return o;

}

Page 63: Shadow gunのサンプルから学べるモバイル最適化

Sphere Ambient Occlusion

Page 64: Shadow gunのサンプルから学べるモバイル最適化

Sphere Ambient Occlusion

• ある点がどれだけ遮蔽されているかに応じて陰をつける

• ShadowGun ではキャラクターの影で使用している–両足、腰に球を置いてその影を投影

Page 65: Shadow gunのサンプルから学べるモバイル最適化

Sphere Ambient Occlusion

• なんか小難しい式をあれこれすると最終的に

Page 67: Shadow gunのサンプルから学べるモバイル最適化

void surf (Input IN, inout SurfaceOutput o) {fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);

o.Albedo = tex.rgb;o.Alpha = tex.a;

half3 t = _Center.xyz - IN.worldPos.xyz;half d = 1 / (t.x * t.x + t.y * t.y + t.z * t.z);o.Gloss = (_Radius * _Radius * d);

WorldNormalVector(IN, o.Normal);}

Page 68: Shadow gunのサンプルから学べるモバイル最適化

コードfixed4 LightingSimpleLambertAO (SurfaceOutput s, fixed3 lightDir, fixed atten) {

fixed NdotL = dot (s.Normal, lightDir);fixed bl = NdotL * s.Gloss;

fixed4 c;c.rgb = s.Albedo * _LightColor0.rgb *

(NdotL * atten * 2) * (1 - bl);c.a = s.Alpha;return c;

}

光のブロック率を出す

Page 69: Shadow gunのサンプルから学べるモバイル最適化

まとめ

Page 70: Shadow gunのサンプルから学べるモバイル最適化

まとめ• StaticBatching のためにマテリアルを共通化• テクスチャは結構な量を使っても大丈夫– ただし圧縮フォーマット前提

• 静的なライティングで十分• 処理を頂点シェーダに可能な限り持ってい

く– = ピクセル単位での処理を減らす

• シェーダの計算は精度を落とす