Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
ShadowGun Sample Level から学べるモバイル最適化                      株式会社 Aiming               リードソフトウェアエンジニア                         ...
自己紹介• オンラインゲームを長年作ってきま  した• 主にサーバや通信部分担当です!• クライアントや 3D は自信ないです
でもがんばって解説します!
• 基本的に多くの情報はすでに英語で  Unity の Web サイトに出ています – http://blogs.unity3d.com/2012/03/23/shad   owgun-optimizing-for-mobile-sample-...
ShadowGun
概要• データを見てみよう• シェーダから学ぶ• テクニックを解説してみる
データを見てみよう
Scene 内データ数• GameObject    : 795• メッシュ(MeshFilter) : 429 –不透明    : 369 –半透明    : 60
Scene 内データ数• マテリアル           : 40• シェーダ         : 17• ライト             : 92 –Directional: 1 –Point      :91
テクスチャ枚数•   64     × 1枚•   128    × 1枚•   256    × 7枚•   512    × 10枚•   1024   × 10枚•   2048   × 3枚
テクスチャ用途• 64、128  – 光の表現、God Ray、BRDF LookUpTexture• 256  – 遠景(月、山)、煙、床、水面• 512  – 彫像、床、旗、空、NormalMap• 1024  – 敵、シャトル、壁、窓• ...
テクスチャフォーマット• 64、128  – RGBA 32、RGB 16• 256  – RGBA 32、RGB 16、Compressed• 512、1024、2048  – Compressed
ポリゴン数• ポリゴン数 – 毎フレーム         : 20k 〜 30k 描画 – 敵1体       : 約2k – Draw-call : 30 〜 50 – Batched   : 120 〜 150
レンダリングオブジェクト数• 不透明   : 349• 半透明   : 49
レンダリングオブジェクト数• 不透明   : 349 – 5 種類のマテリアルで約 300 – この 5 種類は同じシェーダ• 半透明   : 49 – 3 種類のマテリアルで約 30
処理時間•   physx: 0.3•   animation: 0.3•   culling 0.0•   skinning: 2.6•   batching: 0.7•   render: 1.8•   fixed-update-count...
処理時間•   physx: 0.3•   animation: 0.3•   culling 0.0•   skinning: 2.6            結構重い!•   batching: 0.7•   render: 1.8•   f...
シェーダから学ぶ
Case 1v2f vert (appdata_full v) {        v2f o;        o.pos = mul(UNITY_MATRIX_MVP, v.vertex);        o.uv = v.texcoord; ...
Case 2v2f vert (appdata_full v) {        v2f o;        float3 viewPos = mul(UNITY_MATRIX_MV,v.vertex);        float dist =...
• フラグメントシェーダが超シンプ  ル!
• フラグメントシェーダが超シンプ  ル!–なぜ?
• フラグメントシェーダが超シンプ  ル!–なぜ? • 計算量を減らすため • ピクセル数 >>> 頂点数
• Virtual Gloss Per-Vertex Additive  (Supports Lightmap)  –壁とか床  –一番使用量が多い
Pass {     CGPROGRAM     pragma vertex vert     #pragma fragment frag     #pragma fragmentoption  ARB_precision_hint_faste...
Pass {     CGPROGRAM     pragma vertex vert     #pragma fragment frag     #pragma fragmentoption  ARB_precision_hint_faste...
fixed4 frag (v2f i) : COLOR {      fixed4 c = tex2D (_MainTex, i.uv);      fixed3 spec = i.spec.rgb * c.a;      c.rgb += s...
fixed4 frag (v2f i) : COLOR {      fixed4 c = tex2D (_MainTex, i.uv);      fixed3 spec = 明示的に精度を落とす                      i...
精度• fixed  – 通常 11 bit  – -2.0 〜 +2.0  – 精度 1 / 256• half  – 通常 16 bit  – -60000 〜 +60000  – 精度おおよそ 3 桁• float  – 32 bit
精度• fixed  – 通常 11 bit              速い  – -2.0 〜 +2.0  – 精度 1 / 256• half  – 通常 16 bit  – -60000 〜 +60000  – 精度おおよそ 3 桁• f...
精度• fixed  – 色、単位ベクトル• half  – その他• float  – half で精度が足りないとき
精度• こんな宣言もできます – lowp、mediump、highp
精度• こんな宣言もできます – lowp、mediump、highpあくまでヒントでハードウェアによっ てどの精度が使われるか違ってくる
テクニックを学ぼう
描画順1. 不透明2. Skybox  –空、地面  –月、遠景の山3. 半透明
ライティング• ライト – Directional : 1 – Point       : 91
ライティング• ライト – Directional : 1 – Point       : 91   リアルタイムで計算なんか無        理!
ライティング• 静的オブジェクト       → Lightmap• 動的オブジェクト       → LightProbe
静的オブジェクトのライティン      グ         Lightmap            +  Per Vertex Specular Maps
Per Vertex Specular Maps1. テクスチャの α に鏡面反射強度を格   納しておく2. 頂点シェーダでスペキュラ計算3. フラグメントシェーダで上記計算結   果と強度を掛けて足す
コードv2f vert (appdata_full v) {      ・・・      o.spec = _SpecColor *            pow(saturate(dot(viewNormal,            norm...
コードhalf4 frag (v2f i) : COLOR {     half4 c = tex2D (_MainTex, i.uv);     half3 spec = i.spec.rgb * c.a;}
動的オブジェクトのライティン      グ     LightProbe        +       BRDF
BRDF とはBidirectional Reflectance     Distribution Function     = 双方向反射率分布関数
BRDF とは物質の質感をあらわすパラメータで、物質に光が入射してきたときに、どのように反射するのか記述したもの
BRDF• 事前に LookupTexture を作成 – RGB にディフューズ – α にスペキュラ• ライトとビュー方向から LookupTexture か  ら値を取得• アルベドと上記値を乗算
コードvoid surf (Input IN, inout MySurfaceOutput o) {      fixed4 tex =tex2D(_MainTex, IN.uv_MainTex);      o.Albedo = tex.rg...
コードixed4 LightingPseudoBRDF (MySurfaceOutput s, fixed3lightDir, fixed3 viewDir, fixed atten){        fixed3 halfDir = norm...
コード    ・・・    fixed4 l = tex2D (_BRDFTex,                   fixed2(biasNdotL, NdotH));    fixed4 c;    c.rgb = s.Albedo * ...
GodRay
Godray• ポストプロセスで実装されることが  多い• モバイルでポストプロセスはコスト  が高い
Godray• ポストプロセスで実装されることが  多い• モバイルでポストプロセスはコスト  が高い – 板ポリとテクスチャ – 距離に応じて縮小、透明度を上げる
Godray• ポストプロセスで実装されることが  多い• モバイルでポストプロセスはコスト  が高い – 板ポリとテクスチャ – 距離に応じて縮小、透明度を上げる  • 画面いっぱいに広がると負荷が高い  • それっぽく見せるため
コードv2f vert (appdata_full v) {        v2f o;        float3 viewPos = mul(UNITY_MATRIX_MV,v.vertex);        float dist = le...
コード       ・・・       float4 vpos = v.vertex;       vpos.xyz -= v.normal * saturate(1 - nfadeout) * v.color.a* _ContractionA...
旗
旗• 頂点カラーの α に風の影響を受ける  かを格納してある• 上記と各種パラメータを使って頂点  シェーダで計算して直接頂点の位置  を変更
煙
煙• 通常はパーティクルで作成
煙• 普通はパーティクルで作成• 少しでも軽くするために – テクスチャの 2 重スクロール – 頂点カラーとブレンド – 端っこの頂点カラーを透明にする
コードv2f vert (appdata_full v) {        v2f o;          テクスチャ座標移動        o.pos = mul(UNITY_MATRIX_MVP, v.vertex);        o.u...
コード    ・・・    o.uv.x += sin(_Time * _SineFreqX) * _SineAmplX;    o.uv.y += sin(_Time * _SineFreqY) * _SineAmplY;    o.uv.z...
Sphere Ambient Occlusion
Sphere Ambient Occlusion• ある点がどれだけ遮蔽されているか  に応じて陰をつける• ShadowGun ではキャラクターの影で  使用している – 両足、腰に球を置いてその影を投影
Sphere Ambient Occlusion• なんか小難しい式をあれこれする  と最終的に
参考資料• http://www.iquilezles.org/www/articles/spher  eao/sphereao.htm/
void surf (Input IN, inout SurfaceOutput o) {fixed4 tex =       tex2D(_MainTex, IN.uv_MainTex);       o.Albedo = tex.rgb; ...
コードfixed4 LightingSimpleLambertAO (SurfaceOutput s, fixed3lightDir, fixed atten) {        fixed NdotL = dot (s.Normal, lig...
まとめ
まとめ• StaticBatching のためにマテリアルを共通  化• テクスチャは結構な量を使っても大丈夫 – ただし圧縮フォーマット前提• 静的なライティングで十分• 処理を頂点シェーダに可能な限り持って  いく – = ピクセル単位での...
You’ve finished this document.
Download and read it offline.
Upcoming SlideShare
Unityとアセットツールで学ぶ「絵づくり」の基礎 ライト、シェーダー、イメージエフェクト
Next
Upcoming SlideShare
Unityとアセットツールで学ぶ「絵づくり」の基礎 ライト、シェーダー、イメージエフェクト
Next
Download to read offline and view in fullscreen.

Share

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

Download to read offline

Related Audiobooks

Free with a 30 day trial from Scribd

See all

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

  1. 1. ShadowGun Sample Level から学べるモバイル最適化 株式会社 Aiming リードソフトウェアエンジニア 牧野克俊 2012/06/01
  2. 2. 自己紹介• オンラインゲームを長年作ってきま した• 主にサーバや通信部分担当です!• クライアントや 3D は自信ないです
  3. 3. でもがんばって解説します!
  4. 4. • 基本的に多くの情報はすでに英語で 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/
  5. 5. ShadowGun
  6. 6. 概要• データを見てみよう• シェーダから学ぶ• テクニックを解説してみる
  7. 7. データを見てみよう
  8. 8. Scene 内データ数• GameObject : 795• メッシュ(MeshFilter) : 429 –不透明 : 369 –半透明 : 60
  9. 9. Scene 内データ数• マテリアル : 40• シェーダ : 17• ライト : 92 –Directional: 1 –Point :91
  10. 10. テクスチャ枚数• 64 × 1枚• 128 × 1枚• 256 × 7枚• 512 × 10枚• 1024 × 10枚• 2048 × 3枚
  11. 11. テクスチャ用途• 64、128 – 光の表現、God Ray、BRDF LookUpTexture• 256 – 遠景(月、山)、煙、床、水面• 512 – 彫像、床、旗、空、NormalMap• 1024 – 敵、シャトル、壁、窓• 2048 – 壁、オブジェクト用アトラス
  12. 12. テクスチャフォーマット• 64、128 – RGBA 32、RGB 16• 256 – RGBA 32、RGB 16、Compressed• 512、1024、2048 – Compressed
  13. 13. ポリゴン数• ポリゴン数 – 毎フレーム : 20k 〜 30k 描画 – 敵1体 : 約2k – Draw-call : 30 〜 50 – Batched : 120 〜 150
  14. 14. レンダリングオブジェクト数• 不透明 : 349• 半透明 : 49
  15. 15. レンダリングオブジェクト数• 不透明 : 349 – 5 種類のマテリアルで約 300 – この 5 種類は同じシェーダ• 半透明 : 49 – 3 種類のマテリアルで約 30
  16. 16. 処理時間• 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
  17. 17. 処理時間• 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
  18. 18. シェーダから学ぶ
  19. 19. 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; フラグメントシェーダ
  20. 20. 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;}
  21. 21. • フラグメントシェーダが超シンプ ル!
  22. 22. • フラグメントシェーダが超シンプ ル!–なぜ?
  23. 23. • フラグメントシェーダが超シンプ ル!–なぜ? • 計算量を減らすため • ピクセル数 >>> 頂点数
  24. 24. • Virtual Gloss Per-Vertex Additive (Supports Lightmap) –壁とか床 –一番使用量が多い
  25. 25. Pass { CGPROGRAM pragma vertex vert #pragma fragment frag #pragma fragmentoption ARB_precision_hint_faste fixed4 frag (v2f i) : COLOR { ・・・
  26. 26. Pass { CGPROGRAM pragma vertex vert #pragma fragment frag #pragma fragmentoption ARB_precision_hint_faste 精度を可能な限り落して fixed4 frag (v2f i) : COLOR { 実行時間を短くす る ・・・
  27. 27. 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;}
  28. 28. 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;}
  29. 29. 精度• fixed – 通常 11 bit – -2.0 〜 +2.0 – 精度 1 / 256• half – 通常 16 bit – -60000 〜 +60000 – 精度おおよそ 3 桁• float – 32 bit
  30. 30. 精度• fixed – 通常 11 bit 速い – -2.0 〜 +2.0 – 精度 1 / 256• half – 通常 16 bit – -60000 〜 +60000 – 精度おおよそ 3 桁• float 遅い – 32 bit
  31. 31. 精度• fixed – 色、単位ベクトル• half – その他• float – half で精度が足りないとき
  32. 32. 精度• こんな宣言もできます – lowp、mediump、highp
  33. 33. 精度• こんな宣言もできます – lowp、mediump、highpあくまでヒントでハードウェアによっ てどの精度が使われるか違ってくる
  34. 34. テクニックを学ぼう
  35. 35. 描画順1. 不透明2. Skybox –空、地面 –月、遠景の山3. 半透明
  36. 36. ライティング• ライト – Directional : 1 – Point : 91
  37. 37. ライティング• ライト – Directional : 1 – Point : 91 リアルタイムで計算なんか無 理!
  38. 38. ライティング• 静的オブジェクト → Lightmap• 動的オブジェクト → LightProbe
  39. 39. 静的オブジェクトのライティン グ Lightmap + Per Vertex Specular Maps
  40. 40. Per Vertex Specular Maps1. テクスチャの α に鏡面反射強度を格 納しておく2. 頂点シェーダでスペキュラ計算3. フラグメントシェーダで上記計算結 果と強度を掛けて足す
  41. 41. コードv2f vert (appdata_full v) { ・・・ o.spec = _SpecColor * pow(saturate(dot(viewNormal, normalize(h))), _Shininess * 128) * 2 * atten; ・・・}
  42. 42. コードhalf4 frag (v2f i) : COLOR { half4 c = tex2D (_MainTex, i.uv); half3 spec = i.spec.rgb * c.a;}
  43. 43. 動的オブジェクトのライティン グ LightProbe + BRDF
  44. 44. BRDF とはBidirectional Reflectance Distribution Function = 双方向反射率分布関数
  45. 45. BRDF とは物質の質感をあらわすパラメータで、物質に光が入射してきたときに、どのように反射するのか記述したもの
  46. 46. BRDF• 事前に LookupTexture を作成 – RGB にディフューズ – α にスペキュラ• ライトとビュー方向から LookupTexture か ら値を取得• アルベドと上記値を乗算
  47. 47. コード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;}
  48. 48. コードixed4 LightingPseudoBRDF (MySurfaceOutput s, fixed3lightDir, fixed3 viewDir, fixed atten){ fixed3 halfDir = normalize (lightDir + viewDir); // N.L fixed NdotL = dot (s.Normal, lightDir); // N.H fixed NdotH = dot (s.Normal, halfDir); // remap N.L from [-1..1] to [0..1] fixed biasNdotL = NdotL * 0.5 + 0.5; ・・・
  49. 49. コード ・・・ 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)
  50. 50. GodRay
  51. 51. Godray• ポストプロセスで実装されることが 多い• モバイルでポストプロセスはコスト が高い
  52. 52. Godray• ポストプロセスで実装されることが 多い• モバイルでポストプロセスはコスト が高い – 板ポリとテクスチャ – 距離に応じて縮小、透明度を上げる
  53. 53. Godray• ポストプロセスで実装されることが 多い• モバイルでポストプロセスはコスト が高い – 板ポリとテクスチャ – 距離に応じて縮小、透明度を上げる • 画面いっぱいに広がると負荷が高い • それっぽく見せるため
  54. 54. コード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; ・・・
  55. 55. コード ・・・ 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;}
  56. 56.
  57. 57. 旗• 頂点カラーの α に風の影響を受ける かを格納してある• 上記と各種パラメータを使って頂点 シェーダで計算して直接頂点の位置 を変更
  58. 58.
  59. 59. 煙• 通常はパーティクルで作成
  60. 60. 煙• 普通はパーティクルで作成• 少しでも軽くするために – テクスチャの 2 重スクロール – 頂点カラーとブレンド – 端っこの頂点カラーを透明にする
  61. 61. コード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); ・・・
  62. 62. コード ・・・ 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;}
  63. 63. Sphere Ambient Occlusion
  64. 64. Sphere Ambient Occlusion• ある点がどれだけ遮蔽されているか に応じて陰をつける• ShadowGun ではキャラクターの影で 使用している – 両足、腰に球を置いてその影を投影
  65. 65. Sphere Ambient Occlusion• なんか小難しい式をあれこれする と最終的に
  66. 66. 参考資料• http://www.iquilezles.org/www/articles/spher eao/sphereao.htm/
  67. 67. 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);}
  68. 68. コードfixed4 LightingSimpleLambertAO (SurfaceOutput s, fixed3lightDir, 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;}
  69. 69. まとめ
  70. 70. まとめ• StaticBatching のためにマテリアルを共通 化• テクスチャは結構な量を使っても大丈夫 – ただし圧縮フォーマット前提• 静的なライティングで十分• 処理を頂点シェーダに可能な限り持って いく – = ピクセル単位での処理を減らす• シェーダの計算は精度を落とす
  • hifumirei

    Mar. 15, 2018
  • shuntasuzuki31

    Apr. 28, 2016
  • ssuser37fd51

    Nov. 30, 2015
  • alpha_kim

    Jul. 10, 2015
  • toshiyukiyonekura

    Jul. 6, 2015
  • hecomi

    Apr. 25, 2015
  • ryugoabe5

    Mar. 6, 2015
  • YoshioHara

    Mar. 5, 2015
  • shotababa359

    Mar. 5, 2015
  • basabasan

    Feb. 12, 2015
  • heistak

    Nov. 18, 2014
  • KanSakamoto

    Nov. 17, 2014
  • yuyanishizaki

    Nov. 17, 2014
  • miyakou1982

    Aug. 24, 2014
  • tomoto1982

    Jul. 6, 2014
  • YuichiIshii

    May. 27, 2014
  • NobutakaTakushima

    Nov. 20, 2013
  • kenseirealdeal

    Oct. 23, 2013
  • fumiyaota50

    Jul. 19, 2013
  • AtsushiTaniguchi

    Jul. 5, 2013

Views

Total views

22,621

On Slideshare

0

From embeds

0

Number of embeds

10,040

Actions

Downloads

99

Shares

0

Comments

0

Likes

31

×