Металлический вершинный шейдер расширяет отдельные треугольники

Я работаю над 2D приложением для рисования. Я хотел бы сделать эффект, когда линии расширяются, как это:

Это для анимации, где линии расширяются и появляются как воздушные шары.

Линии нарисованы в виде полос треугольника. Моя идея состоит в том, чтобы заставить их расширяться, увеличивая каждый треугольник в вершинном шейдере. Каждая вершина должна быть отодвинута от других вершин треугольника.

Для этого мне нужно получить доступ к другим вершинам треугольника. Это возможно в металле?

vertex Vertex vertex_expand(device float2 *vertices [[buffer(0)]],
                          constant VertexUniforms *uniforms [[buffer(1)]],
                          uint vid [[vertex_id]]) {

// is vertices[vid - 1] and vertices[vid + 1] the previous and next vertices? 
// is vid=0 the first vertex?

}

1 ответ

Решение

Да, вы можете получить доступ к другим вершинам, в зависимости от того, как вы выполняете рисование. Если вы делаете индексированное рисование, то связь между идентификаторами вершин и треугольниками регулируется вашим индексным буфером. Проблема, однако, в том, что вы не знаете, какой индекс используется для данного вызова вершинного шейдера (и он может быть вызван один раз для нескольких индексов, если все эти индексы ссылаются на одну и ту же вершину).

Таким образом, вам следует избегать индексированного рисунка.

В таком случае, да, vertices[vid - 1] а также vertices[vid + 1] являются предыдущей и следующей вершинами.

Тем не менее, обратите внимание, что с треугольной полосой каждая вершина является членом нескольких треугольников. Таким образом, для каждой вершины нет одного уникального треугольника, от центра которого вы можете переместить эту вершину, чтобы расширить ее. Я ожидаю, что вам понадобятся две вершины, которые являются соседями по тому же краю полосы, что и обрабатываемая вами, используйте их для вычисления нормали для сегмента, содержащего текущую вершину, и для перемещения вершины вдоль нее.

Поскольку вы анимируете и, следовательно, будете делать это многократно, вы можете заранее рассчитать эти нормали и передать их как данные для каждой вершины. Вы можете использовать вычислительный шейдер для этих вычислений, хотя выполнение этого на процессоре может быть достаточно быстрым. Если вы предварительно вычислите нормали таким образом, вершинному шейдеру не нужно будет ссылаться на соседние вершины.

Отвечаю на это, потому что у меня недостаточно репутации, чтобы оставлять комментарий к ответу Кена. Кажется, есть способ получить доступ к данным соседних вершин и во время проиндексированного рисования. Передайте индексный буфер в качестве аргумента вершинному шейдеру.

[encoder setVertexBuffer:vertices offset:0 atIndex:0 ];
[encoder setVertexBuffer:indices offset:0 atIndex:1];
[encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:indexCount];// this calls vertex shader with vid ranging from 0 to indexCount-1


vertex Vertex vertex_expand(device float2 *vertices [[buffer(0)]],
                            device uint *indices [[buffer(1)]],
                            uint vid [[vertex_id]]) {

// if vid % 3 == 0 then vertices[indices[vid]] is the current vertex and  vertices[indices[vid + 1]] and vertices[indices[vid + 2]] are the other two vertices belonging to the same triangle.

}
Другие вопросы по тегам