I just found the reason for this weird behaviour!
Explanation and Workaround 1
Project Settings > Quality > Texture Quality
This setting was Half Res
. Setting it to Full Res
fixes the issue. But this way you cannot reduce the texture resolution for better performance settings!
**Deeper understanding and Workaround 2 **
What’s weird: The quality setting still does not explain the difference between editor and build. There is also a variable that allows you to check for this seeting and it is 1 in both cases for me:
QualitySettings.masterTextureLimit
This value is 0 for Full Resolution
, 1 for Half Resolution
etc. In other words: it defines the smallest mip level that is used when rendering textures and it seems to be used by CopyTexture
internaly. We can use that to “fix” the issue:
// The scale factor is 2^QualitySettings.masterTextureLimit:
var scaleFactor = 1 << QualitySettings.masterTextureLimit;
var width = _tex.width / scaleFactor;
var height = _tex.width / scaleFactor;
// Create a texture with the reduced size and no mipmap
var tex = new Texture2D(width, height, _tex.graphicsFormat, 0, TextureCreationFlags.None);
// Temporarily set the texture Limit to 0 so taht CopyTexture behaves properly
var texLimit = QualitySettings.masterTextureLimit;
QualitySettings.masterTextureLimit = 0;
Graphics.CopyTexture(_tex, 0, texLimit, tex, 0, 0);
QualitySettings.masterTextureLimit = texLimit;
Compute Shader
The original reason I came accross this was that I got the exact same weird behavior using a very simple compute shader. I was able to fix it using that same workaround. Here is a working version that might help you too:
/// C#
CubemapRenderTexture = new RenderTexture(_tex.width, _tex.height, 0, _tex.graphicsFormat, 0);
{
CubemapRenderTexture.dimension = TextureDimension.Tex2D;
CubemapRenderTexture.enableRandomWrite = true;
CubemapRenderTexture.useMipMap = false;
CubemapRenderTexture.Create();
}
int kernelIndex = computeShader.FindKernel("CSMain");
computeShader.SetTexture(kernelIndex, "INPUT", _tex);
computeShader.SetTexture(kernelIndex, "OUTPUT", CubemapRenderTexture);
// Run the kernel with textureLimit==0
var texLimit = QualitySettings.masterTextureLimit;
QualitySettings.masterTextureLimit = 0;
computeShader.Dispatch(kernelIndex, _tex.width, _tex.height, 1);
QualitySettings.masterTextureLimit = texLimit;
/// .compute file
#pragma kernel CSMain
// Inputs
Texture2D<float4> INPUT;
RWTexture2D<float4> OUTPUT;
[numthreads(1,1,1)]
void CSMain(uint3 id : SV_DispatchThreadID)
{
OUTPUT[id.xy] = INPUT[id.xy]; // Same as INPUT.mip[0][id.xy] => full resolution texture
}
Wrap up
To me this looks like a bug. However it is really weird that I cannot find much about this online though I only do very basic stuff and this should happen to a lot of people out there. So maybe I missed something essential here?