#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:
Родитель
ebda446929
Коммит
d012728c2e
|
@ -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;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче