Warning: Trying to access array offset on value of type bool in /home/empty/karanokan.info/public_html/wp-content/themes/lionblog/single.php on line 12

Warning: Trying to access array offset on value of type bool in /home/empty/karanokan.info/public_html/wp-content/themes/lionblog/single.php on line 13

Warning: Trying to access array offset on value of type bool in /home/empty/karanokan.info/public_html/wp-content/themes/lionblog/single.php on line 14
Scriptによるレンダーテクスチャへの数値書き込みについて │ 空の缶詰

Scriptによるレンダーテクスチャへの数値書き込みについて

NO IMAGE

 以前に投稿した波動方程式を用いた波紋の作成という記事内のScriptにおいて、SetPixelによりR=0.5、G=0.5のレンダーテクスチャを作成しました。ただ、少し気になることがあり調べてみました。

問題点

 GetPixelによって レンダーテクスチャの色を調べたところ0.50196・・・という数値が出てきました。そこで、Unityのドキュメントを見てみると”この関数の機能はARGB32、RGB32、Alpha8のテクスチャフォーマットのみに対応しています。”と記載されていました。つまり、SetPixel(0, 0, new Color(0.5f, 0.5f, 0.5f, 1))は8ビット(0~255)の内で一番近い数値(128/255=0.50196・・・ )へ自動的に変換されているようです。確認のために以下のScriptとShaderを作成し、実行してみました。

script

 作成したScriptは以下の通りです。レンダーテクスチャへSetPixelを用いてColor(0.5f, 0.5f, 0.5f, 1)を書き込んだのちに、レンダーテクスチャの色をDebug.Logで出力しています。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GenerateGrayTexture : MonoBehaviour
{
    public Material mat_gray_tex;

    private RenderTexture rTex;
    private int TextureSize = 256;

    // Start is called before the first frame update
    void Start()
    {
        rTex = new RenderTexture(TextureSize, TextureSize, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Default);

        Texture2D texBuf = new Texture2D(1, 1);
        texBuf.SetPixel(0, 0, new Color(0.5f, 0.5f, 0.5f, 1));
        texBuf.Apply();
        Graphics.Blit(texBuf, rTex);

        Texture2D tex = new Texture2D(rTex.width, rTex.height, TextureFormat.RGBAFloat, false);
        RenderTexture.active = rTex;
        tex.ReadPixels(new Rect(0, 0, rTex.width, rTex.height), 0, 0);
        tex.Apply();
        Debug.Log(tex.GetPixel(0, 0).ToString("f6"));
    }
}

実行結果

 上記Scriptの実行結果は以下の通りです。

0.501961となり、128/255がレンダーテクスチャに書き込まれていることが分かります。

解決策

 テクスチャへ目的の数値を書き込めるようShaderの作成及びScriptの変更を行いました。

Shader

 作成したShaderは以下の通りです。RGBA=(0.5,0.5,0.5,1.0)を出力するだけのShaderです。

Shader "Unlit/GenerateGrayTexture"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float4 col;
				col.rgb = 0.5;
				col.a = 1.0;
                return col;
            }
            ENDCG
        }
    }
}

Scriptの変更及び結果

 テクスチャの作成部分を変更し実行してみました。mat_gray_texは上記Shaderを割り当てたMaterialです。

Texture2D texBuf = new Texture2D(1, 1);
texBuf.SetPixel(0, 0, new Color(1.0f, 1.0f, 1.0f, 1));
texBuf.Apply();
Graphics.Blit(texBuf, rTex, mat_gray_tex);

結果は以下の通りです。

0.5が書き込まれていることが分かります。また、以下のように変更しても

RenderTexture buf = RenderTexture.GetTemporary(rTex.width, rTex.height, 0, RenderTextureFormat.ARGBFloat);
Graphics.Blit(rTex, buf, mat_gray_tex);
Graphics.Blit(buf, rTex);
RenderTexture.ReleaseTemporary(buf);

同様の結果となり、目的の数値をレンダーテクスチャへ書き込むことができました。

参考サイト

Unity|Document:スクリプティング API(Texture2D.SetPixels)

ftvlog:[Unity] RenderTextureからピクセル色を取得する