#14: Use RHalf/RFloat (not RGBA) texture format for data texture. Use half precision floating point format for TF textures.

This commit is contained in:
Matias Lavik 2020-02-26 18:29:44 +01:00
Родитель ebda446929
Коммит d012728c2e
8 изменённых файлов: 102 добавлений и 48 удалений

Просмотреть файл

@ -18,7 +18,8 @@ namespace UnityVolumeRendering
public TransferFunction()
{
texture = new Texture2D(TEXTURE_WIDTH, TEXTURE_HEIGHT, TextureFormat.RGBAFloat, false);
TextureFormat texformat = SystemInfo.SupportsTextureFormat(TextureFormat.RGBAHalf) ? TextureFormat.RGBAHalf : TextureFormat.RGBAFloat;
texture = new Texture2D(TEXTURE_WIDTH, TEXTURE_HEIGHT, texformat, false);
tfCols = new Color[TEXTURE_WIDTH * TEXTURE_HEIGHT];
}

Просмотреть файл

@ -24,7 +24,8 @@ namespace UnityVolumeRendering
public TransferFunction2D()
{
texture = new Texture2D(TEXTURE_WIDTH, TEXTURE_HEIGHT, TextureFormat.RGBAFloat, false);
TextureFormat texformat = SystemInfo.SupportsTextureFormat(TextureFormat.RGBAHalf) ? TextureFormat.RGBAHalf : TextureFormat.RGBAFloat;
texture = new Texture2D(TEXTURE_WIDTH, TEXTURE_HEIGHT, texformat, false);
}
public void AddBox(float x, float y, float width, float height, Color colour, float alpha)

Просмотреть файл

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9805df7fa7b5e1b4cbc7c9c9fb18d2d5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -10,16 +10,25 @@ namespace UnityVolumeRendering
private int minDataValue = int.MaxValue;
private int maxDataValue = int.MinValue;
private Texture3D texture = null;
private Texture3D dataTexture = null;
private Texture3D gradientTexture = null;
public Texture3D GetTexture()
public Texture3D GetDataTexture()
{
if (texture == null)
if (dataTexture == null)
{
texture = new Texture3D(dimX, dimY, dimZ, TextureFormat.RGBAFloat, false);
texture.wrapMode = TextureWrapMode.Clamp;
dataTexture = CreateTextureInternal();
}
return texture;
return dataTexture;
}
public Texture3D GetGradientTexture()
{
if (gradientTexture == null)
{
gradientTexture = CreateGradientTextureInternal();
}
return gradientTexture;
}
public int GetMinDataValue()
@ -48,5 +57,69 @@ namespace UnityVolumeRendering
maxDataValue = Math.Max(maxDataValue, val);
}
}
private Texture3D CreateTextureInternal()
{
TextureFormat texformat = SystemInfo.SupportsTextureFormat(TextureFormat.RHalf) ? TextureFormat.RHalf : TextureFormat.RFloat;
Texture3D texture = new Texture3D(dimX, dimY, dimZ, texformat, false);
texture.wrapMode = TextureWrapMode.Clamp;
int minValue = GetMinDataValue();
int maxValue = GetMaxDataValue();
int maxRange = maxValue - minValue;
Color[] cols = new Color[data.Length];
for (int x = 0; x < dimX; x++)
{
for (int y = 0; y < dimY; y++)
{
for (int z = 0; z < dimZ; z++)
{
int iData = x + y * dimX + z * (dimX * dimY);
cols[iData] = new Color((float)(data[iData] - minValue) / maxRange, 0.0f, 0.0f, 0.0f);
}
}
}
texture.SetPixels(cols);
texture.Apply();
return texture;
}
private Texture3D CreateGradientTextureInternal()
{
TextureFormat texformat = SystemInfo.SupportsTextureFormat(TextureFormat.RGBAHalf) ? TextureFormat.RGBAHalf : TextureFormat.RGBAFloat;
Texture3D texture = new Texture3D(dimX, dimY, dimZ, texformat, false);
texture.wrapMode = TextureWrapMode.Clamp;
int minValue = GetMinDataValue();
int maxValue = GetMaxDataValue();
int maxRange = maxValue - minValue;
Color[] cols = new Color[data.Length];
for (int x = 0; x < dimX; x++)
{
for (int y = 0; y < dimY; y++)
{
for (int z = 0; z < dimZ; z++)
{
int iData = x + y * dimX + z * (dimX * dimY);
int x1 = data[Math.Min(x + 1, dimX - 1) + y * dimX + z * (dimX * dimY)] - minValue;
int x2 = data[Math.Max(x - 1, 0) + y * dimX + z * (dimX * dimY)] - minValue;
int y1 = data[x + Math.Min(y + 1, dimY - 1) * dimX + z * (dimX * dimY)] - minValue;
int y2 = data[x + Math.Max(y - 1, 0) * dimX + z * (dimX * dimY)] - minValue;
int z1 = data[x + y * dimX + Math.Min(z + 1, dimZ - 1) * (dimX * dimY)] - minValue;
int z2 = data[x + y * dimX + Math.Max(z - 1, 0) * (dimX * dimY)] - minValue;
Vector3 grad = new Vector3((x2 - x1) / (float)maxRange, (y2 - y1) / (float)maxRange, (z2 - z1) / (float)maxRange);
cols[iData] = new Color(grad.x, grad.y, grad.z, (float)(data[iData] - minValue) / maxRange);
}
}
}
texture.SetPixels(cols);
texture.Apply();
return texture;
}
}
}

