読者です 読者をやめる 読者になる 読者になる

のしメモ アプリ開発ブログ

Unityアプリとかロボットとか作ってるときに困ったこととかメモ

Textureをスクリプトから編集してみる

Unity

Unity Advent Calendar 15日目の記事です

処理の流れとしてはこんな感じのを作ります
現在のテクスチャ(元絵)を読み取り
→書き換え用テクスチャ作成
→テクスチャを反映

1. 元絵を編集できるように設定する

まずはスクリプトからテクスチャを編集、取得できる設定をしていきます
元の画像をインポートして[Texture Type]を[Advanced]に変更
[Read / Write Enabled]にチェックをいれる
これでスクリプトから編集、取得できるようになります。

2. Planeにテクスチャ貼ります

シェーダーはUI/Unlit/Transparentを指定します(後で透過使うので)

とりあえずGameビューがこんな感じに

3. 元絵から書き換え用テクスチャを生成して貼り付けるスクリプト

// 元絵のPixel情報取得
Texture2D mainTexture = (Texture2D) GetComponent<Renderer> ().material.mainTexture;
Color[] pixels = mainTexture.GetPixels();

// 書き換え用テクスチャ用配列の作成
Color[] change_pixels = new Color[pixels.Length];
for (int i = 0; i < pixels.Length; i++) {
        Color pixel = pixels[i];

        // 書き換え用テクスチャのピクセル色を指定
        Color change_pixel = new Color(1f, pixel.g, pixel.b, pixel.a);
        change_pixels.SetValue(change_pixel, i);
}

// 書き換え用テクスチャの生成
Texture2D change_texture = new Texture2D (mainTexture.width, mainTexture.height, TextureFormat.RGBA32, false);
change_texture.filterMode = FilterMode.Point;
change_texture.SetPixels (change_pixels);
change_texture.Apply();

// テクスチャを貼り替える
GetComponent<Renderer> ().material.mainTexture = change_texture;

これで実行するとこんな感じに赤みがかる

Color change_pixel = new Color(1f, pixel.g, pixel.b, pixel.a);

この部分で赤色の要素に1を指定しているので、赤くなっています。

4. 指定色を入れ替えてみる

pixelsを回しているところで、色のチェックをして分岐させたりしてみます
// 黒色の場合
if (pixel == Color.black) {
	// グレーに書き換え
	change_pixels.SetValue(Color.grey, i);
} else {
	// 書き換え用テクスチャのピクセル色を指定
	Color change_pixel = new Color(pixel.r, pixel.g, pixel.b, pixel.a);
	change_pixels.SetValue(change_pixel, i);
}

こんな感じ

透過もしてみる
// 青色が一定値を上回ったら
if (pixel.b >= 1) {
	// 透過させる
	change_pixels.SetValue(Color.clear, i);
} else {
	// 書き換え用テクスチャのピクセル色を指定
	Color change_pixel = new Color(pixel.r, pixel.g, pixel.b, pixel.a);
	change_pixels.SetValue(change_pixel, i);
}

これが(わかりやすいように量産しました)

こうなる

このテクスチャ機能を応用させて、アルファ値だけをみる画像と通常の透過されていない画像を合成して、任意の透過画像を生成することも可能です。

備考

GetPixelや、SetPixel等の画像処理は重い処理なので、ゲーム中ではシェーダー等でやったほうがスマートですね。
ただ、元画像から透過されていると便利なケースもあるので、手法の一つとしていいかなと思います。

Advent Calendarの16日目はRhodoniteさんです!