ShaderGraphでインタラクティブな表現を実装【Unity、ShaderGraph、マウス操作、タップ】

# ■ 概要
本記事ではUnityの **「ShaderGraph」** と **「マウス操作」** を組み合わせたインタラクティブな表現の実装を紹介します。

今回は、[「ShaderGraphでマーブルノイズを実装」](https://qiita.com/generosity_honda/items/f851f79f9727551a8f11)の記事の実装を流用して、マウスオーバーしたカーソル位置のマーブルノイズカラーを変更する実装を試してみます。

# ■ 環境

Unityバージョン：Unity2022.3.44f1
プロジェクトテンプレート：Universal 3D


**今回はShaderGraphの機能が標準で搭載されている「URP」レンダリングパイプラインのプロジェクトで実装しています。**

※ビルトインのレンダリングパイプラインでも、パッケージを後からインストールしてShaderGraphを使用することができます。
[その手順はこちらの記事が参考になります。](https://ekulabo.com/unity-built-in-shader-graph)

# ■ 実装

Game画面：
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730387/8e1f41a1-caaf-0e38-d560-24ca09798b6a.gif" width="480">


今回の実装のShaderGraphファイル：
![スクリーンショット 2024-10-21 184914.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730387/42eff972-4000-a0af-ff2c-f59717512c89.png)

[「ShaderGraphでマーブルノイズを実装」](https://qiita.com/generosity_honda/items/f851f79f9727551a8f11)の記事と合わせたShaderGraphファイル：
（実装の詳細は画像を拡大して見ていただけると。）

![スクリーンショット 2024-11-28 124811.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730387/6be6ae21-dbd1-85a7-96e4-831c1b0ddc76.png)

# ■ 実装のポイント

今回の実装ではメッシュのUV座標を使いマウス位置との距離を計算して、マウス位置に近い部分の色を変化させています。

要所を1つずつ説明します。

## ① 別パターンのカラーを生成
マウスオーバーしたカーソル位置の色を変更させたいため、変更したいカラーを生成しておきます。
今回は濃い青色のマーブル模様のみを変更させたいので、同じマーブル模様のパターンを使用して紫色のマーブル模様を生成しておきます。

（[「ShaderGraphでマーブルノイズを実装」](https://qiita.com/generosity_honda/items/f851f79f9727551a8f11)の記事の続きからだと6番目の手順ということになります。）


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730387/853d3420-a91e-6ca1-1fd4-c7e652b20268.png" width="300">

## ② マウスオーバーのUV座標のプロパティを定義する
今回はマウスオーバーの座標をシェーダーに引き渡す必要があるので、シェーダーにプロパティを定義しておきます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730387/d6e7842b-9262-d9fd-4f60-385208a042af.png" width="300">


下記は実装例で、マウスオーバーのUV座標をシェーダーのプロパティにセットしています。

```MouseOverPositionDetector.cs
using UnityEngine;
using UnityEngine.InputSystem;

public class MouseOverPositionDetector : MonoBehaviour
{
    public Material targetMaterial;
    public Camera mainCamera;

    void Update()
    {
        Vector2 screenPosition = Mouse.current.position.ReadValue();

        Ray ray = mainCamera.ScreenPointToRay(screenPosition);
        RaycastHit hit;

        if (Physics.Raycast(ray, out hit))
        {
            // UV座標を取得
            Vector2 uv = hit.textureCoord;

            // シェーダーにUV座標を引き渡す
            targetMaterial.SetVector("_MouseOverPosition", uv);
        }
    }
}
```

## ③ 距離マップを生成する
プロパティにセットされているマウスオーバー位置のUV座標とメッシュのUV座標との2Dベクトル間の距離を計算します。この処理によってマウスオーバー位置に近いピクセルほど「0」に近くなるグラデーションの距離マップが生成されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730387/f3048e46-ff75-c3d4-d6f7-8e719f2f185e.png" width="300">

## ④ グラデーションの範囲を制限
「Smoothstep」ノードを使用し、グラデーションの範囲を制限します。
「Smoothstep」ノードは、第1引数の値より小さい値は「0」になり、第2引数の値より大きい値は「1」になり、その間の値はグラデーションで補間されます。
そのため先ほどの距離マップをこの「Smoothstep」ノードに通すと、画像のようにグラデーションの幅が制限されます。

今回はその結果を線形補間のパラメーターとして使用しマウス位置に近いほど紫色に変化させたいため、「One Minus」ノードで反転させておきます。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730387/d5d1232c-11ea-fc48-5cc4-472225d8b09a.png" width="300">



## ⑤ 2パターンのカラーを線形補間
グラデーションの出力結果をパラメーターとして、2パターンのカラーを線形補間する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730387/094927af-b523-ad37-b5f0-afa421f62924.png" width="300">


# ■ 最後に （感想）

今回は簡易的にマウス操作のパラメーターを使用して、インタラクティブなShader表現を実装してみました。
応用でマーブルノイズの強度を変更させたりなど、色々な表現が可能になるかと思います。

ご覧いただきありがとうございました。