Unity Days

Unity や VR/AR に関することを書いていきたい。

Shader 勉強メモ 「サンプルを理解する2」

前々回に予告していたサンプルをやっていきます。

Unity - マニュアル: Vertex and fragment shader examples

法線情報を使ったシェーダーは前にやったので、スカイボックスを反射させるシェーダーから。 解説は追記する予定。

f:id:Dmiyamo3:20170311142914p:plain

Shader "Unlit/SkyReflection"
{
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            // vertで値を入力し、fragで利用する値を定義
            struct v2f {
                half3 worldRefl : TEXCOORD0;
                float4 pos : SV_POSITION;
            };

            v2f vert (float4 vertex : POSITION, float3 normal : NORMAL)
            {
                v2f o;
                // オブジェクト空間の頂点位置をクリップ空間に変換
                o.pos = UnityObjectToClipPos(vertex);
                // 定義済値、オブジェクト空間→ワールド空間へ変換する行列と
                // オブジェクト空間の頂点位置の行列積
                float3 worldPos = mul(_Object2World, vertex).xyz;
                // compute world space view direction
                float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
                // world space normal
                float3 worldNormal = UnityObjectToWorldNormal(normal);
                // world space reflection vector
                o.worldRefl = reflect(-worldViewDir, worldNormal);
                return o;
            }
        
            fixed4 frag (v2f i) : SV_Target
            {
                // sample the default reflection cubemap, using the reflection vector
                half4 skyData = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, i.worldRefl);
                // decode cubemap data into actual color
                half3 skyColor = DecodeHDR (skyData, unity_SpecCube0_HDR);
                // output it!
                fixed4 c = 0;
                c.rgb = skyColor;
                return c;
            }
            ENDCG
        }
    }
}

おまけ

ビルドインシェーダーの関数はドキュメントに書かれてないものがあるので、ソースコードを調べてみました。 Unity - Download Archive:ビルドインシェーダーのソースコードがダウンロードできます。 例えば、UnityObjectToWorldNormal()のコード。こんな感じになってます。

// Transforms normal from object to world space
inline float3 UnityObjectToWorldNormal( in float3 norm )
{
#ifdef UNITY_ASSUME_UNIFORM_SCALING
    return UnityObjectToWorldDir(norm);
#else
    // mul(IT_M, norm) => mul(norm, I_M) => {dot(norm, I_M.col0), dot(norm, I_M.col1), dot(norm, I_M.col2)}
    return normalize(mul(norm, (float3x3)unity_WorldToObject));
#endif
}

Shader関連の気になる記事と参考記事

Shader Debugger [ Unity ] と[ Visual Studio ] で [ DirectX 11 ] [Microsoft HLSL Shader Debugger ] [シェーダーのデバッガー] を使ってみる。00200 | Whaison JUGEM! StudyNoteBook .

空間とプラットフォームの狭間で - Unityの座標変換にまつわるお話 -

内蔵(ビルドイン)シェーダのソースコードの配布ページ - 強火で進め

Unity - マニュアル: ビルトインシェーダーヘルパー機能

Shader 勉強メモ 「定義済値と組み込み関数」

前回まででシェーダーの扱いがなんとなくわかってきたので、次のサンプルをやる前に少し遊びます。 UnityのシェーダーはHLSLの組み込み関数を利用でき、Unity独自の定義済みの値も使えます。

組み込み関数 (DirectX HLSL)

[Unity] シェーダで使える定義済値 - Qiita

これらを使って、グニャーと変形させるシェーダーを作りました。前回のものに二行加えただけです。

Shader "Tutorial/DisplayNormalTransform"
{
    SubShader
    {
        Pass{

        CGPROGRAM

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

        struct v2f {
            float4 pos : SV_POSITION;
            fixed3 color : COLOR0;
        };

        v2f vert(appdata_base v) {
            v2f o;
            v.vertex.x *= 1 + pow(sin(_CosTime*v.vertex.y), 2);    // 追加
            v.vertex.z *= 1 + pow(sin(_CosTime*v.vertex.y), 2);    // 追加
            o.pos = UnityObjectToClipPos(v.vertex);
            o.color = v.normal * 0.5 + 0.5;
            return o;
        }

        fixed4 frag(v2f i) : SV_Target{
            return fixed4(i.color,1);
        }
        ENDCG
        }
    }
}

