Aizu-Progressive xr Lab blog

会津大学のVR部であるA-PxLの部員が持ち回りで投稿していくブログです。部員がそれぞれVRに関する出来事やVRにちなんだことについて学んだことを書いていきます。

連絡はサークルTwitterのDMへお願いします。
「面白法人カヤックVR分室」としても活動しています。詳細はこちら

アバターの服の一部に動く絵をかく

はじめに

こんにちは, 学部3年の木村です.
この記事では, 私がよく使わせて頂いているこのアバターの着物の模様を自分でもかきたくなったのでシェーダーで袖に絵を描けるようにしたことを書きます.

豊姫うか -Toyohime Uka- ver.2.00

試したこと

袖の領域をマスクする

まずは袖のマスク用のテクスチャを用意しました.

こんな感じで袖の領域を切り抜けます.

シェーダーはArktoon-Shadersを少し改変して使いました.
arcludeFrag.cgincのフラグメントシェーダーでDiffuseが宣言している箇所を以下のように変更し, float3 customColor(float2 uv, float3 color)関数内で絵を描きます.

float3 Diffuse = (customColor(i.uv0, _MainTex_var.rgb)*REF_COLOR.rgb);

上の画像のようにマスクした領域をピンクに塗る場合はこのようになります.

float3 customColor(float2 uv, float3 color)
{
    float mask = UNITY_SAMPLE_TEX2D(REF_SHADERMASK, TRANSFORM_TEX(uv, REF_SHADERMASK)).r;
    return lerp(color, float3(1, 0, 1), mask);
}


ここで試しに袖に絵を描いてみましたが, 境界線が目立ってしまってよくなかったです.

UV座標を見て頑張る

次に試したのは絵を描きたい領域をUV座標で直接切り分ける方法です.

float2 st = uv*2. - 1.;
float3 col = color;
if(color.r >= .1 && color.g >= .1 && color.b >= .1) return float3(st, 0);   // 襟の部分
if(st.x >= 0.) return float3(st, 0);  // 胴の部分
if(st.y <= 0.) 
{
   // 左袖
   st = mul(st + 1., R(-.74));
   float i = smoothstep(.5, 1., st.x);
   st.x -= _Time.x*.5;
   st.y += _Time.x;
   col = lerp(col, float3(st.x-.83, st.y+.2, 0), i);
} else
{
   // 右袖
   st = mul(st, R(-.85));
   float i = smoothstep(.5, 1.,st.y);
   st.x += _Time.x;
   st.y -= _Time.x*.5;
   col = lerp(col, float3(st.x + .25, st.y-.8, 0), i);
}
return col;

無理矢理感しかないですが, とりあえず部位ごとに色を塗れるようになりました.
あとは袖にだけ絵を描きます.

最終的にこうなりました

花びらの距離関数

float sdFlower(float2 p, float size)
{
    p+= .5;
    p*=.7;
    float a = atan2(p.y, p.x);  // -PI~PI
    a+= sin(_Time.y);
    float d = min(abs(cos(a * 5.) + .4), abs(sin(a * 5.)) + 1.1) * .32*size;
    return step(length(p), d);
}

今後

この記事を書いてる途中でマスクを使っても境界線は誤魔化せそうだなと思いました.
また, 花びらの動き方など単調なのでもっと自然の花びらのような動きをさせたいです.

会津大学VR部の部員が持ち回りで投稿していくブログです。特にテーマに縛りを設けずに書いていきます!