モデルのアニメーションテクスチャ。シェーダーの書き方は?


9

ロケットリーグを見ていて、アニメーションのデカールとホイールがあることに気づきました。

画像

上の画像の効果に似たものを実装したいと思います。

Unityシェーダーを作成してホイールエフェクトを作成するにはどうすればよいですか?

シェーダーについてよく知りませんが、標準のUnityシェーダーを編集してアニメーション効果を実行できますか?


3
シェーダーは、スクロールテクスチャのような単純なものでも、間違いなくここでの主なソリューションです。Unityには_Time、(頂点)シェーダーのテクスチャ座標に追加できる組み込み変数があり、スクロール効果を簡単に取得できます。六角形の効果も非常に簡単です。質問を編集して1つの効果のみを強調し、「Unityシェーダーでこれをどのように実装しますか?」と尋ねると、おそらく私たちがお手伝いできます。シェーダーがライティング/シャドウイングに応答する必要があるかどうかを指定してください。これは、シェーダーの記述方法に影響を与えるためです。
DMGregory

情報をありがとう。私の質問が変わりましたが、それは少し良いですか?私はライティングとシャドウイングについて本当に知らないので、シェーダーについて理解を深めるまで、ここでは省略しました。欲しいと思いますが、標準のシェーダーからパーツをコピーするだけでいいのでしょうか?
JacketPotatoeFan 2017年

3
私は今夜​​少し後で答えを拡張します(誰かが今答えたいなら、私をそれに打ち負かしても構いません!)-しかし、通常は「表面シェーダー」として照明を使用するUnityシェーダーを書きます。一方、照明を必要としないものは、「Unlit Shader」として書く方が簡単です。これらのホイールは照らされていないように見えます(端のわずかな影はSSAOのように見えます)。そのため、最初は照明を画像から外しておきます。あなたは明確にすることができます:あなたはここに示されている幾何学的パターンを正確に望んでいますか、それとも任意のテクスチャを外側にスクロールして虹のような色合いにしたいですか?
DMGregory

どうもありがとうございました。私を始めるためにどんな情報でも提供していただければ幸いです。私はシェーダーを書くことができる人々に本当に感心します、Unity Shadersについていくつかの記事を見てきました、そしてええ、とても混乱しています。テクスチャー(またはテクスチャーuvs?)をスクロールするだけで十分で、色合いを付けることができると思います。
JacketPotatoeFan 2017年

回答:


13

これをいくつかの層に積み上げて、どのように組み合わされるかを確認できるようにします。

Unityで新しいシェーダーを作成することから始めCreate --> Shader --> Unlitます。[プロジェクト]ウィンドウの[アセット]メニューまたは右クリックコンテキストメニューを選択します。

上のブロックに_ScrollSpeeds、テクスチャーが各方向に動く速度を制御するパラメーターを追加します。

Properties
{
    _MainTex ("Texture", 2D) = "white" {}
    _ScrollSpeeds ("Scroll Speeds", vector) = (-5, -20, 0, 0)
}

これにより、マテリアルインスペクタに新しい4コンポーネントフロートプロパティが表示されます。これは、「Scroll Speeds」というわかりやすい名前で付けられています(スクリプトにpublicまたはSerialized変数を追加するのと同じですMonoBehaviour)。

次に、この変数を頂点シェーダーで使用o.uvして、デフォルトのシェーダーに2行だけ追加することにより、テクスチャ座標()をシフトします。

sampler2D _MainTex;
float4 _MainTex_ST;
// Declare our new parameter here so it's visible to the CG shader
float4 _ScrollSpeeds;

v2f vert (appdata v)
{
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.uv = TRANSFORM_TEX(v.uv, _MainTex);

    // Shift the uvs over time.
    o.uv += _ScrollSpeeds * _Time.x;

    UNITY_TRANSFER_FOG(o,o.vertex);
    return o;
}

それをクワッドで叩いて(ケニーによる素敵な無料のキリンの質感で)、あなたは次のようになります:

