I am currently writing a compute shader that requires a simple float multiplication of a float and a uint3, and I am getting really inaccurate results.
for example, uint3(1, 2, 3) * 0.25
expected result: uint3(0.25, 0.5, 0.75)
actual result: uint3(0.3, 0.5, 0.8)
Any idea how to increase the precision somehow?
The compute shader:
[numthreads(X_THREADS, Y_THREADS, Z_THREADS)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
// Fill the array
uint tid = id.x;
while (tid < octree_length)
{
// Normalize tid
uint depth = OctreeDepth(tid);
uint mid = tid - depth_offsets[depth];
// Compute node data
float node_size = bounds_size / pow(2, depth);
float3 node_min = MortonToXYZ(mid) * node_size;
// Build node
octree[tid].anchor = node_min;
octree[tid].size = node_size;
// Move tid
tid += total_num_threads;
}
}
The inaccurate multiplication:
float3 node_min = MortonToXYZ(mid) * node_size;
The code that launches the shader and reads the data back:
ComputeBuffer BuildOctree(Vector3 boundsMin, float boundsSize, int octreeDepth, Vector3Int numThreadGroups)
{
// Compute constants
int totalNumThreads = numThreadGroups.x * numThreadGroups.y * numThreadGroups.z * THREADS_PER_GROUPS;
// Compute depth offsets and octree length
int[] depthOffsets = new int[octreeDepth];
int length = 0;
for (int i = 0; i < octreeDepth; i++)
{
depthOffsets[i] = length;
length += (int) Mathf.Pow(8, i);
}
// Prepare buffers
ComputeBuffer octree = new ComputeBuffer(length, 4 * sizeof(float), ComputeBufferType.Structured);
ComputeBuffer depthOffsetsGPU = new ComputeBuffer(octreeDepth, sizeof(int), ComputeBufferType.Structured);
depthOffsetsGPU.SetData(depthOffsets);
octree.SetData(new OctreeNode[length]);
// Load data into shader
OCTREE_BUILDER.SetBuffer(0, "octree", octree);
OCTREE_BUILDER.SetBuffer(0, "depth_offsets", depthOffsetsGPU);
OCTREE_BUILDER.SetInt("total_num_threads", totalNumThreads);
OCTREE_BUILDER.SetInt("octree_length", length);
OCTREE_BUILDER.SetFloat("bounds_size", boundsSize);
// Launch kernal
OCTREE_BUILDER.Dispatch(0, numThreadGroups.x, numThreadGroups.y, numThreadGroups.z);
OctreeNode[] output = new OctreeNode[length];
octree.GetData(output);
for (int i = 0; i < output.Length; i++)
Debug.Log("cell[" + i + "]: " + output[i].anchor + ", " + output[i].size);
// Return octree buffer
return octree;
}
Note:\
As user @bart pointed out, the issue was in the print, unity prints a 2 digit format which rounded my values down, by using ToString("F5") in my print it shows the correct values
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With