Search Unity

RenderTexture 3D to Texture3D

Discussion in 'General Graphics' started by Cr4fter, Jul 9, 2020.

  1. Cr4fter

    Cr4fter

    Joined:
    Mar 2, 2017
    Posts:
    1
    Is it possible to Convert a Rendertexture with depth to a Texture3D? or Store the Rendertexture as a Texture3D.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    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
    .
     
    Bovine and Nordjk like this.
  3. unity_LKgpBqmE7KPjcQ

    unity_LKgpBqmE7KPjcQ

    Joined:
    Dec 8, 2020
    Posts:
    1
    This worked for me.
     
    blenderfan1 likes this.
  4. JollyTheory

    JollyTheory

    Joined:
    Dec 30, 2018
    Posts:
    156
    Fastest way for even large (multiple GB) textures:
    Code (CSharp):
    1. void SaveRT3DToTexture3DAsset(RenderTexture rt3D, string pathWithoutAssetsAndExtension)
    2. {
    3.     int width = rt3D.width, height = rt3D.height, depth = rt3D.volumeDepth;
    4.     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)
    5.     AsyncGPUReadback.RequestIntoNativeArray(ref a, rt3D, 0, (_) =>
    6.     {
    7.         Texture3D output = new Texture3D(width, height, depth, rt3D.graphicsFormat, TextureCreationFlags.None);
    8.         output.SetPixelData(a, 0);
    9.         output.Apply(updateMipmaps: false, makeNoLongerReadable: true);
    10.         AssetDatabase.CreateAsset(output, $"Assets/{pathWithoutAssetsAndExtension}.asset");
    11.         AssetDatabase.SaveAssetIfDirty(output);
    12.         a.Dispose();
    13.         rt3D.Release();
    14.     });
    15. }
     
    axiwam likes this.