キリンが繰り返しスクロールするクワッド。

テクスチャをリング内で外側にスクロールするには、スパイダーウェブのように細分割されたメッシュを使用し、中心から外側に向かってUV V座標を増加させます。しかし、それはそれ自体でいくつかの鋸刃状のアーティファクトを与えます。代わりに、フラグメントごとのUVを計算する方法を示します。

これは、trig&length操作(基本的な計算よりもコストが高い)と、補間するだけではなく、フラグメントごとにtexcoordを計算するときにハードウェアでテクスチャデータを予測してキャッシュするのが効率的でないため、少しコストがかかります。頂点間。しかし、このような小さな特殊効果の場合、それは過度ではありません。

v2f vert (appdata v)
{
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);

    // Shift the UVs so (0, 0) is in the middle of the quad.
    o.uv = v.uv - 0.5f;

    UNITY_TRANSFER_FOG(o,o.vertex);
    return o;
}

fixed4 frag (v2f i) : SV_Target
{
    // Convert our texture coordinates to polar form:
    float2 polar = float2(
           atan2(i.uv.y, i.uv.x)/(2.0f * 3.141592653589f), // angle
           length(i.uv)                                    // radius
        );

    // Apply texture scale
    polar *= _MainTex_ST.xy;

    // Scroll the texture over time.
    polar += _ScrollSpeeds.xy * _Time.x;

    // Sample using the polar coordinates, instead of the original uvs.
    // Here I multiply by MainTex
    fixed4 col = tex2D(_MainTex, polar);

    // apply fog
    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}

それは私たちにこのようなものを与えます(ここで私はマテリアルのタイリングパラメーターを増やしたので、何が起こっているのかより明確になります-円の周りのタイルの単一の繰り返しだけを包むことは歪んで奇妙に見えます)

クワッドの中心から外側に向かって広がるキリンのタイリング

最後に、スクロールグラデーションでテクスチャに色を付けるには、2番目のテクスチャとしてグラデーションを追加し、それらを掛け合わせるだけです。

最初に、新しいテクスチャパラメータを上部に追加します。

Properties
{
    _MainTex ("Texture", 2D) = "white" {}
    _TintTex("Tint Texture", 2D) = "white" {}
    _ScrollSpeeds ("Scroll Speeds", vector) = (-5.0, -20.0, 0, 0)
}

そして、CGシェーダーがそれを見ることができるように、それをCGPROGRAMブロックで宣言します。

sampler2D _MainTex;
float4 _MainTex_ST;

// Declare our second texture sampler and its Scale/Translate values
sampler2D _TintTex;
float4 _TintTex_ST;

float4 _ScrollSpeeds;

次に、フラグメントシェーダーを更新して両方のテクスチャを使用します。

fixed4 frag(v2f i) : SV_Target
{
    float2 polar = float2(
           atan2(i.uv.y, i.uv.x) / (2.0f * 3.141592653589f), // angle
           length(i.uv)                                    // radius
        );

    // Copy the polar coordinates before we scale & shift them,
    // so we can scale & shift the tint texture independently.
    float2 tintUVs = polar * _TintTex_ST.xy;
    tintUVs += _ScrollSpeeds.zw * _Time.x;

    polar *= _MainTex_ST.xy;
    polar += _ScrollSpeeds.xy * _Time.x;

    fixed4 col = tex2D(_MainTex, polar);
    // Tint the colour by our second texture.
    col *= tex2D(_TintTex, tintUVs);

    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}

そして今、私たちのキリンは本当にトリッピーになります:

遠く、男...

テクスチャとスクロールレートを少し芸術的に選択すると、質問で示したものと非常によく似た効果が得られます。


