はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Unity】ComputeShaderでグレースケールをしてみた【Q2】

グレースケールとは

グレースケールとは色の濃淡の明暗を分ける技法のことです。

それを実現するには色の情報を以下の計算式に代入し、白黒のグラデーションで表現させます。

Y = 0.2126 R + 0.7152 G + 0.0722 B

とりあえずこの式にいれとけばよいので、すごい簡単ですよね。

コード

ComputeShaderのコードはこんな感じ。

#pragma kernel GrayScale

RWTexture2D<float4> Result;
Texture2D<float4> Texture;

[numthreads(8,8,1)]
void GrayScale (uint3 id : SV_DispatchThreadID)
{
    float gray = 0.2126 * Texture[id.xy].x + 0.7152 * Texture[id.xy].y + 0.0722 * Texture[id.xy].z;

    Result[id.xy] = float4(gray, gray, gray, 1);
}


UnityのCPU側のコードはこんな感じ。

using UnityEngine;
using UnityEngine.UI;

public class GrayScale : MonoBehaviour
{
    [SerializeField] private ComputeShader _computeShader;
    [SerializeField] private Texture2D _tex;
    [SerializeField] private RawImage _renderer;
    private RenderTexture _result;

    private void Start()
    {
        if(!SystemInfo.supportsComputeShaders)
        {
            Debug.LogError("Comppute Shader is not support.");
            return;
        }

        // RenderTextueの初期化
        _result = new RenderTexture(_tex.width, _tex.height, 0, RenderTextureFormat.ARGB32);
        _result.enableRandomWrite = true;
        _result.Create();

        // GreayScaleのカーネルインデックス(0)を取得
        var kernelIndex = _computeShader.FindKernel("GrayScale");

        // 一つのグループの中に何個のスレッドがあるか
        ThreadSize threadSize = new ThreadSize();
        _computeShader.GetKernelThreadGroupSizes(kernelIndex, out threadSize.x, out threadSize.y, out threadSize.z);

        // GPUにデータをコピーする
        _computeShader.SetTexture(kernelIndex, "Texture", _tex);
        _computeShader.SetTexture(kernelIndex, "Result", _result);

        // GPUの処理を実行する
        _computeShader.Dispatch(kernelIndex, _tex.width / (int)threadSize.x, _tex.height / (int)threadSize.y, (int)threadSize.z);

        // テクスチャを適応する
        _renderer.texture = _result;

    }

    private void OnDestroy()
    {
        _result = null;
    }
}

struct ThreadSize
{
    public uint x;
    public uint y;
    public uint z;

    public ThreadSize(uint x, uint y, uint z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

さいごに

ComputeShaderも含めてShader全般になんですが、VisualStudioがメモ帳同然になってしまうのはどうすればよいのでしょうか。

一応拡張機能もあるみたいなのですが、よく分かっていません・・・。

もう少し調べてみます。