简体   繁体   English

金属顶点着色器扩展单个三角形

[英]Metal vertex shader expand individual triangles

I'm working on a 2d drawing app.我正在开发一个 2d 绘图应用程序。 I'd like to make an effect where lines expand, like this:我想在线条扩展处产生效果,如下所示:

扩展线

This is for an animation where the lines expand and pop like balloons.这是一个动画,其中线条像气球一样膨胀和弹出。

The lines are drawn as triangle strips.线条绘制为三角形条。 My idea is to make them expand by making each triangle larger in the vertex shader.我的想法是通过在顶点着色器中使每个三角形变大来使它们扩展。 Each vertex should be pushed away from the other vertices in the triangle.每个顶点都应该被推离三角形中的其他顶点。

To do this, I'd need to access the other vertices in the triangle.为此,我需要访问三角形中的其他顶点。 Is that possible in Metal?这在金属中可能吗?

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?

}

Yes, you can potentially access the other vertices, depending on how you do the draw.是的,您可以访问其他顶点,具体取决于您如何进行绘制。 If you do indexed drawing then the relationship between vertex IDs and triangles is governed by your index buffer.如果您进行索引绘图,则顶点 ID 和三角形之间的关系由您的索引缓冲区控制。 The problem, though, is that you don't know the index being used for a given invocation of the vertex shader (and it might be invoked once for multiple indexes if those indexes all refer to the same vertex).但是,问题是您不知道用于给定顶点着色器调用的索引(如果多个索引都引用同一个顶点,则可能会为多个索引调用一次)。

So, you would have to avoid indexed drawing.因此,您必须避免索引绘图。

In that case, yes, vertices[vid - 1] and vertices[vid + 1] are the previous and next vertices.在这种情况下,是的, vertices[vid - 1]vertices[vid + 1]是前一个和下一个顶点。

However, note that with a triangle strip, each vertex is a member of multiple triangles.但是,请注意,对于三角形带,每个顶点都是多个三角形的成员。 So, there's not one unique triangle for each vertex away from whose center you can move that vertex to expand it.因此,每个顶点都没有一个独特的三角形,您可以移动该顶点以扩展它的中心。 I expect you'd want the two vertexes that are neighbors along the same edge of the strip as the one you're processing, use those to compute a normal for the segment containing the current vertex, and move the vertex along that.我希望您希望与您正在处理的条带相同边缘的两个顶点相邻,使用它们来计算包含当前顶点的线段的法线,然后沿该条移动顶点。

Since you're animating and thus going to be doing this repeatedly, you might want to compute those normals once in advance and pass them in as per-vertex data.由于您正在制作动画并因此将重复执行此操作,您可能希望提前计算一次这些法线并将它们作为每个顶点数据传递。 You could use a compute shader for this computation, although doing it on the CPU may be fast enough.您可以使用计算着色器进行此计算,尽管在 CPU 上执行它可能足够快。 If you precompute the normals this way, the vertex shader won't need to reference any neighboring vertexes.如果您以这种方式预先计算法线,顶点着色器将不需要引用任何相邻的顶点。

Answering this because I don't have enough reputation to post a comment to Ken's answer.回答这个问题是因为我没有足够的声誉来对 Ken 的回答发表评论。 There seems to be a way to access the data of neighboring vertices during indexed drawing as well.似乎也有一种方法可以在索引绘图期间访问相邻顶点的数据。 Pass the index buffer as an argument to the vertex shader.将索引缓冲区作为参数传递给顶点着色器。

[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.

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM