夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

Blenderで服のウェイトを素体と合わせる。

本日はBlenderモデリング枠です。

昨日筆者のオリジナルキャラクターモデルにほかのクリエイターさんが作成された服を購入し合わせていきました。

f:id:Holomoto-Sumire:20210413154959j:plain

前回で立ち姿でのフィットができたのですが、キャラクターの動きに合わせた設定を行っていないためキャラクターを動かすと次の画像のように服を貫通してしまいます。

f:id:Holomoto-Sumire:20210413163050j:plain

今回は服を体の動きに合わせて動くようにウェイトペイントを設定します。

〇ウェイトペイントの複製

Blenderではウェイトペイントを別のオブジェクトへ複製するという機能があります。今回はこの方法で体のウェイトペイントを服へと複製していきます。

①[オブジェクトモード]にします。

f:id:Holomoto-Sumire:20210413212102j:plain

②[Shift]キーを押しながら服のメッシュ→[アーマーチュア(ボーン)]の順で選択します。

f:id:Holomoto-Sumire:20210413212159j:plain

③[Ctrl]キー+[P]キーを押し、[空のウェイトで]を選択します。

f:id:Holomoto-Sumire:20210413212601j:plain

この動作によって服のメッシュにボーンの頂点グループが設定されます。(ボーンごとの頂点グループ)

f:id:Holomoto-Sumire:20210413212717j:plain

④キャラクター→服の順に選択します。

f:id:Holomoto-Sumire:20210413212846j:plain

⑤[ウェイトペイント]モードへ切り替えます。

f:id:Holomoto-Sumire:20210413212930j:plain

⑥上部ワールドタブから[ウェイト]→[ウェイト転写]を選択します。

f:id:Holomoto-Sumire:20210413213201j:plain

⑦タブから[転送元のレイヤー]を[名前]に変更します。

f:id:Holomoto-Sumire:20210413213327j:plain

これによって同一名の頂点グループのウェイトテクスチャが転写されます。

以上で素体のウェイトペイントが服に転写されモデルの動きに合わせて服が動くようになりました。

f:id:Holomoto-Sumire:20210413220546j:plain

本日は以上です。

Blenderでシュリンプクラップを使用してオリジナルモデルに外部からインポートした服を着せる。

本日はBlenderモデリング枠です。

先日はBlenderでリアルな髪の毛を作り、さらにメッシュを法線に沿って拡大しました。

本日は服を着せていきます。

redhologerbera.hatenablog.com

redhologerbera.hatenablog.com

〇服を着せる

今回はこちらのモデルに服を着せます。 これは[MB-Lab]と[HairTool]で作成しています。

f:id:Holomoto-Sumire:20210412203643j:plain

服を選びます。今回は他のクリエイターさんが作成したモデルを自身のモデルに合わせていきます。

今回は[Nori7023]さんが[Booth]で販売しているこちらのモデルを使用します。

f:id:Holomoto-Sumire:20210412204035j:plain

booth.pm

[Nori7032]さんのブログ[Graph3D]でのモデルの見て感動したためこちらのモデルを購入しました。

3dgraph.me

まずはBlenderにモデルを[Inport]します。

f:id:Holomoto-Sumire:20210412204546j:plain

もちろんですが、筆者のモデルと体格が異なるためうまくマッチしていません。今回はこれをBlenderのモディファイア[シュリンプクラップ]を使用して合わせていきます。

〇シュリンプクラップを使用してモデルを合わせる

①[スカート]をモデルのお尻に合わせて配置します。

f:id:Holomoto-Sumire:20210412204845j:plain

②[スカート]のモデルを選択し[シュリンプクラップ]のモディファイアをアタッチします。

f:id:Holomoto-Sumire:20210412205141j:plain

③[シュリンプクラップ]モディファイアの[ターゲット]に素体を設定します。

これによってスカートがお尻に合わせて包み込むように変形します。

f:id:Holomoto-Sumire:20210412205257j:plain

このままでは手も包み込むように変形しています。 モデルの手を曲げて干渉しないようにしました。

f:id:Holomoto-Sumire:20210412205443j:plain

