본문 바로가기

유니티(Unity)

Unity 텍스처 압축 시 주의 할 점.

런타임 최적화를 위해 머터리얼에 들어있는 텍스처를 압축 하는 중에 문제 발생.
머터리얼에 들어 있는 텍스처를 수정하기 위해서는 Read/Write가 true가 되어야하는데 이것은 에디터에서만 설정할 수 있다. 텍스처를 복제하여 새롭게 생성해주면 수정이 가능하기 때문에 기존의 텍스처를 복제하려고 했다.
 
하지만 문제가 많이 발생했다.
1. 에디터에서는 잘 동작. 하지만 윈도우 빌드에서는 GetRawTextureData 부분에서 읽을 수 없다는 에러발생.(GetPixels도 마찬가지)

Texture2D tex = (Texture2D)mat.GetTexture(name);
byte[] data = tex.GetRawTextureData();
Texture2D compressTex = new Texture2D(tex.width, tex.height, tex.format, false);
compressTex.LoadRawTextureData(data);

바이트 배열로 가져오기도 힘듬.
 
2. 이 또한 에디터에서는 잘 동작함. 하지만 윈도우 빌드에서는 텍스처가 전부 회색으로 변함.

Texture2D compressTex = new Texture2D(tex.width, tex.height, tex.format, false);
Graphics.CopyTexture(tex, compressTex);

Graphics.CopyTexture 는 기본적으로 GPU에서 동작한다.
공식문서에서는 텍스처의 isReadable이 true로 설정되어 있어야 CPU에 있는 데이터에 접근 가능하다고 한다.
그런데 이것은 읽기 전용이므로 코드 상에서 수정할 수 없고, 에디터에서 설정해야하는 것 같다.
Texture2D compressTex = new Texture2D(tex.width, tex.height, tex.format, false); 는 cpu에 올라가 있으므로, 이것도 사용 불가능.
 
3. 해결방법. 에디터에서도 잘 동작하고 윈도우 빌드에서도 잘 동작함.

public Texture2D DuplicateTexture(Texture source)
{
    RenderTexture renderTex = RenderTexture.GetTemporary(source.width,source.height);
    Graphics.Blit(source, renderTex);
    RenderTexture.active = renderTex;
    Texture2D readableTexture = new Texture2D(source.width, source.height);
    readableTexture.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
    readableTexture.Apply();

    RenderTexture.ReleaseTemporary(renderTex);
    MonoBehaviour.Destroy(source);

    return readableTexture;
}

RenderTexture을 이용하면 GPU 측에서 작업이 가능하다. 위 코드는 GPU에서 텍스처를 복제하고 ReadPixels를 통해 CPU 작업으로 넘겨주는 원리이다.
 
원인을 몰라서 3일동안 고생했는데, 앞으로 텍스처에 접근할 일이 있으면 RenderTexture 를 사용해야겠다.