У меня есть сетка и массив точек. Я хочу вычислить для каждой вершины индекс ближайшей точки в массиве. У меня есть рутина, которая работает:
for (int i=0;i<vertexPositions.Length;i++)
{
float minDist = 100000.0f;
int index=0;
float dist;
for (int a=0;a<pointPositions.Length;a++)
{
dist = (vertexPositions[i] - pointPositions[a]).sqrMagnitude;
if (dist<minDist)
{
minDist = dist;
index = a;
}
}
vertexParameter[i] = index;
}
Массив vertexParameter
содержит желаемый результат. Эта процедура очень медленная, если есть много вершин, поэтому я хотел создать вычислительный шейдер, который делает то же самое. Но я новичок в вычислительных шейдерах…
Это мой код вычислительного шейдера:
#pragma kernel ClosestPoint
struct vertexData
{
float3 position;
int parameter;
};
struct pointData
{
float3 position;
float parameter;
};
RWStructuredBuffer<vertexData> vertex;
StructuredBuffer<pointData> point;
[numthreads(32, 1, 1)]
void ClosestPoint(uint3 id : SV_DispatchThreadID)
{
int index;
float dist;
float minDist = 1000.0f;
for (uint i = 0; i < point.Length; i++)
{
dist = distance(point[i].position, vertex[id.x].position);
if (dist < minDist)
{
minDist = dist;
index = i;
}
}
vertex[id.x].parameter = index;
}
Не знаю почему, но этот код дает ошибочные результаты. Результаты меняются, если я изменяю ThreadGroups в вызове Dispatch, поэтому я полагаю, что это может быть связано с некоторыми проблемами синхронизации…?
В случае необходимости, это код скрипта, который вызывает шейдер:
vertex = new ComputeBuffer(vertices.Length, System.Runtime.InteropServices.Marshal.SizeOf(typeof(vertexData)));
vertex.SetData(vertices);
point= new ComputeBuffer(points.Length, System.Runtime.InteropServices.Marshal.SizeOf(typeof(pointData)));
point.SetData(points);
shader.SetBuffer(kernelHandle, "vertex", vertex);
shader.SetBuffer(kernelHandle, "point", point);
shader.Dispatch(kernelHandle, 1, 1, 1);
vertex.GetData(vertices);
for (int i = 0; i < vertexParameter.Length; i++)
{
vertexParameter[i] = vertices[i].parameter;
}
vertex.Release();
point.Release();
dxl
в коде hlsl? Кажется, это не определено/объявлено там. - person Ruzihm   schedule 18.06.2019point.Length
компилируется в hlsl. Возможно, он случайно имел в виду что-то другое. Попробуйте добавить переменную intcount
, передающую длину буфера точек, используяSetInt
. См. здесь для примера того, о чем я говорю. - person Ruzihm   schedule 18.06.2019count
ничего не изменило. Но я как-то частично нашел решение. Кажется, проблема в том, что я не отправляю нужное количество потоков. Если я устанавливаю `[numthreads(32, 1, 1)]` в шейдере иshader.Dispatch(kernelHandle, vertices.Length, 1, 1);
, процедура дает правильный результат. Но иметь так много групп потоков, все с одним потоком, кажется очень плохой оптимизацией... - person kefren   schedule 18.06.2019