これで手に干渉しなくなりましたが、スカートの原型をとどめないままにピタリと素体に張り付いてしまっています。

④[ターゲットの法線に投影]、[外側]を設定します。

f:id:Holomoto-Sumire:20210412205917j:plain

これによってスカートのディティールが復活します。

⑤[オフセット]の値をあげます。

f:id:Holomoto-Sumire:20210412210158j:plain

⑥[適応]を選択します。 これによってモディファイアが反映されます。

トップに対しても同様に処理を行います。

これによってオリジナルのモデルにほかのクリエイターさんの作成された服のモデルを合わせることができました。

f:id:Holomoto-Sumire:20210412211518j:plain

Blenderで法線に沿ってメッシュの拡大、縮小を行う。

本日はBlender枠です。

Blenderには数多くの機能が提供されており、今回メッシュを法線に沿って拡大、縮小を初めて触ったため、記事に残します。

〇メッシュの拡大

Blenderではメッシュの拡大、縮小といったスケールの変更は[編集モード]でメッシュを選択した状態で[S]キーで行います。

f:id:Holomoto-Sumire:20210411194407g:plain

〇法線に沿って拡大、縮小

本日のお題です。

今回素体を基に法線に沿って拡大し、服を作成しようとしました。

①[編集モード]で対象のメッシュを選択します。

f:id:Holomoto-Sumire:20210411194918j:plain

②[Alt]キー+[S]キーを選択します。

f:id:Holomoto-Sumire:20210411195302g:plain

これによってメッシュの法線に沿って拡大縮小が行えます。

[S]キーによる拡大縮小とは異なるものが、テンキーによる操作です。

例えば[S]キー+[0.5]と入力すると0.5倍に拡大を意味します。

しかし[Alt]キー+[S]キー+[0.5]と入力すると0.5m拡大を意味します。

法線に沿って拡大する場合この点に注意する必要があるようです。

Blenderでリアルな髪を作成する。

本日はモデリング枠です。

以前リアルな髪の毛を作成するアドオン[Hair Tool for Blender]を導入してからしばらくの間勉強してやっと使えるようになってきたので記事にします。

f:id:Holomoto-Sumire:20210410211356j:plain

〇HairToolとは?

[HairTool]はbartoszstyperek氏によって提供されているBlender用の有料アドオンです。2021年4月現在52$で販売されています。(筆者が購入した時より若干値上げしているようです…)

HairToolは以下のリンクで販売されています。

gumroad.com

導入に関しては以前記事にしています。

redhologerbera.hatenablog.com

redhologerbera.hatenablog.com

〇HairToolでリアルな髪を作成する

筆者がいろいろ試した中で一番効率が良かったものを紹介します。

①キャラクターの素体を用意します。 今回は[MB-Lab]のアドオンで作成しています。

f:id:Holomoto-Sumire:20210410212432j:plain

②メッシュで髪の毛を作成し合わせます。 この方法はここでは紹介しませんが、[VRoid Studio]などで作成することもできます。またロイアルティフリーのモデルの頭を使用することもできます。 今回は後者の方法を用いています。

f:id:Holomoto-Sumire:20210410212700j:plain

③[編集モード]に切り替え髪の毛の束ごとにメッシュを選択し、[P]キーでメッシュを別オブジェクトとして切り出します。

f:id:Holomoto-Sumire:20210410212931j:plain

④[A]キーで髪の束のメッシュを全選択した状態で[ALT]キー+[J]キーを押します。

 この作業によって選択しているメッシュが三角ポリゴンから四角ポリゴンへと変わります。

f:id:Holomoto-Sumire:20210410213008j:plain

 [HairTool]を使用する場合ポリゴンを[Quad]にする必要があります。

⑤④で自動でQuadにできていないメッシュを手動でQuadに変換します。

f:id:Holomoto-Sumire:20210410213512j:plain

ジオメトリから三角ポリゴンがなくなればOKです。

⑥髪の生え際に当たる辺を選択します。

f:id:Holomoto-Sumire:20210410213636j:plain

⑦上部ワールドタブから[]→[シャープをマーク]を選択します。

f:id:Holomoto-Sumire:20210410213809j:plain

これは[HairTool]を使用する際の髪の流れを指定するために使用されます。

⑧[オブジェクトモード]へ切り替えます。準備が終わった状態が以下の様になります。

f:id:Holomoto-Sumire:20210410214050j:plain

⑨[HairTool]のタブから[Curves from grid surface]を押します。

f:id:Holomoto-Sumire:20210410214218j:plain

この作業によってカーブのオブジェクトが作成されます。

f:id:Holomoto-Sumire:20210410214401j:plain

⑩[Add profile]を選択します。

f:id:Holomoto-Sumire:20210410214455j:plain

この作業によってメッシュが生成されます。

f:id:Holomoto-Sumire:20210410214616j:plain

⑪[Materials/UV Refresh]を選択します。

f:id:Holomoto-Sumire:20210410214717j:plain

これによってメッシュにマテリアルが適応され髪の毛の見た目が作成されます。

f:id:Holomoto-Sumire:20210410214845j:plain

⑫ ③~⑪の動作を髪の束ごとに行います。これによって最終的に以下のようにリアルな髪の毛が完成します。

f:id:Holomoto-Sumire:20210410215052j:plain

〇調整

上記の方法で髪の毛が作成できますが、最終的に調整が必要になることがあります。

例えば以下の画像の場合つむじ部分が剥げてしまっています。

f:id:Holomoto-Sumire:20210410215213j:plain

髪の毛の束を[Shift]キーで選択し[編集モード]に切り替えます。

f:id:Holomoto-Sumire:20210410215443j:plain

これによって髪の毛のカーブの制御点が表示されます。生え際の制御点を選択します。

f:id:Holomoto-Sumire:20210410215656j:plain

[S]キー+[0]キーで縮小します。

f:id:Holomoto-Sumire:20210410215753j:plain

[G]キーでつむじ部分を移動させ肌が見えないように移動します。

f:id:Holomoto-Sumire:20210410215901j:plain

以上で剥げている部分が消えました。

f:id:Holomoto-Sumire:20210410215941j:plain

以上で[HairTool]を用いてリアルな髪の毛を作成できました。

f:id:Holomoto-Sumire:20210410222407j:plain

UnityShaderGraphで多角形の表現を行う

本日はUnity Shader調査枠です。

UnityではHDRLもしくはURPを導入することでShaderGraphが使用できるようになります。

ShaderGraphを用いることで専門的な知識が無くてもShaderをより簡単に構築できるようになりました。

今回は昨日作成した多角形の表現をShaderGraphで行います。

〇多角形の方程式のおさらい

Shaderで多角形を表現する方程式は次のようになります。

f:id:Holomoto-Sumire:20210408211342j:plain

前回はShaderLabで多角形表現を行いました。

redhologerbera.hatenablog.com

f:id:Holomoto-Sumire:20210408215816j:plain

〇ShaderGraphで多角形表現を行う。

①[Unlit]のShaderGraphを作成します。

f:id:Holomoto-Sumire:20210409203327j:plain

②ShaderLabでのフラグメントシェーダー部を再現する

                fixed4 col = _Color*(sin(map(i.uv) * 10) + 1) /1.6;
                
                return col;

colは表示カラーを意味します。

[_Color]という変数を作成します。

f:id:Holomoto-Sumire:20210409204453j:plain

③[Multiply]ノードを作成し、作成した変数[Color]を入力に、出力部をUnlitの[Color]と接続します。

f:id:Holomoto-Sumire:20210409205126j:plain

これはShaderLabでいうところの次の部分に当たります。

fixed4 col = _Color*  

④[sin]ノードと[Divide]ノードを作成し画像のように[Multiply]と接続します。

f:id:Holomoto-Sumire:20210409205450j:plain

これはShaderLabでいうところの次の部分に当たります。

