本日はShader枠です。
昨日はコンピュートシェーダーを使用して、Unityの任意のオブジェクトの情報を毎フレームコンピュートシェーダー内で使用することができました。
今回は任意のColor型の情報をComputeShaderに渡していきます。
〇色の情報をコンピュートシェーダーで使用する
[SerializeField] private Color _paintingColor;//追加
として定義しました。
using UnityEngine;
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class VertexColorCompute : MonoBehaviour
{
public ComputeShader vertexColorComputeShader;
public GameObject targetObject; // ターゲットオブジェクト
private Mesh mesh;
private Vector3[] vertices;
private int[] triangles;
private Color[] colors;
[SerializeField] private Color _paintingColor;//追加
private ComputeBuffer vertexBuffer;
private ComputeBuffer triangleBuffer;
private ComputeBuffer colorBuffer;
private ComputeBuffer targetBuffer; // ターゲットオブジェクトの位置を保持するバッファ
void Start()
{
// メッシュの取得
mesh = GetComponent<MeshFilter>().mesh;
vertices = mesh.vertices;
triangles = mesh.triangles;
colors = new Color[vertices.Length];
// 頂点バッファの作成
vertexBuffer = new ComputeBuffer(vertices.Length, sizeof(float) * 3);
vertexBuffer.SetData(vertices);
// インデックスバッファの作成
triangleBuffer = new ComputeBuffer(triangles.Length, sizeof(int));
triangleBuffer.SetData(triangles);
// カラーバッファの作成
colorBuffer = new ComputeBuffer(colors.Length, sizeof(float) * 4);
colorBuffer.SetData(colors);
// ターゲットオブジェクトの位置を保持するバッファの作成
targetBuffer = new ComputeBuffer(1, sizeof(float) * 3);
targetBuffer.SetData(new Vector3[] { targetObject.transform.position });
// メッシュに初期カラーを設定
mesh.colors = colors;
}
void Update()
{
// ターゲットオブジェクトの位置をターゲットバッファに更新
targetBuffer.SetData(new Vector3[] { targetObject.transform.position });
// コンピュートシェーダーのセットアップ
int kernelHandle = vertexColorComputeShader.FindKernel("CSMain");
// シェーダーにバッファをセット
vertexColorComputeShader.SetBuffer(kernelHandle, "vertexBuffer", vertexBuffer);
vertexColorComputeShader.SetBuffer(kernelHandle, "colorBuffer", colorBuffer);
vertexColorComputeShader.SetBuffer(kernelHandle, "targetBuffer", targetBuffer);
// ワールド変換行列をセット(必要に応じて)
vertexColorComputeShader.SetMatrix("localToWorldMatrix", transform.localToWorldMatrix);
// シェーダーをディスパッチ
int threadGroups = Mathf.CeilToInt(vertices.Length / 256.0f);
vertexColorComputeShader.Dispatch(kernelHandle, threadGroups, 1, 1);
// カラーバッファからデータを取得
colorBuffer.GetData(colors);
// メッシュにカラーを適用
mesh.colors = colors;
}
void OnDestroy()
{
// バッファの解放
if (vertexBuffer != null)
vertexBuffer.Release();
if (triangleBuffer != null)
triangleBuffer.Release();
if (colorBuffer != null)
colorBuffer.Release();
if (targetBuffer != null)
targetBuffer.Release();
}
}
このカラー情報は毎フレームコンピュートシェーダー側に渡す必要があるため、Update関数で値を渡します。
これはComputeShader.SetVectorで値を渡します。
この使い方はマテリアルパラメータに参照する際のShader.SetFloatなどと同じです。
void Update()
{
・・・
// シェーダーにペイントカラーを設定
vertexColorComputeShader.SetVector("_paintingColor", _paintingColor);
・・・
mesh.colors = colors;
}
〇コンピュートシェーダー側の処理
コンピュートシェーダーのHLSL側で実装することは以下の二点です。
・定数バッファとして _paintingColor を宣言。
・距離判定後に _paintingColor を使用。
#pragma kernel CSMain
// バッファの宣言
StructuredBuffer<float3> vertexBuffer;
RWStructuredBuffer<float4> colorBuffer;
StructuredBuffer<float3> targetBuffer;
// ワールド変換行列
float4x4 localToWorldMatrix;
// ペイントカラー
float4 _paintingColor;
[numthreads(256, 1, 1)]
void CSMain(uint3 id : SV_DispatchThreadID)
{
uint index = id.x;
// バッファの範囲をチェック
if (index >= vertexBuffer.Length)
return;
// 頂点位置を取得
float3 vertexPos = vertexBuffer[index];
// ターゲット位置をバッファから取得
float3 targetPos = targetBuffer[0];
// 頂点とターゲットの距離を計算
float distance = length(vertexPos - targetPos);
// ターゲットに近い頂点にカラーを設定
if (distance < 1.0) // 任意の距離閾値
{
// ターゲットに近い場合、ペイントカラーを使用
colorBuffer[index] = _paintingColor;
}
else
{
// それ以外は青色
colorBuffer[index] = float4(0.0, 0.0, 1.0, 1.0);
}
}
これによって任意の色をColor型のパラメータとしてコンピュートシェーダーに渡すことができるようになりました。

本日は以上です。