Просмотреть файл

@ -14,41 +14,6 @@ namespace UnityVolumeRendering
volObj.dataset = dataset;
int dimX = dataset.dimX;
int dimY = dataset.dimY;
int dimZ = dataset.dimZ;
int minValue = dataset.GetMinDataValue();
int maxValue = dataset.GetMaxDataValue();
int maxRange = maxValue - minValue;
Color[] cols = new Color[dataset.data.Length];
for (int x = 0; x < dataset.dimX; x++)
{
for (int y = 0; y < dataset.dimY; y++)
{
for (int z = 0; z < dataset.dimZ; z++)
{
int iData = x + y * dimX + z * (dimX * dimY);
int x1 = dataset.data[Math.Min(x + 1, dimX - 1) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)] - minValue;
int x2 = dataset.data[Math.Max(x - 1, 0) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)] - minValue;
int y1 = dataset.data[x + Math.Min(y + 1, dimY - 1) * dataset.dimX + z * (dataset.dimX * dataset.dimY)] - minValue;
int y2 = dataset.data[x + Math.Max(y - 1, 0) * dataset.dimX + z * (dataset.dimX * dataset.dimY)] - minValue;
int z1 = dataset.data[x + y * dataset.dimX + Math.Min(z + 1, dimZ - 1) * (dataset.dimX * dataset.dimY)] - minValue;
int z2 = dataset.data[x + y * dataset.dimX + Math.Max(z - 1, 0) * (dataset.dimX * dataset.dimY)] - minValue;
Vector3 grad = new Vector3((x2 - x1) / (float)maxRange, (y2 - y1) / (float)maxRange, (z2 - z1) / (float)maxRange);
cols[iData] = new Color(grad.x, grad.y, grad.z, (float)(dataset.data[iData] - minValue) / maxRange);
}
}
}
Texture3D tex = dataset.GetTexture();
tex.SetPixels(cols);
tex.Apply();
const int noiseDimX = 512;
const int noiseDimY = 512;
Texture2D noiseTexture = NoiseTextureGenerator.GenerateNoiseTexture(noiseDimX, noiseDimY);
@ -62,7 +27,8 @@ namespace UnityVolumeRendering
TransferFunction2D tf2D = TransferFunctionDatabase.CreateTransferFunction2D();
volObj.transferFunction2D = tf2D;
meshRenderer.sharedMaterial.SetTexture("_DataTex", tex);
meshRenderer.sharedMaterial.SetTexture("_DataTex", dataset.GetDataTexture());
meshRenderer.sharedMaterial.SetTexture("_GradientTex", dataset.GetGradientTexture());
meshRenderer.sharedMaterial.SetTexture("_NoiseTex", noiseTexture);
meshRenderer.sharedMaterial.SetTexture("_TFTex", tfTexture);

Просмотреть файл

@ -24,7 +24,7 @@ namespace UnityVolumeRendering
MeshRenderer sliceMeshRend = sliceRenderingPlane.GetComponent<MeshRenderer>();
sliceMeshRend.material = new Material(sliceMeshRend.sharedMaterial);
Material sliceMat = sliceRenderingPlane.GetComponent<MeshRenderer>().sharedMaterial;
sliceMat.SetTexture("_DataTex", dataset.GetTexture());
sliceMat.SetTexture("_DataTex", dataset.GetDataTexture());
sliceMat.SetTexture("_TFTex", transferFunction.GetTexture());
sliceMat.SetMatrix("_parentInverseMat", transform.worldToLocalMatrix);
sliceMat.SetMatrix("_planeMat", Matrix4x4.TRS(sliceRenderingPlane.transform.position, sliceRenderingPlane.transform.rotation, Vector3.one)); // TODO: allow changing scale

Просмотреть файл

@ -3,6 +3,7 @@
Properties
{
_DataTex ("Data Texture (Generated)", 3D) = "" {}
_GradientTex("Gradient Texture (Generated)", 3D) = "" {}
_NoiseTex("Noise Texture (Generated)", 2D) = "white" {}
_TFTex("Transfer Function Texture (Generated)", 2D) = "" {}
_MinVal("Min val", Range(0.0, 1.0)) = 0.0
@ -53,6 +54,7 @@
};
sampler3D _DataTex;
sampler3D _GradientTex;
sampler2D _NoiseTex;
sampler2D _TFTex;
@ -79,13 +81,13 @@
// Gets the density at the specified position
float getDensity(float3 pos)
{
return tex3Dlod(_DataTex, float4(pos.x, pos.y, pos.z, 0.0f)).a;
return tex3Dlod(_DataTex, float4(pos.x, pos.y, pos.z, 0.0f));
}
// Gets the gradient at the specified position
float3 getGradient(float3 pos)
{
return tex3Dlod(_DataTex, float4(pos.x, pos.y, pos.z, 0.0f)).rgb;
return tex3Dlod(_GradientTex, float4(pos.x, pos.y, pos.z, 0.0f)).rgb;
}
// Converts local position to depth value

Просмотреть файл

@ -54,7 +54,7 @@ Shader "VolumeRendering/SliceRenderingShader"
fixed4 frag (v2f i) : SV_Target
{
float3 dataCoord = i.relVert +float3(0.5f, 0.5f, 0.5f);
float dataVal = tex3D(_DataTex, dataCoord).a;
float dataVal = tex3D(_DataTex, dataCoord);
float4 col = tex2D(_TFTex, float2(dataVal, 0.0f));
col.a = 1.0f;