I am writing a very simple compute shader that copies the color data from a texture2D and stores it in a render texture. The issue I’m having is that the output Render Texture is much darker than the input texture2D.
I’ve put a copy of the shader and implementation below.
The image I’m using for this test is a 512x512 cloud render .png from photoshop with 32 bit color depth. The standard image format (RGB Compressed DXT1) and RGBA 32 bit cause the problem.
I’ve found that if untick sRGB (Color Texture) or select RGB 16 bit or RGBA Half as the image format the image lightens in normal use, but looks correct after being processed by the compute shader. So I’m pretty convinced that my issue is the color format of the texture2D, the render texture or both.
Playing with the render texture format can also resolve the problem. The problem exists with ARGB32 and Default (When the textures import format is RGBA 32 bit, so it looks correct). If I set the RenderTexture format to ARGB Half, ARGB Float or Default HDR it works.
I would have expected the 32 bit Color depth import option to match the 32 bit depth render texture option. I have a solution that will work for this case but I would love to understand the problem so I can get more predictable results in the future.
I’ve been reading through the documentation on Color formats in Unity here
and here
But can’t work out why I need to use the formats I do to get my expected result. If anyone knows whats going wrong or can point me at a better resource to understand the issue it would be much appreciated.
This is the shader I’m using:
#pragma kernel CopyTexture
Texture2D<float4> original;
RWTexture2D<float4> output;
float w, h;
SamplerState _LinearClamp;
[numthreads(8,8,1)]
void CopyTexture (uint2 id : SV_DispatchThreadID)
{
float2 uv = float2(id.x/w, id.y/h);
float4 t = original.SampleLevel(_LinearClamp, uv, 0);
output[id] = t;
}
And a simplified version of my implementation:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CopyTextureTest : MonoBehaviour
{
public Texture2D original;
RenderTexture rtOutput;
public ComputeShader copyTextureShader;
int copyTextureKernelIndex;
MeshRenderer myMeshRenderer;
// Use this for initialization
void Start ()
{
rtOutput = new RenderTexture(original.width, original.height, 24);
rtOutput.enableRandomWrite = true;
rtOutput.Create();
myMeshRenderer = GetComponent<MeshRenderer>();
myMeshRenderer.material.mainTexture = rtOutput;
copyTextureKernelIndex = copyTextureShader.FindKernel("CopyTexture");
copyTextureShader.SetTexture(copyTextureKernelIndex, "original", original);
copyTextureShader.SetTexture(copyTextureKernelIndex, "output", rtOutput);
copyTextureShader.SetFloat("w", original.width);
copyTextureShader.SetFloat("h", original.width);
copyTextureShader.Dispatch(copyTextureKernelIndex, rtOutput.width / 8, rtOutput.height / 8, 1);
}
}