Shader 勉強メモ 「サンプルを理解する」

今回はUnityドキュメントのサンプルを理解していきます。

Unity - マニュアル: シェーダー: 頂点とフラグメントプログラム

最初のサンプルはメッシュの法線情報を色情報に変換するシェーダーです。

f:id:Dmiyamo3:20170308142124p:plain

Shader "Tutorial/DisplayNormal"{
    SubShader{
    Pass{

        CGPROGRAM

        // バーテックスシェーダーとフラグメントシェーダーの関数宣言
        #pragma vertex vert
        #pragma fragment frag

        // 内臓のシェーダーincludeファイル
        // UnityCG.cginc はビルトインシェーダーヘルパー機能
        // UnityCG.cginc は例えば以下のデータ構造を持つ
        // struct appdata_base:位置/法線/テクスチャ座標/頂点シェーダー入力
        // また、UnityObjectToClipPos()などが使えるようになる
        #include "UnityCG.cginc"

        // v2f:vertex to fragment
        // 頂点プログラムからフラグメントプログラムに渡される情報を定義します
        struct v2f {
            float4 pos : SV_POSITION;
            fixed3 color : COLOR0;
        };

        v2f vert(appdata_base v) {
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex);
            o.color = v.normal * 0.5 + 0.5;
            return o;
        }

        fixed4 frag(v2f i) : SV_Target{
            return fixed4(i.color,1);
        }
        ENDCG
    }
    }
}

次のサンプルですが、一行だけ変えてMain ColorとTextureの色を足し合わせるようにしました。

f:id:Dmiyamo3:20170308150058p:plain f:id:Dmiyamo3:20170308150108p:plain

Shader "Tutorial/Textured Colored" {
    Properties{
        _Color("Main Color", Color) = (1,1,1,0.5)
        _MainTex("Texture", 2D) = "white" { }
    }
    SubShader{
    Pass{

    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag

    #include "UnityCG.cginc"

    fixed4 _Color;
    sampler2D _MainTex;

    struct v2f {
        float4 pos : SV_POSITION;
        float2 uv : TEXCOORD0;
    };

    float4 _MainTex_ST;

    v2f vert(appdata_base v)
    {
        v2f o;
        o.pos = UnityObjectToClipPos(v.vertex);
        // UnityCG.cgincからTRANSFORM_TEXマクロを使用して
        // テクスチャスケールとオフセットが正しく適用されていることを確認
        o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
        return o;
    }

    fixed4 frag(v2f i) : SV_Target
    {
        fixed4 texcol = tex2D(_MainTex, i.uv);
        return texcol + _Color;   //変更点
    }
    ENDCG

    }
    }
}

テクスチャにチェック模様を入れれば黒い部分だけ色がつくようにできたりします。

f:id:Dmiyamo3:20170308162129p:plain f:id:Dmiyamo3:20170308162136p:plain f:id:Dmiyamo3:20170308162154p:plain

次回は、 Unity - マニュアル: Vertex and fragment shader examples のサンプルを触っていこうと思います。

参考サイト:

dragon & teapot model : http://graphics.cs.williams.edu/data/meshes.xml#7

Unity - マニュアル: シェーダーリファレンス

Unity Shader のコミュニティ

Shader 勉強メモ 「シェーダーとは?」

Unityでのシェーダーの位置づけ「シェーダーで何ができる?」

グラフィックスパイプライン:一連の描画工程

CPU上でのドローコール

 

バーテックスシェーダー

頂点数の増減・プリミティブの変更を含まない頂点属性の変更

プリミティブアセンブリ

 

テッセレーションシェーダー

プリミティブの分割粒度を変更できる

ジオメトリーシェーダー

頂点数の増減・プリミティブの変更を含む頂点属性の変更

ラスタライゼーション

 

フラグメントシェーダー

テクスチャやオブジェクトの表面情報を用いた複雑な陰影処理

ROP処理

 

フレームバッファの出力

 

※バーテックス=頂点情報、フラグメント=色情報・深度情報、プリミティブ=点と直線と三角形からなる基本図形

グラフィックスパイプライン外でのシェーダーの利用

