本日はUnity枠です。
前回はComputeShaderでメッシュの回転を行っていきました。
ここでは回転行列を使用することでメッシュを回転させるアニメーションを行いました。
今回はスケールをアニメーションさせていきます。
〇環境
・Unity2022.3.26f1
・Windows11PC
〇スケール
回転は回転行列を使用しましたが、スケールはスケーリング行列を使用します。
スケーリング行列をHLSL文であらわすと次のようになります。
// スケール行列
float4x4 GetScaleMatrix(float scale)
{
return float4x4(
float4(scale, 0, 0, 0),
float4(0, scale, 0, 0),
float4(0, 0, scale, 0),
float4(0, 0, 0, 1)
);
}
行列を使用したコンピュートシェーダーは以下のようになります。
// スケール行列
float4x4 GetScaleMatrix(float scale)
{
return float4x4(
float4(scale, 0, 0, 0),
float4(0, scale, 0, 0),
float4(0, 0, scale, 0),
float4(0, 0, 0, 1)
);
}
[numthreads(256, 1, 1)] // スレッドの設定
void CSMain(uint3 id : SV_DispatchThreadID)
{
if (id.x >= inputVertices.Length) return;
// 元の頂点を取得
float3 vertex = inputVertices[id.x];
// 回転行列を計算
float4x4 rotationMatrix = GetRotationMatrixY(time);
// スケール行列を計算
float4x4 scaleMatrix = GetScaleMatrix(scale);
// スケールと回転を適用
float4 transformedVertex = mul(rotationMatrix, float4(vertex, 1.0));
transformedVertex = mul(scaleMatrix, transformedVertex);
// 結果を出力バッファに保存
outputVertices[id.x] = transformedVertex.xyz;
}
スケーリング行列を使用することで非常にシンプルな処理になっています。
〇C#側の処理
using UnityEngine;
public class ScaleMesh : MonoBehaviour
{
public ComputeShader computeShader; // コンピュートシェーダー
private Mesh mesh;
private ComputeBuffer inputBuffer;
private ComputeBuffer outputBuffer;
private Vector3[] vertices;
private int kernel;
void Start()
{
// メッシュの取得
mesh = GetComponent<MeshFilter>().mesh;
vertices = mesh.vertices;
// コンピュートバッファの作成
inputBuffer = new ComputeBuffer(vertices.Length, sizeof(float) * 3);
outputBuffer = new ComputeBuffer(vertices.Length, sizeof(float) * 3);
// 元の頂点データをバッファにセット
inputBuffer.SetData(vertices);
// カーネルを取得
kernel = computeShader.FindKernel("CSMain");
computeShader.SetBuffer(kernel, "inputVertices", inputBuffer);
computeShader.SetBuffer(kernel, "outputVertices", outputBuffer);
}
void Update()
{
// 時間を送る
computeShader.SetFloat("time", Time.time);
// スケールを送る
float scale = Mathf.PingPong(Time.time, 2.0f) + 0.5f; // 0.5~2.5の範囲でスケール変化
computeShader.SetFloat("scale", scale);
// ディスパッチを実行
computeShader.Dispatch(kernel, Mathf.CeilToInt(vertices.Length / 256.0f), 1, 1);
// 結果を取得してメッシュに反映
Vector3[] outputVertices = new Vector3[vertices.Length];
outputBuffer.GetData(outputVertices);
mesh.vertices = outputVertices;
mesh.RecalculateNormals();
}
void OnDestroy()
{
// バッファの解放
inputBuffer.Release();
outputBuffer.Release();
}
}
C#側の処理はComputeShaderのfloat型変数Scaleに値を送る処理を加えたのみです。
これによってスケーリングと回転が実装できました。

本日は以上です。