CubeWalk: go言語cacheサーバーのリージョン選定
前書き
先月、こちらに登壇して PlayFab の CloudScript で同時実行を回避しつつ、不正させないゲームのためのアイディアを語ってみたのですが
jpfug.connpass.com
質問者から CloudScript が実行されている場所って US West オレゴンだから、日本にキャッシュサーバー置くと
結果的に情報路が長くなって、片道 1.3万キロメートルだから、理論上通信に最小 0.1 秒ほどの不要な遅れが足されて
あと日本でサーバー立てる方がランニングコストも通信費も高いですよね
とご指摘いただいたのです。
なるほど、go言語キャッシュサーバーを US West オレゴンに置いて、そこにアクセスする CloudScript も用意して
実際の通信速度に差が 0.1 秒ほど出るのか試してみますね!
やったこと
以前行った時のログをたよりにドキュメントを読み直し 東京リージョンと同じ構成でオレゴンリージョンにも同じ golang キャッシュサーバーを構築します。
simplestar-tech.hatenablog.com
まず、自宅(日本、東京)の pc からリクエストをそれぞれの golang サーバーに送ってヘルスチェックレスポンスが返ってくるまでの時間を計測
東京リージョンは 110~180 ms を要してました。
オレゴンリージョンは 610~680 ms を要してました。
この、それぞれのサーバーにヘルスチェックリクエストをする PlayFab CloudScript を javascript で実装し
自宅(日本、東京)の pc 上で実行する Unity クライアントから、CloudScript を呼び出してヘルスチェックレスポンスが返ってくるまでの時間を計測しました。
東京リージョンは 650~700 ms を要してました。
オレゴンリージョンは 220~300 ms を要してました。
結果
日本・東京の Unity クライアントから、PlayFab CloudScript を呼び出して golang のキャッシュサーバーのレスポンスを確認して Unity に戻ってくるまでの時間を計測しました。
サーバーの場所:
東京リージョンは 650~700 ms を要してました。
オレゴンリージョンは 220~300 ms を要してました。
PlayFab の PlayStream には、CloudScript 呼び出しの詳細が json で記録されますが
東京リージョンに置いた golang キャッシュサーバーにヘルスチェックを返してもらうのに "ExecutionTimeSeconds": 0.5307192
オレゴンリージョンに置いた golang キャッシュサーバーにヘルスチェックを返してもらうのに "ExecutionTimeSeconds": 0.0244125
PlayFab のスタジオのリージョンを日本にできればいいんだけどね…オレゴンにあるのは間違いない
今は東京リージョンにキャッシュサーバーを置くのは間違い確定なので、しばらくオレゴンリージョンに置いて作業を進めます。
Unity: SteamVR 2.0 の入力処理の入門記事
アクション単体では作れない
アクションを束ねた、アクションセットを作成するところから始まります。
最初はいくつものアクションが定義された default アクションセットが選択されている
default のほかに platformer, buggy, mixedreality のアクションセットが確認できる
アクションセットを作る
Window > Steam VR Input でダイアログを表示し
既存の default, platformer, buggy, misedreality のボタンの右側に + ボタンあるので押す
NewSet で作成、何か一つ In Actions に NewAction を追加 boolean Type とする
Save and generate ボタンを押し、完了を待つ
BooleanAction を参照してイベントハンドラを登録
using UnityEngine; using Valve.VR; public class MyActionScript : MonoBehaviour { // a reference to the action public SteamVR_Action_Boolean sphereOnOff; // a reference to the hand public SteamVR_Input_Sources handType; //reference to the sphere public GameObject sphere; void Start() { this.sphereOnOff.AddOnStateDownListener(this.TriggerDown, handType); this.sphereOnOff.AddOnStateUpListener(this.TriggerUp, handType); } private void TriggerDown(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource) { Debug.Log("Trigger is down"); this.sphere.GetComponent<MeshRenderer>().enabled = true; } private void TriggerUp(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource) { Debug.Log("Trigger is up"); this.sphere.GetComponent<MeshRenderer>().enabled = false; } }
ということ
Activate Action Set しないといけない
自分で作ったアクションセットはゲーム開始時にアクティブではない
アクティブになるように明示
先ほどの MyActionScript より前に実行される位置にシーンに配置しないといけない制約もある
Open Binding UI
Window > Steam VR Input でダイアログを表示し、Open Binding UI ボタンを押す
newset という、さっき作ったアクションセットのタブが見える。
アクションが割り当たっていないことを示す表示かな
タブを選択して
はじめて動作することになる
まとめると、以下の一つが欠けると、何も反応ない結果になる
- アクションセットを作る
- アクションを作る
- アクションハンドラを作る
- アクションハンドラを登録するコードを書く
- アクションを参照
- 順番を守ったアクションアクティベート
- 入力管理でアクションセットのアクションをコントローラのいずれかの操作にバインディング
Unity:VRでも使えるMToon互換のURPシェーダを30分で作ろう
前書き
Unity でゲーム作っている人なら多くの方が知っている VRM - VR向け3Dアバターファイルフォーマット -。
その VRM の標準シェーダーとして採用されている MToon を URP でも表示できるようにしたい!
作りましょう!
そのための情報集めから作業をこの記事で公開します。
そのあと、公開しました。
github.com
MToon のパラメータ一覧
新しく ShaderGraph - Unlit を作成して公開パラメータとして次のものを作成します。
光源情報を Custom Function ノードで取得
github.com
ここにあるサブグラフ一式と .hlsl シェーダー実装をコピーしておきます。いつでも使えるように
内容はほんと、単に光源情報取ってきているだけです。
Toon シェーディング for ShaderGraph
次の動画の説明欄にあるリンクから Toon 表現の肝となる Node を見つけてコピーします。
ほしいのはこの Node です。
アウトライン Shader
そして MToon で外せないのが Outline です。
Shader Graph で実現する方法が紹介されている記事がこちら
Normal が Alpha テストできない問題に最終的に当たるので、もろもろ削除して、結局 Depth を書き出すプロジェクトで次の CustomFunction を呼ぶだけにします。
最終的に Outline サブシェーダーを作りますが、そこに登場する Custom Function は三つ
下図のとおり、左上のオフセットが
Out = unity_StereoEyeIndex;
左下の係数が
Out = 1.0; #if UNITY_SINGLE_PASS_STEREO Out = 0.5; #endif
右下の Custom Function がこちら
TEXTURE2D(_CameraDepthTexture); SAMPLER(sampler_CameraDepthTexture); float4 _CameraDepthTexture_TexelSize; void OutlineObject_float(float2 UV, float OutlineThickness, float DepthSensitivity, float NormalsSensitivity, out float Out) { float halfScaleFloor = floor(OutlineThickness * 0.5); float halfScaleCeil = ceil(OutlineThickness * 0.5); float2 uvSamples[4]; float depthSamples[4]; uvSamples[0] = UV - float2(_CameraDepthTexture_TexelSize.x, _CameraDepthTexture_TexelSize.y) * halfScaleFloor; uvSamples[1] = UV + float2(_CameraDepthTexture_TexelSize.x, _CameraDepthTexture_TexelSize.y) * halfScaleCeil; uvSamples[2] = UV + float2(_CameraDepthTexture_TexelSize.x * halfScaleCeil, -_CameraDepthTexture_TexelSize.y * halfScaleFloor); uvSamples[3] = UV + float2(-_CameraDepthTexture_TexelSize.x * halfScaleFloor, _CameraDepthTexture_TexelSize.y * halfScaleCeil); for(int i = 0; i < 4 ; i++) { depthSamples[i] = SAMPLE_TEXTURE2D(_CameraDepthTexture, sampler_CameraDepthTexture, uvSamples[i]).r; } // Depth float depthFiniteDifference0 = depthSamples[1] - depthSamples[0]; float depthFiniteDifference1 = depthSamples[3] - depthSamples[2]; float edgeDepth = sqrt(pow(depthFiniteDifference0, 2) + pow(depthFiniteDifference1, 2)) * 100; float depthThreshold = (1/DepthSensitivity) * depthSamples[0]; Out = edgeDepth > depthThreshold ? 1 : 0; }
あとはつなぐだけ
Toon 表現と Outline がそろっているので、接続して MToon の説明をたよりに編みます
MToon の心臓となる処理は Main と Shade のテクスチャを陰影で利用すること。
なので、Toon 表現で白黒を出力して、それを Lerp する処理が書けたらほぼ完成。自分はさらにライト色をもらうように Multiplyしてます。
MToon の Add を少々
最後に塩コショウのように Sphere Add と Emission を足すと
Imagemagick:画像のエッジを引き延ばして格子状に再配置
前書き
キューブの見た目を更新する目的で動いています。
前回は Shader ができたところまで
simplestar-tech.hatenablog.com
今回はテクスチャを連番で結合する処理を作ります。
大分前に python の pillow で画像処理を書きましたが…
github.com
処理が遅すぎるのと
画像のエッジの引き延ばしを行っていなかったので、キューブ群を遠目で見ると結合部分が光ったり黒くなったり…とにかく見た目が良くない
その部分を今回は imagemagick を利用して解決していきます。
参考までに、昔のキューブの見た目は頑張ってこんなの
simplestar-tech.hatenablog.com
もう2年以上、技術選定を続けているという…今年は完成させるぞ!
simplestar-tech.hatenablog.com
Imagemagick の基本を習得
まずは Windows 環境で使えるように portable 版をダウンロードして展開し PATH を通しておきます。
imagemagick.org
以降、Windows 環境だと convert コマンドを magick にしなければバッティングする旨を imagemagick が教えてくれるので
magick コマンドを利用します。
そうしたことを念頭に次のマニュアルを完走して、imagemagick を身体になじませました。
Imagemagick での画像のエッジ引き延ばし
情報ソースはこちら
www.imagemagick.org
細かいことは置いとくと、次の倍率を指定するだけで余白を引き延ばすことができます。
(残念ながら distort は基本操作には出てこない)
magick in.png -set option:distort:viewport %[fx:w*(1+0.05)]x%[fx:h*(1+0.05)] -virtual-pixel Edge -distort SRT "0,0 1,1 0 %[fx:w/(2/0.05)],%[fx:h/(2/0.05)]" out.png
ちょっとだけ解説すると
distort:vieport が left, top 引き延ばし幅に関与&全体の幅高さ倍率指定
virtual^pixel Edge が right, bottom の引き延ばし幅に関与していて、要するに 1 引いた倍率を 1/2 倍で指定というながれ
画像を変換してタイル状に並べる
変換した画像を利用するという小技について、まずはおさらい。
こちらの画像を入力に(昔、自分が描いた絵です)
こちらの処理を実行すると
magick in.jpg -resize 200x200 -size 300x300 xc:blue +swap -gravity center -compose over -composite -mattecolor red -frame 10x10 exit.jpg
意味は、200x200 にアスペクト比を保ったまま縮小して、blue 一色で塗りつぶした 300x300 の画像を新規作成、並び順を入れ替えて、conposite により青を背景に重ね合わせて、10pixel 幅の赤いフレームを追加
という文(読めました?)
次の結果が得られます。
PowerShell で実行する複数ファイル作成とタイリングモンタージュ
以下の powershell は Windows 環境で imagemagick に PATH が通っていれば動きます。
テクスチャはこちらの有料アセット(single entity license)を購入したものを利用します。
Yughues PBR Nature Materials
assetstore.unity.com
tga ファイルは magick で変換すると上下逆転しますし、Specular は png に tga から変換すると背景色が真っ白に変わるので(本当は黒)
一度 jpg に中間ファイルを出して、上下反転しつつもなんとか
あと、ファイルによっては正方形ではないので正方形に直します。
加えて、左右に 8 pixel の余白を設けるように 1008 x 1008 に圧縮してタイリングしたいと思います。
を実現する Powershell が以下の通り
# [AO, Diffuse, Height, Normal, Specular] $target = "Specular" New-Item $target -ItemType Directory -Force $dir = "~\Assets\Yughues PBS Nature Materials" $imgs = Get-ChildItem -Recurse -Path "$dir\*$target.tga" foreach ($img in $imgs) { $fullName = $img.FullName $jpg = "$target\" + [io.path]::ChangeExtension($img.Name, "jpg") $id = identify $fullName $edge = 0.0158730 if ($id -like "*512x1024*") { magick $fullName -resize 504x1008 -flip -write mpr:i +delete mpr:i mpr:i +append -set option:distort:viewport "%[fx:w*(1+$edge)]x%[fx:h*(1+$edge)]" -virtual-pixel Edge -distort SRT "0,0 1,1 0 %[fx:w/(2/$edge)],%[fx:h/(2/$edge)]" -quality 100 $jpg } else { magick $fullName -resize 1008x1008 -flip -set option:distort:viewport "%[fx:w*(1+$edge)]x%[fx:h*(1+$edge)]" -virtual-pixel Edge -distort SRT "0,0 1,1 0 %[fx:w/(2/$edge)],%[fx:h/(2/$edge)]" -quality 100 $jpg } echo $jpg } montage "$target\*$target.jpg" -tile 8x8 -geometry 1024x1024 "0_$target.png"
出力されるテクスチャを使って、Height map を利用しつつ絵を作ることができました。
ステップ2はクリアです。
残すはゲーム内の UV 操作のみ
追記
余白をエッジ引き延ばしするのもよかった
だけど parallax で使う場合はかなり余白を利用することになるし、そこがエッジ引き延ばしだとまた不自然な見た目になったので
リピートラッピングする方法を考案しました。
次の命令は画像の上下左右ななめ方向すべてにタイリングする例です
magick in.jpg -resize 960x960 -flip -write mpr:i +delete mpr:i mpr:i mpr:i +append -write mpr:j +delete mpr:j mpr:j mpr:j -append -gravity center -crop 1024x1024+0+0 -quality 100 out.jpg
これをスクリプトにつなげると
# [AO, Diffuse, Height, Normal, Specular] $target = "Diffuse" New-Item $target -ItemType Directory -Force $dir = "D:\github\Unity\UniversalParallaxOffset\Assets\Yughues PBS Nature Materials" $imgs = Get-ChildItem -Recurse -Path "$dir\*$target.tga" foreach ($img in $imgs) { $fullName = $img.FullName $jpg = "$target\" + [io.path]::ChangeExtension($img.Name, "jpg") $id = identify $fullName if ($id -like "*512x1024*") { magick $fullName -resize 480x960 -flip -write mpr:i +delete mpr:i mpr:i +append -write mpr:j +delete mpr:j mpr:j mpr:j +append -write mpr:k +delete mpr:k mpr:k mpr:k -append -gravity center -crop 1024x1024+0+0 -quality 100 $jpg } else { magick $fullName -resize 960x960 -flip -write mpr:j +delete mpr:j mpr:j mpr:j +append -write mpr:k +delete mpr:k mpr:k mpr:k -append -gravity center -crop 1024x1024+0+0 -quality 100 $jpg } echo $jpg } montage "$target\*$target.jpg" -tile 8x8 -geometry 1024x1024 "0_$target.png"
期待通り
Unity:URPでParallaxMapping
# 前書き
私が作っているキューブの世界
simplestar-tech.hatenablog.com
そろそろキューブの見た目を更新する時が来た
この先のステップとしては
1.AO, Albedo, Height, Normal, Specular テクスチャを入力とする、Height Map をちゃんと利用する Shader Graph が作られている
2.8192 x 8192 のテクスチャにインデックスで区分けして AO, Albedo, Height, Normal, Specular テクスチャ計5枚を用意、余白を指定して高速出力できるプログラムが作られている
3.余白を考慮したテクスチャ座標サンプルができるゲームロジックになっている
が想像できる
今回は ParallaxOffset を使った1.ステップについて解説
# Shader Graph
ここのところだいぶ Shader Graph に慣れてきたので、UV 操作する ParallaxOffset SubGraph があるならこんな感じのグラフになる
肝心の SubShader の中身がこれ
見た目はこんな感じで
情報源はこちらのやりとり
How do I use a Heightmap in Shader Graph?
https://forum.unity.com/threads/how-do-i-use-a-heightmap-in-shader-graph.538170/
後に解説を求めて参考にしたフォローアップ記事
LearnOpenGL - Parallax Mapping
まとめ
即興で作れるグラフなので
ソース公開しなくてもいいかな
Unity: URPのモザイクシェーダーと水面シェーダー
1/14 に twitter で知り合った方に、その方が作成したオンライン VR ゲームに誘われてログイン
こちらのマイクの設定が初めてで最後までつなぎ方がわからなかったのだけど、面白い話を聞かせてもらいました。
なんとも VR 空間の、それも Unity の URP でモザイクとインタラクティブな水面シェーダーがあるとうれしいとのこと
モザイクシェーダーはその日話を終えた 22:00 から作り始めて、朝2:00頃までにいきおいで完成させて公開
github.com
その後も、URP VR 空間における水の表現は自分もほしいところだったので、作り始めます。
Twitter に水面シェーダーの制作過程を記したところ、最大でツィートインプレッションが 15万を超えて
この20日でフォロワーが 500人くらい増えるなど、知名度が上がる出来事がありました。
後にこの出来事が人生を大成功へ導く大きな一歩だったと気づくことになるのですが、それはまた別のお話(おい
とりあえず、一連のシェアされたツィートを並べると次の通り
Unity の ComputeShader 使う Wave(波動方程式シミュレーション)が UniversalRP でできるか試してみた。
— Simplestar@Unityゲーム開発 (@lpcwstr) January 18, 2020
問題なく動かせました!
Unity楽しい
ソースはこちら↓https://t.co/kmeMtkXNll#Unity #UniversalRP #ShaderGraph pic.twitter.com/mXmyPFfhye
波動方程式わかってきた。だいたい作りたい絵が作れてきた
— Simplestar@Unityゲーム開発 (@lpcwstr) January 19, 2020
こいつを URP の VR で見れたらすごい!
技術要素はそろっているので頑張ってみますか
なにげに 500 FPS とか、GPGPU によって、ほとんどCPU負荷がかからないのもすごい#Unity #UniversalRP pic.twitter.com/qhCoaCG2XA
Unity の URP の Single Pass Stereo Rendering Mode でこういう水面の表現ができるの、現在はまだ珍しい時期なので面白い絵が作れたかなと思ってます。(動画は昨日の投稿と同じ)
— Simplestar@Unityゲーム開発 (@lpcwstr) January 19, 2020
個人制作している Cube を敷き詰めた世界に水を表現できる可能性が上がった(今までは技術なくて、あきらめてた) pic.twitter.com/z3VIqy7I0u
ひとつ前の投稿動画から、回転オフセットを与えるところまで
— Simplestar@Unityゲーム開発 (@lpcwstr) January 20, 2020
ひとまず回転は合っている。
あとは位置オフセットをどう与えるか pic.twitter.com/vgnBrdXExQ
なんとか PlayFab 勉強会発表前に(勉強会では発表しないネタ)URP で使える glass shader graph のサンプルがそれらしく動いた。
— Simplestar@Unityゲーム開発 (@lpcwstr) January 25, 2020
これを前作った波紋がインタラクティブに広がる水面に適用できれば、かなり意図した水面になる かもしれません#Unity #UniversalRP pic.twitter.com/2Np4Lr5Bsz
屈折シェーダーには法線が必須なので、波紋から法線を作り出す必要があって、なんとからしい法線が得られたところ
— Simplestar@Unityゲーム開発 (@lpcwstr) January 25, 2020
今日はここまで pic.twitter.com/7Z8sbNgOTp
波動方程式シミュレーション x 屈折シェーダー x 波の法線計算 x メッシュ細分化 x 頂点位置変更を掛け合わせた最初の絵です。
— Simplestar@Unityゲーム開発 (@lpcwstr) January 26, 2020
これを URP の VR で遊べるようにしていきます!
(そこまで作ったら売ろう)#Unity #UniversalRP #GameDev pic.twitter.com/aSv2uwe8Ua
URP Single Pass VR でインタラクティブな水面表現できた!水中からの絵も作ってみた!(みんなに成果見てほしいので、よかったら拡散してね!)
— Simplestar@Unityゲーム開発 (@lpcwstr) January 26, 2020
…今日はここまでにしておこう
別件、コロナウイルス怖いですね。
明日から満員電車に乗るのやめて、徒歩出社しようかな#Unity #VR #gamedev pic.twitter.com/oNCS4ahI1T
昨日の夜は帰宅後に Unity の AssetStore 用に namespace 切ったりとコード整理しながら、アセット説明用の動画1を作ってた
— Simplestar@Unityゲーム開発 (@lpcwstr) January 27, 2020
次は VR で水に潜ったりするやつ作る予定#Unity #URP
※動画はBGM流れます! pic.twitter.com/50IF9XIax5
void OnValidate()
— Simplestar@Unityゲーム開発 (@lpcwstr) January 28, 2020
{
this.SubDivide(this.subDivCount);
}
そういうことです。 pic.twitter.com/6OJNlhU6Ps
物体の移動方向を拾って、波を立てる上下方向を変更することで、プレゼンスが向上
— Simplestar@Unityゲーム開発 (@lpcwstr) January 28, 2020
今日はここまで(毎日少しずつ) pic.twitter.com/TpXSnDLTkS
目的の VR コントローラで波を作るシーンがやっとできた。楽しくて調整しながら長いこと遊んでた
— Simplestar@Unityゲーム開発 (@lpcwstr) January 29, 2020
Unity 2019.3 URP 7.1.8#Unity #madewithunity pic.twitter.com/Pp1kyeQtDB
信じられる?
— Simplestar@Unityゲーム開発 (@lpcwstr) February 3, 2020
これが、パーティクルなんだって
水球パーティクル作りました
このあと VFX Editor で大量にエミットできるか試してみます#Unity #VFX pic.twitter.com/AVVYx14UFF
さっき作った水球パーティクルを数万エミットしても VR で 120 FPS が開発環境で出せるって、すごい
— Simplestar@Unityゲーム開発 (@lpcwstr) February 3, 2020
水面波紋シェーダーと同時でもパフォーマンス出てる
これをうまく加工すれば水しぶき作れるかな#Unity #VisualEffectGraph pic.twitter.com/yvnttPOYZO
やっと満足いく water shader できた
— Simplestar@Unityゲーム開発 (@lpcwstr) February 5, 2020
週末の連休でアセットストアに提出する予定
(水パーティクルも独立して便利に使えると思います)#madewithunity #Shader #VR pic.twitter.com/UIOMBH4FiN
インタラクティブな水面アセットをストアに提出しました。
— Simplestar@Unityゲーム開発 (@lpcwstr) February 9, 2020
こちらの記事を参考にさせてもらいましたー
審査通るといいです🙏
UnityのAsset販売のノウハウ https://t.co/CDsMNmL8t4 #Qiita #Unity pic.twitter.com/CFOMlMUcbT
何が言いたいかというと
まとめ
ここのところ hatena の記事数は少ないけど、アクティブに学習とアウトプットを続けて、ちゃんとキューブのゲームにつながる技術習得とアセット入手まで進んでますよ自分
という、いつか記事数だけ見て、疑問に思っている自分にメッセージを残しておきます。
そうそう、これも記録してなかったけど PlayFab Meetup #2 で発表もしてきました。
なかなか好評でしたよ。
jpfug.connpass.com
自分の発表資料はこちらで公開中
docs.google.com