コンピュートシェーダー

GPUでの汎用計算(GPGPU)、物理シミュレーション、画像処理/画像認識/ポストエフェクト、機械学習などの用途

Unity のコンピュートシェーダーは DirectX 11 の DirectCompute テクノロジに非常に近いものです。コンピュートシェーダーを実行できるプラットホームは以下のとおりです。

DirectX 11 グラフィックス API と Shader Model 5.0 GPU を伴う WindowsWindows ストア

・現段階で一般的に使用されている OpenGL プラットフォーム (LinuxWindows 上の OpenGL 4.3、Android 上の OpenGL ES 3.1)。Mac OS XOpenGL 4.3 に対応していないため、コンピュートシェーダーはまだ、利用することはできません。

・現段階で一般的に使用されているコンソール (Sony PS4Microsoft XboxOne)。

ー『Unity - マニュアル: コンピュートシェーダー』より引用

 Unityでのシェーダーの扱い「シェーダーをどうやって使う?」

Shader Labと呼ばれるUnity独自の形式。各種シェーディング言語で書かれたシェーダーをShader Labに埋め込むことでGPUに計算させることができる。以下のフォーマットで書かれる。

Shader “Tutorial/Test”{

              Properties{

 [UnityEditer上から編集できる変数やテクスチャの指定などの設定]

              }

              SubShader{

                            Pass{

                [各種シェーディング言語で書かれたシェーダー]

                            }

              }

              FallBack “Diffuse”

}

シェーディング言語の種類

GLSL (OpenGL Shading Language)

C言語ライクなシェーディング言語

Cg (C for Graphics)

NVIDIAが開発。2012年に開発終了。

HLSL (High Level Shading Language)

Microsoftが開発。コンピュートシェーダーも書ける。

MSL (Metal Shading Language)

Appleが開発。macOS/iOSに対応。

シェーダー実行時の処理

Shader Labの形式にCg/HLSLで記述→実行時プラットフォーム毎にGLSLに変換される。

 

シェーダー関連の気になる記事

Unity - マニュアル: グラフィックスコマンドバッファ

Unity - マニュアル: コンピュートシェーダー

Unity - マニュアル: DirectX 11 と OpenGL Core

Unity - マニュアル: 非同期テクスチャアップロード

Unity 上に自分で物理エンジンを実装したい - yuki-koyama's blog

Unityのシェーダーについて自分なりにまとめてみた - SSSSLIDE

Unityのシェーダを自分の言葉で説明してみる - 渋谷ほととぎす通信

 「塗り」を表現する技術 - SSSSLIDE

Unity備忘録: Unityのshaderまとめ(Shader Lab)

Shader 勉強メモ 「はじめに」

Shader、ずっと前から勉強しようと思っていたが、手を出していなかった。今回は記録を残すことでモチベーションを保っていこうと思います。開発環境はもちろんUnityで。

学習教材/参考資料は「Unityのリファレンス」と「ゲームアプリの数学 Unityで学ぶ基礎からシェーダーまで」と「CGWORLD (シージーワールド) 2013年 10月号 vol.182」、あとは凹みさんの記事や必要に応じて論文などを使っていこうかと。

勉強の進め方は

  1. 参考資料の内容をまとめて記事にする。
  2. 実際に使って確かめる。使った機能や関数などと画像を一緒にまとめて記事にする。
  3. 作ったコードをGithubに公開する。

主に2番でやっていくかと思います。次回から本格的にやっていきます。

CGWORLD (シージーワールド) 2013年 10月号 vol.182:「リアルタイムシェーダー入門」特集があり、p22-p37に歴史や用語がまとまっていたので買った。

tips.hecomi.com

あとshader関連の気になる記事や書籍など

シェーダー - Wikipedia

グラフィックスパイプライン - Wikipedia

床井研究室 - 第3回 シェーダプログラム

固定機能パイプライン | とまと・ソフトウェア製作所

megumisoft.hatenablog.com

 

VR/ARでの文字入力方法(キーボード)まとめ

概要

VR HMD(ヘッドマウントディスプレイ)のOculus Rift, HTC Vive, PSVR, Fove, Daydream, ハコスコ。AR HMDのHololens, meta。