上記で示したバージョンの2つの小さなアーティファクトに気付くでしょう。

  • 円の中心付近の顔は引き伸ばされた/細く/先のとがったものになり、外側に向かって移動すると、押しつぶされた/広くなります。

    この歪みは、周囲に一定数の面があるために発生しますが、半径が大きくなると、それらがまたがっている円周は、高さが同じままで広くなります。

    これを修正するには、テクスチャサンプルの垂直成分を再マップして対数曲線をたどります。そのため、テクスチャの繰り返しは、半径が大きくなるにつれて離れ、中心に近づくほど近くなります。(実際には、これは私たちにますます小さなキリンの無限の退行を与えます...)

  • クワッドの左中央に沿って1つまたは2つのぼやけたピクセルの行があります。

    これは、GPUが2つの隣接するテクスチャサンプル座標を調べて、使用するフィルタリングを把握するために発生します。サンプルが近接している場合、テクスチャが大きく/近接して表示されていることがわかり、最も詳細なミップレベルが表示されます。サンプルが遠く離れている場合は、テクスチャを小さなズームまたは遠くで表示している必要があると推測し、きらめくエイリアシングアーティファクトが発生しないように、小さい/ブラーミップマップからサンプリングします。

    問題はここです。極座標のラップアラウンドポイントである-180から180度です。そのため、実際には、繰り返されるテクスチャ空間の非常に類似したポイントからサンプリングしています。たとえそれらの数値座標によって、それらが離れているように見える場合でもです。したがって、これを修正するために独自のサンプリング勾配ベクトルを提供できます。

これらの修正を加えたバージョンは次のとおりです。

fixed4 frag(v2f i) : SV_Target
{
    float2 polar = float2(
           atan2(i.uv.y, i.uv.x) / (2.0f * 3.141592653589f), // angle
           log(dot(i.uv, i.uv)) * 0.5f                       // log-radius
        );

    // Check how much our texture sampling point changes between
    // neighbouring pixels to the sides (ddx) and above/below (ddy)
    float4 gradient = float4(ddx(polar), ddy(polar));

    // If our angle wraps around between adjacent samples,
    // discard one full rotation from its value and keep the fraction.
    gradient.xz = frac(gradient.xz + 1.5f) - 0.5f;

    // Copy the polar coordinates before we scale & shift them,
    // so we can scale & shift the tint texture independently.
    float2 tintUVs = polar * _TintTex_ST.xy;
    tintUVs += _ScrollSpeeds.zw * _Time.x;

    polar *= _MainTex_ST.xy;
    polar += _ScrollSpeeds.xy * _Time.x;

    // Sample with our custom gradients.
    fixed4 col = tex2Dgrad(_MainTex, polar, 
                           _MainTex_ST.xy * gradient.xy,
                           _MainTex_ST.xy * gradient.zw
                         );

    // Since our tint texture has its own scale,
    // its gradients also need to be scaled to match.
    col *= tex2Dgrad(_TintTex, tintUVs,
                          _TintTex_ST.xy * gradient.xy,
                          _TintTex_ST.xy * gradient.zw
                         );

    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}

2
1)V方向に対数曲線を使用すると、テクスチャが外側にスクロールしても形状が維持されます(中央のポイントまで狭めるのではなく、小さなコピーの無限のチェーンが得られます)。ミップはそれを塗りつぶします)2)独自のテクスチャグラデーションを計算しtex2Dgrad、角度を-piから+ piにラップするフィルタリングアーティファクトを修正します(左側のぼやけたピクセルの細い線です)。これは、より
青みを帯びた修正

すばらしい、故障もありがとう。私はシェーダーは書けないかもしれないものだと感じています(特に、「極」のために行ったことのようなものです。私は非常に基本的な数学のスキルしか持っていないので、数学のことは私には何の意味もありません)。
JacketPotatoeFan 2017年

1
そのような人々は通常、ただ見上げるだけです。;)キーボードから離れるだけで十分です。ただし、さまざまな数学関数をいじってみて、結果を確認してください。このようなツールを使用して、数学が幾何学的に行っていることを視覚化できるので、そもそも練習を始めました。(具体的にはシェーダーではなく、WhiteCapと呼ばれる古いWinAmpビジュアライザ...)シェーダーの数学がひどく間違っている場合でも、見た目が奇妙にクールであることがよくあります。:D
DMGregory
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.