I have this script used for generating the area around 0,0,0 as a Texture3D volume.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class LBTraceArea : MonoBehaviour
{
public Texture3D Volume;
public float CubeScale;
public int CubeQuality;
public string SaveAs;
//pre-define texel size so it can be used among all functions
float texelSize = 1f;
// Start is called before the first frame update
void Start()
{
Debug.Log(Volume.mipmapCount);
//define the size of 1 3d texel/volumetric cube pixel/voxel
texelSize = CubeScale / CubeQuality;
VoxelizeArea();
AssetDatabase.CreateAsset(Volume, "Assets/" + SaveAs + ".asset");
Debug.Log(Volume.mipmapCount);
}
// Update is called once per frame
void Update()
{
}
//function to create 3D texture AKA voxel image with scene objects.
void VoxelizeArea(){
//Setup a 3d Texture
//Format
TextureFormat form = TextureFormat.RGBA32;
TextureWrapMode wrap = TextureWrapMode.Clamp;
//Defining the Volume
Volume = new Texture3D(CubeQuality, CubeQuality, CubeQuality, form, false);
Volume.wrapMode = wrap;
Volume.filterMode = FilterMode.Trilinear;
//Create a volumetric color array.
Color[] color = new Color[CubeQuality * CubeQuality * CubeQuality];
//Loop to actually create the color volume
//Define how offset the position of the object is from the center of the Volume.
//object Offset
Vector3 oOff = new Vector3(
transform.position.x + (CubeScale * -0.5f),
transform.position.x + (CubeScale * -0.5f),
transform.position.x + (CubeScale * -0.5f)
);
//define "Real Tick"/rt or how many loops total of all 3 for loops
int rt = 0;
//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)
for (int tx = 0; tx < CubeQuality; tx++){
for (int ty = 0; ty < CubeQuality; ty++){
for (int tz = 0; tz < CubeQuality; tz++){
//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.
//Color at Real Tick AKA rt would define the exact pixel at the exact position.
//so Color[rt] would be Color at the pixel
//color[rt] = new Color(tx, 1f, tz, ty);
color[rt] = GetColorAtPosition(new Vector3(tz * texelSize, ty * texelSize, tx * texelSize) + oOff);
rt++;
}
}
}
//Put the colors on the 3d bitmap volume and apply the changes so it gets resent to the GPU.
Volume.SetPixels(color);
Volume.Apply();
}
//function to get an objects surface color at an exact Vector3 location
void GetColorAt(Vector3 cpos){
}
Color GetColorAtPosition(Vector3 position) {
Vector4 grabber = Vector4.zero;
grabber += GetColorAtPosAndRot(position, Vector3.up);
grabber += GetColorAtPosAndRot(position, -Vector3.up);
grabber += GetColorAtPosAndRot(position, Vector3.right);
grabber += GetColorAtPosAndRot(position, -Vector3.right);
grabber += GetColorAtPosAndRot(position, Vector3.forward);
grabber += GetColorAtPosAndRot(position, -Vector3.forward);
return grabber;
}
Vector4 GetColorAtPosAndRot(Vector3 position, Vector3 normal){
RaycastHit hit;
if (Physics.Raycast(position, normal, out hit, texelSize)){
Renderer renderer = hit.collider.GetComponent<Renderer>();
if (renderer != null){
Texture2D texture = renderer.material.mainTexture as Texture2D;
if (texture){
Vector2 pixelUV = hit.textureCoord;
pixelUV.x *= texture.width;
pixelUV.y *= texture.height;
return texture.GetPixel((int)pixelUV.x, (int)pixelUV.y);
} else {
return renderer.material.color;
}
}
return new Vector4(1f,1f,1f,1f);
}
return new Vector4(0f,0f,0f,0f);
}
}
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:
Color = float4(0, 0, 0, 0);
Distance = 0;
float MarchSize = 1 / VolumeQuality;
float3 pos = float3(0,0,0);
//Define t and start 4 steps out
//4 because honestly it's the best I could do
float t = MarchSize * 4;
while (t < 1) {
if (Color.a < 1) {
pos = Position + (Normal * t);
Color += SAMPLE_TEXTURE3D_LOD(Volume, Sampler, pos, Roughness * t);
Distance = t;
}
//advance tick size
t += MarchSize;
}
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):