現在、数多くのVR/ARのHMDが世の中に出回っています。これらHMDは周りを見渡したり動き回ったりして使用するため、マウスやキーボードのように机に置くようなデバイスは使い勝手が悪いことが多いです。ということで、その代わりとなるような文字入力方法が色々と考えられています。今回はそれらのデバイスで「どのような文字入力方法(キーボード)が考案/実装されているのか」についてまとめようと思います。

気が向いたら更新すると思います。「あれ、なんか足りなくない?」とかあれば、教えて頂ければうれしいです。

 文字入力方法の種類

  • 従来のキーボードを用いた方法:いつもの入力方法。
  • 「ノート型デバイス」を用いた方法:研究
  • 「コントローラー」を用いた方法 :Oculus Touch / Viveコン / PS Move / Daydreamコン
  • 「ハンドモーションキャプチャ」を用いた方法:Leap Motion / Hololens?
  • 「視線(頭)」を用いた方法:Fove / その他の vr/ar HMD
  • 「音声」を用いた方法:全ての vr/ar HMD
  • スマホHMD」を用いた方法:全ての vr/ar HMD

ノート型デバイスを用いた方法

1.『Poupyrev, Ivan, Numada Tomokazu, and Suzanne Weghorst. "Virtual Notepad: handwriting in immersive VR." Virtual Reality Annual International Symposium, 1998. Proceedings., IEEE 1998. IEEE, 1998.』:ペンとノート型のデバイスを持って使う。現実で持っているノートがVR空間上に現れる。ペンでノートに文字を書けば、VR空間のノートにも同じように書かれる。

ドラムスティック方式

ドラムスティックで従来型キーボードのボタンを押す方式。ブラインドタッチはできなさそう。

1.Drum Keys - Google Daydream Lab: 

2.Cutie Keys - Normal VR : https://github.com/NormalVR/CutieKeys/

 ほとんど同じ。こちらはオープンソース

てんちょー方式

立体方式(両手)・フリック方式(片手)でアルファベットも日本語も入力できる。キー配置の色んなアイデアがあって楽しい。

 扇型方式

yutokun:ハンドコントローラーでVR日本語入力✏ - Qiita

手首をひねって扇形のUIから文字の選択。人差し指のトリガーで文字の決定。スティックの上下で濁音などに対応。文字選択時に振動のフィードバックあり。

f:id:Dmiyamo3:20170212142224p:plain

GitHub - yutokun/VR-Text-Input: VR Text Input Method for Japanese. 』より引用

フリック方式

コントローラーで スマホフリック入力をできるようにしたもの。

ハンドモーションキャプチャーを用いた方法

Leap Motionを用いた文字入力

1. Leap Motion で日本語の文字入力・文字認識 | Do Design Space

空中に指で文字を描き、手書き文字認識し、入力する。

2.『細野敬太, et al. "Leap Motion を用いたジェスチャ操作による文字入力方法の提案." 人工知能学会全国大会論文集 28 (2014): 1-4.』

3. 将来的に(oculusがPebbles Interfacesを買収してVRグローブを研究しているので、そちらもそのうち出てくると思います。)

視線(頭)を用いた方法

1. Fove:視線を動かしてポインティングする方式

f:id:Dmiyamo3:20170212151608p:plain

FOVE: The World's First Eye Tracking Virtual Reality Headset by FOVE — Kickstarter』より引用

2. その他のHMD:頭を動かしてポインティングする方式。

音声を用いた方法

音声認識用いることでマイクのついているHMDならどれでもできる。

スマホHMDを用いた方法

HoloKeyboard - @sumihiro(twitter):iPhoneからHoloLensに文字入力ができるというもの。このアプリはHolo専用ですが、技術的には他のHMDにも応用可能だと思います。

ヤバいスミヒロ on Twitter: "HoloLensのキーボードとして使えるiPhoneアプリをオープンソースで公開しました。日本語も使えます。 #HoloLens #HoloLensJP #HoloJP
https://t.co/ilTfK10BvO https://t.co/cVb6d5XbJx"

 あとがき

今回は実例ばかりで論文や研究段階のものはあまり調べていません。今後時間があったらチェックしていこうかなと思います。また、情報が不足している部分も後で埋めていこうと思います。