fixed4 col = _Color* (sin() /1.6;

⑤[Multiply]と[Add]を作成します。 画像のようにつなぎます。

f:id:Holomoto-Sumire:20210409210117j:plain

fixed4 col = _Color*(sin(  * 10) + 1) /1.6;

⑥次にShaderLabのmap変数を作成します。

        float map(float2 uv){
                float2 fPos = frac(uv);

                fPos.x = fPos.x * 1. - .5;
                fPos.y = fPos.y * 1. - .5;

                return dPolygon(fPos * _Pattern, _N, 0) - _Time.x * 3.;
            }

map変数はdPolygonが返されます。

 return dPolygon(fPos * _Pattern, _N, 0) - _Time.x * 3.;

さきに[dPolygon]を作成します。

   float dPolygon(float2 p, int n, float size){
                float a = atan2(p.x, p.y) + PI;
                float r = 2 * PI / n;
                return cos(floor(.5 + a / r) * r - a) * length(p) - size;
            }

dPolygonではUvの成分ごとに処理を行っていますが、UVノードでは以下のようにVector4型として扱い、成分を取り出すことができませんでした。

f:id:Holomoto-Sumire:20210409211604j:plain

そこで今回は[CustomFunction]ノードを使用しました。

redhologerbera.hatenablog.com

⑥[UV]ノード、[CustomFunction]ノードを作成します。

f:id:Holomoto-Sumire:20210409211716j:plain

⑦[CustomFunction]のStringに以下のコードを記述します。

float a = atan2(UV.x, UV.y) + PI;
float r = 2 * PI / n;
output = cos(floor(0.5 + a / r) * r - a) * length(UV) - size; 

これはPolygonの中身と同じです。

これをUVノードと接続します。

f:id:Holomoto-Sumire:20210409212613j:plain

以上で[Polygon]が完成しました。

次にmap変数を作成します。

⑧[Multiply]ノードを作成しUVと接続します。

f:id:Holomoto-Sumire:20210409213152j:plain

⑨[_Pattern]変数をMultiplyと接続します。

f:id:Holomoto-Sumire:20210409213324j:plain

⑩[Polygon]の入力に変数[_N]を接続します。

f:id:Holomoto-Sumire:20210409213421j:plain

⑪[fraction]ノードを作成し、UVと接続します。

f:id:Holomoto-Sumire:20210409213722j:plain

以上でShaderGraphでも多角形の表現ができました。

f:id:Holomoto-Sumire:20210409214640j:plain

変数[N]の値を変えると正N角形の表現が行えます。

f:id:Holomoto-Sumire:20210409214717j:plain

多角形の図面を描くShaderを描く

本日はShader学習枠です。

今回はShader表現の一つとしてサーバーグラフィックスでよく見る多角形の模様を作成します。

〇多角形の方程式

n角形の図形の方程式は次のようになります。

f:id:Holomoto-Sumire:20210408211342j:plain

これをShaderLabで記述します。

〇多角形の処理

次の基礎的なスクリプトを作成しました。

Shader "Custom/NewSurfaceShader"
{
   Properties
    {
        _Color ("Color", color) = (1.0, 1.0, 1.0, 1.0)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
 
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include <Lighting.cginc>
            #include <UnityShaderUtilities.cginc>

            struct appdata {
                float4 vertex : POSITION;
                float2 uv: TEXCOORD0;
            };
 
            struct v2f {
                float4 pos : SV_POSITION;
                float2 uv :TEXCOORD0;
            };
 
            v2f vert(appdata v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv= v.uv;
                return o;
            }
 
            // Color from the property section
            float4 _Color;
 
            float4 frag(v2f i) : SV_Target {

                
                return _Color;
            }
 
            ENDCG
        }
    }
}

このShaderのを加工します。

まずは多角形を描く関数をさくせいします。

  static const float PI = 3.14159265;
            v2f vert(appdata v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv= v.uv;
                return o;
            }
               float dPolygon(float2 p, int n, float size){
                float a = atan2(p.x, p.y) + PI;
                float r = 2 * PI / n;
                return cos(floor(.5 + a / r) * r - a) * length(p) - size;
            }

[PI]は円周率を意味します。

次にUVを移動するための関数を作成します。

            float map(float2 uv){
                float2 iPos = floor(uv);
                float2 fPos = frac(uv);

                fPos.x = fPos.x * 1. - .5;
                fPos.y = fPos.y * 1. - .5;

                return dPolygon(fPos * _Pattern, _N, 0) - _Time.x * 3.;
            }

これによって多角形の値を扱うことができるようになりました。

