Is it possible to Convert a Rendertexture with depth to a Texture3D? or Store the Rendertexture as a Texture3D.
It should be possible, but it’ll take a bit of extra work.
Right now there’s no way to read back a specific layer of a 3D render texture to the CPU. I’ve not tried, but I suspect if you tried to use ReadPixels
on a render texture with volume depth, you’ll always get the top slice. So instead you’ll need to create a 2D render texture with the same width, height and format as the 3D one and use Graphics.CopyTexture()
to copy a single layer at a time out. You can then use tex.ReadPixels()
to read that 2D render texture into a Texture2D
. You can then use GetPixels
/SetPixels
or CopyTexture
again to copy each slice from a Texture2D
into a Texture3D
.
Also as an aside, you said “a render texture with depth”. A render texture with depth isn’t a 3D render texture, it’s a render texture with a separate 2D depth buffer. To make a 3D render texture you need to create a render texture using a RenderTextureDescriptor with a TextureDimension.tex3D
dimension
and volumeDepth
.
This worked for me.
Fastest way for even large (multiple GB) textures:
void SaveRT3DToTexture3DAsset(RenderTexture rt3D, string pathWithoutAssetsAndExtension)
{
int width = rt3D.width, height = rt3D.height, depth = rt3D.volumeDepth;
var a = new NativeArray<byte>(width * height * depth, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); //change if format is not 8 bits (i was using R8_UNorm) (create a struct with 4 bytes etc)
AsyncGPUReadback.RequestIntoNativeArray(ref a, rt3D, 0, (_) =>
{
Texture3D output = new Texture3D(width, height, depth, rt3D.graphicsFormat, TextureCreationFlags.None);
output.SetPixelData(a, 0);
output.Apply(updateMipmaps: false, makeNoLongerReadable: true);
AssetDatabase.CreateAsset(output, $"Assets/{pathWithoutAssetsAndExtension}.asset");
AssetDatabase.SaveAssetIfDirty(output);
a.Dispose();
rt3D.Release();
});
}