Skip to content

Commit 38b7279

Browse files
Compute Histogram on GPU
NOTE: - Result seems to be broken for some reason (probably texture format) - Supports only 8-bit data
1 parent cb4ef48 commit 38b7279

File tree

4 files changed

+86
-2
lines changed

4 files changed

+86
-2
lines changed

Assets/Editor/TransferFunctionEditorWindow.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ private void OnGUI()
7979
tf.GenerateTexture();
8080

8181
if(histTex == null)
82-
histTex = HistogramTextureGenerator.GenerateHistogramTexture(volRendObject.dataset);
82+
histTex = HistogramTextureGenerator.GenerateHistogramTextureOnGPU(volRendObject.dataset);
8383

8484
tfGUIMat.SetTexture("_TFTex", tf.GetTexture());
8585
tfGUIMat.SetTexture("_HistTex", histTex);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma kernel HistogramInitialize
2+
#pragma kernel HistogramMain
3+
4+
Texture3D<float4> VolumeTexture;
5+
6+
struct histStruct {
7+
uint cnt;
8+
};
9+
RWStructuredBuffer<histStruct> HistogramBuffer;
10+
11+
[numthreads(8, 1, 1)]
12+
void HistogramInitialize(uint3 id : SV_DispatchThreadID)
13+
{
14+
HistogramBuffer[id.x].cnt = uint(0);
15+
}
16+
17+
[numthreads(8, 8, 8)]
18+
void HistogramMain(uint3 id : SV_DispatchThreadID)
19+
{
20+
uint col = uint(255.0 * VolumeTexture[id.xyz].r);
21+
22+
InterlockedAdd(HistogramBuffer[col].cnt, 1);
23+
}

Assets/Resources/ComputeHistogram.compute.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Scripts/Utils/HistogramTextureGenerator.cs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using UnityEngine;
1+
using System.Linq;
2+
using UnityEngine;
23

34
namespace UnityVolumeRendering
45
{
@@ -41,6 +42,58 @@ public static Texture2D GenerateHistogramTexture(VolumeDataset dataset)
4142
cols[iSample] = new Color(Mathf.Log10((float)values[iSample]) / Mathf.Log10((float)maxFreq), 0.0f, 0.0f, 1.0f);
4243

4344
texture.SetPixels(cols);
45+
//texture.filterMode = FilterMode.Point;
46+
texture.Apply();
47+
48+
return texture;
49+
}
50+
51+
52+
/// <summary>
53+
/// Generates a histogram (but computaion is done on GPU) where:
54+
/// X-axis = the data sample (density) value
55+
/// Y-axis = the sample count (number of data samples with the specified density)
56+
/// </summary>
57+
/// <param name="dataset"></param>
58+
/// <returns></returns>
59+
public static Texture2D GenerateHistogramTextureOnGPU(VolumeDataset dataset)
60+
{
61+
ComputeShader computeHistogram = Resources.Load("ComputeHistogram") as ComputeShader;
62+
int handleInitialize = computeHistogram.FindKernel("HistogramInitialize");
63+
int handleMain = computeHistogram.FindKernel("HistogramMain");
64+
65+
ComputeBuffer histogramBuffer = new ComputeBuffer(256, sizeof(uint) * 1);
66+
uint[] histogramData = new uint[256];
67+
Color32 [] histogramCols = new Color32[256];
68+
69+
Texture3D dataTexture = dataset.GetDataTexture();
70+
71+
if (handleInitialize < 0 || handleMain < 0)
72+
{
73+
Debug.LogError("Histogram compute shader initialization failed.");
74+
}
75+
76+
computeHistogram.SetTexture(handleMain, "VolumeTexture", dataTexture);
77+
computeHistogram.SetBuffer(handleMain, "HistogramBuffer", histogramBuffer);
78+
computeHistogram.SetBuffer(handleInitialize, "HistogramBuffer", histogramBuffer);
79+
80+
computeHistogram.Dispatch(handleInitialize, 256 / 8, 1, 1);
81+
computeHistogram.Dispatch(handleMain, (dataTexture.width + 7) / 8, (dataTexture.height + 7) / 8, (dataTexture.depth + 7) / 8);
82+
83+
histogramBuffer.GetData(histogramData);
84+
85+
int maxValue = (int)histogramData.Max();
86+
87+
Texture2D texture = new Texture2D(256, 1, TextureFormat.RGBA32, false);
88+
for (int iSample = 0; iSample < 256; iSample++)
89+
{
90+
histogramCols[iSample] = new Color(Mathf.Log10((float)histogramData[iSample]) / Mathf.Log10((float)maxValue), 0.0f, 0.0f, 1.0f);
91+
//if (histogramData[iSample] == 0)
92+
// Debug.Log (iSample);
93+
}
94+
95+
texture.SetPixels32(histogramCols);
96+
//texture.filterMode = FilterMode.Point;
4497
texture.Apply();
4598

4699
return texture;

0 commit comments

Comments
 (0)