Graphics.Blit to copy material to texture gives incorrect results

749 Views Asked by At

I have a material using a shader I wrote. I am using HDRP. This shader samples a texture, does some manipulation to the texture, and outputs the result.

I want to save the the result of this manipulation as a texture asset.

    public Material mat;
    public int width = 2048;
    public int height = 1024;
    public Texture2D tex;

    public Texture2D SaveMaterialToTexture(Material mat, int width, int height)
    {
        Texture2D tex = new Texture2D(width, height);
        RenderTexture rt = new RenderTexture(width, height, 0);
        RenderTexture.active = rt;
        Graphics.Blit(null, rt, mat, 0);
        tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
        tex.Apply();

        return tex;
    }

    public void SaveTexToDisk()
    {
        tex = SaveMaterialToTexture(mat, width, height);
        byte[] bytes = tex.EncodeToPNG();
        System.IO.File.WriteAllBytes(Application.dataPath + "/Tex.png", bytes);
    }

The appearance of the material and the outputted texture are not the same.

The sizes of the texture I am manipulating in my shader, and the size of the texture I am trying to save are set to the same.

I have made sure I am using an unlit shader, and not some sort of surface shader.

I have tried adding this as a tag to my SubShader "RenderTexture"="True"

I have tried using a pass like this Graphics.Blit(null, blitTarget, blitMaterial, 0);

I have tried with a different very simple unlit shader, outlined below, and the result seems to be correct.

fixed4 frag (v2f i) : SV_Target
{
   float4 col = tex2D(_MainTex, i.uv);
   return float4(col.r + i.uv.x, col.g + i.uv.y, col.b, 1.0);
}
1

There are 1 best solutions below

1
Program232323 On

Issue was using TexelSize in the shader it seems. Start manually feeding the TexelSize in my self, without using unity's built in shader property, and everything started to work.