Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Let us know your feedback about the Global Illumination changes in the 2023.2 beta.
    Dismiss Notice
  3. Dismiss Notice

Question How do I generate mipmaps for a Texture3D?

Discussion in 'Global Illumination' started by MacksNotCool, Aug 20, 2023.

  1. MacksNotCool

    MacksNotCool

    Joined:
    Apr 28, 2020
    Posts:
    7
    I have this script used for generating the area around 0,0,0 as a Texture3D volume.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5.  
    6.  
    7.  
    8. public class LBTraceArea : MonoBehaviour
    9. {
    10.     public Texture3D Volume;
    11.     public float CubeScale;
    12.     public int CubeQuality;
    13.     public string SaveAs;
    14.  
    15.     //pre-define texel size so it can be used among all functions
    16.     float texelSize = 1f;
    17.  
    18.     // Start is called before the first frame update
    19.     void Start()
    20.     {
    21.         Debug.Log(Volume.mipmapCount);
    22.         //define the size of 1 3d texel/volumetric cube pixel/voxel
    23.         texelSize = CubeScale / CubeQuality;
    24.         VoxelizeArea();
    25.         AssetDatabase.CreateAsset(Volume, "Assets/" + SaveAs + ".asset");
    26.         Debug.Log(Volume.mipmapCount);
    27.     }
    28.  
    29.     // Update is called once per frame
    30.     void Update()
    31.     {
    32.      
    33.     }
    34.  
    35.     //function to create 3D texture AKA voxel image with scene objects.
    36.     void VoxelizeArea(){
    37.  
    38.  
    39.         //Setup a 3d Texture
    40.      
    41.         //Format
    42.         TextureFormat form = TextureFormat.RGBA32;
    43.         TextureWrapMode wrap = TextureWrapMode.Clamp;
    44.      
    45.         //Defining the Volume
    46.         Volume = new Texture3D(CubeQuality, CubeQuality, CubeQuality, form, false);
    47.         Volume.wrapMode = wrap;
    48.         Volume.filterMode = FilterMode.Trilinear;
    49.  
    50.         //Create a volumetric color array.
    51.         Color[] color = new Color[CubeQuality * CubeQuality * CubeQuality];
    52.  
    53.  
    54.         //Loop to actually create the color volume
    55.      
    56.         //Define how offset the position of the object is from the center of the Volume.
    57.         //object Offset
    58.         Vector3 oOff = new Vector3(
    59.             transform.position.x + (CubeScale * -0.5f),
    60.             transform.position.x + (CubeScale * -0.5f),
    61.             transform.position.x + (CubeScale * -0.5f)
    62.         );
    63.  
    64.         //define "Real Tick"/rt or how many loops total of all 3 for loops
    65.         int rt = 0;
    66.  
    67.         //tx ty and tz is a pun because they are short for texel+(the axis, for example x) and also short for tick+(the axis, for example y)
    68.         for (int tx = 0; tx < CubeQuality; tx++){
    69.             for (int ty = 0; ty < CubeQuality; ty++){
    70.                 for (int tz = 0; tz < CubeQuality; tz++){
    71.                     //tick area, ya have access to tx, ty, and tz all in here so you shouldn't need to be outsize of this when calculating coor math and stuff.
    72.  
    73.                     //Color at Real Tick AKA rt would define the exact pixel at the exact position.
    74.                     //so Color[rt] would be Color at the pixel
    75.                  
    76.                     //color[rt] = new Color(tx, 1f, tz, ty);
    77.                     color[rt] = GetColorAtPosition(new Vector3(tz * texelSize, ty * texelSize, tx * texelSize) + oOff);
    78.                  
    79.                     rt++;
    80.                 }
    81.             }
    82.         }
    83.  
    84.         //Put the colors on the 3d bitmap volume and apply the changes so it gets resent to the GPU.
    85.         Volume.SetPixels(color);
    86.         Volume.Apply();
    87.  
    88.     }
    89.  
    90.     //function to get an objects surface color at an exact Vector3 location
    91.     void GetColorAt(Vector3 cpos){
    92.  
    93.     }
    94.  
    95.     Color GetColorAtPosition(Vector3 position) {
    96.         Vector4 grabber = Vector4.zero;
    97.         grabber += GetColorAtPosAndRot(position, Vector3.up);
    98.         grabber += GetColorAtPosAndRot(position, -Vector3.up);
    99.         grabber += GetColorAtPosAndRot(position, Vector3.right);
    100.         grabber += GetColorAtPosAndRot(position, -Vector3.right);
    101.         grabber += GetColorAtPosAndRot(position, Vector3.forward);
    102.         grabber += GetColorAtPosAndRot(position, -Vector3.forward);
    103.         return grabber;
    104.     }
    105.  
    106.     Vector4 GetColorAtPosAndRot(Vector3 position, Vector3 normal){
    107.         RaycastHit hit;
    108.         if (Physics.Raycast(position, normal, out hit, texelSize)){
    109.             Renderer renderer = hit.collider.GetComponent<Renderer>();
    110.          
    111.             if (renderer != null){
    112.                 Texture2D texture = renderer.material.mainTexture as Texture2D;
    113.              
    114.                 if (texture){
    115.                     Vector2 pixelUV = hit.textureCoord;
    116.                     pixelUV.x *= texture.width;
    117.                     pixelUV.y *= texture.height;
    118.  
    119.                     return texture.GetPixel((int)pixelUV.x, (int)pixelUV.y);
    120.                 } else {
    121.                     return renderer.material.color;
    122.                 }
    123.             }
    124.             return new Vector4(1f,1f,1f,1f);
    125.         }
    126.      
    127.         return new Vector4(0f,0f,0f,0f);
    128.     }
    129. }
    130.  
    When using this I have noticed the LOD function of a Sample Texture3D node does not work (URP 16). I have deducted that the reason is because there are NO MIPMAPS on my generated Texture3D.
    I have been trying to use this 3D Texture volume for smooth noise-free Global illumination using this raymarching script:
    Code (CSharp):
    1. Color = float4(0, 0, 0, 0);
    2. Distance = 0;
    3.  
    4. float MarchSize = 1 / VolumeQuality;
    5.  
    6. float3 pos = float3(0,0,0);
    7.  
    8. //Define t and start 4 steps out
    9. //4 because honestly it's the best I could do
    10. float t = MarchSize * 4;
    11. while (t < 1) {
    12.  
    13.  
    14.  
    15.     if (Color.a < 1) {
    16.         pos = Position + (Normal * t);
    17.         Color += SAMPLE_TEXTURE3D_LOD(Volume, Sampler, pos, Roughness * t);
    18.         Distance = t;
    19.     }
    20.  
    21.     //advance tick size
    22.     t += MarchSize;      
    23. }
    24. Color.a = min(Color.a, 1.0);
    When using this, my output looks like this:

    When my output should look like this image(except without basically any of the noise in this image, this is stochastically sampled because I couldn't get LOD to work from the lack of Mipmaps):
     
  2. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    10,977
    Try setting the last parameter here to true as opposed to false.
     
  3. MacksNotCool

    MacksNotCool

    Joined:
    Apr 28, 2020
    Posts:
    7
    Thank you so much! Where did you find that? I couldn't even find that on the docs website.
     
  4. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    10,977
  5. MacksNotCool

    MacksNotCool

    Joined:
    Apr 28, 2020
    Posts:
    7
    Thank you!