最後にフラグメントシェーダーを編集します。

            float4 frag(v2f i) : SV_Target {
                fixed4 col = _Color*(sin(map(i.uv) * 10) + 1) /1.6;
                
                return col;
            }

uv情報をmapに渡し、UV上で多角形を描きます。

これによって次の様に多角形が広がる演出を行えます。

f:id:Holomoto-Sumire:20210408215816j:plain

〇Shader全文

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/NewSurfaceShader"
{
   Properties
    {
        _Color ("Color", color) = (1.0, 1.0, 1.0, 1.0)
        _N("n",float)=6
        _Pattern("pattern",float)=1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
       
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include <Lighting.cginc>
            #include <UnityShaderUtilities.cginc>

            struct appdata {
                float4 vertex : POSITION;
                float2 uv: TEXCOORD0;
            };
 
            struct v2f {
                float4 pos : SV_POSITION;
                float2 uv :TEXCOORD0;
            };
             static const float PI = 3.14159265;
            v2f vert(appdata v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv= v.uv;
                return o;
            }
               float dPolygon(float2 p, int n, float size){
                float a = atan2(p.x, p.y) + PI;
                float r = 2 * PI / n;
                return cos(floor(.5 + a / r) * r - a) * length(p) - size;
            }
            float _Pattern;
            float _N;
            // Color from the property section
            float4 _Color;

                        float map(float2 uv){
                float2 fPos = frac(uv);

                fPos.x = fPos.x * 1. - .5;
                fPos.y = fPos.y * 1. - .5;

                return dPolygon(fPos * _Pattern, _N, 0) - _Time.x * 3.;
            }
            float4 frag(v2f i) : SV_Target {
                fixed4 col = _Color*(sin(map(i.uv) * 10) + 1) /1.6;
                
                return col;
            }
 
            ENDCG
        }
   

    }
}

Unity ShaderGraphでCustomFunctionを使用する。

本日はUnityShader枠です。

UnityではSRPプロジェクトで[ShaderGraph]が使用可能です。

[ShaderGraph]の登場によってShaderLabより低コストで学習を進めることができます。

また従来のShaderLabではいちいちコンパイルする必要がありましたが、ShaderGraphではリアルタイムで結果を出力してみることができます。

しかしながらShaderGraphのノードでは対応していない場合や、複雑な処理などを行う際大量のノードを接続すると可読性が下がることがあります。

ShaderGraphでは[CustomFunction]と呼ばれる特殊なノードが提供されており、ユーザーがカスタムしたノードを作成可能です。

f:id:Holomoto-Sumire:20210407100011j:plain

[CustomFunction]は作成時は上図のように何もすることができません。

ノード上部の歯車マークをクリックしプロパティを開きます。

f:id:Holomoto-Sumire:20210407100543j:plain

[Source]がデフォルトで[File]となっています。これはShaderLabでいうところの以下の処理に該当します。

#inclube UnityCG.cginc(のような外部ファイル)

つまり外部ファイルに定義した関数を使用する場合に使用します。 よく使用する関数を用意します。

この[Source]を[String]に変更します。 

f:id:Holomoto-Sumire:20210407100802j:plain

これによってHLSLの処理を記述することができるようになります。

今回次のように処理を書いてみました。

Outa=In.x*0.5;
Outb=In.y*0;

この処理ではVector2型の変数Inのx成分に0.5を積算した値がOuta、Inのy成分に0をかけたもの(実質0)がOutbという変数代入されます。

この処理を行うためにはInという入力値とOuta,Outbという出力値が必要です。

これはCustomFunctionの[Input],[Output]に定義します。

f:id:Holomoto-Sumire:20210407101433j:plain

これによってCustomFunctionを使用したオリジナルノードが作成できました。

f:id:Holomoto-Sumire:20210407101547j:plain

入出力を設定したことでノードのソケットが表示されます。

結果を見てみます。

f:id:Holomoto-Sumire:20210407102050j:plain

今回Vector2型で変数を作成、最初は1の値でしたが、Outaではグレー(0.5)、Outbでは黒(0)が出力されました。

ShaderGraphでHLSLを記述することもできたので複雑な処理も行えそうです。