how to create per triangle shader in metal?

I want to compute normals per triangle in shader. I could only operate per vertex. but our primitive is triangle. so there should be a way to deal with a triangle as a whole. iPad GLSL. From within a fragment shader how do I get the surface - not vertex - normal gives answers in opengl but I am looking in metal

Replies

Hello


To be exact, vertex shaders are _invoked_ per vertex, right, but you can operate on whatever you want. Like this:

struct VertexOut {
     float4 position [[position]];
     float2 normal;
};
vertex VertexOut vertexShader(
     constant float4 * vertices [[buffer(0)]],
     uint vid [[vertex_id]]
)
{
     VertexOut vout;
     // vid is vertex id, so compute triangle id out of that
     uint tid = vid / 3;
     // load all three triangle vertices
     float4 a = vertices[tid * 3], b = vertices[tid * 3 + 1], c = vertices[tid * 3 + 2];
     // now compute per-triangle normal (or whatever else one may want)
     vout.normal = compute_normal(a, b, c);
     vout.position = vertices[vid];
     return vout;
}   


Of course you invoke this with float4 vertex coordinates buffer attached as buffer(0), and you pass in proper number of triangles/vertices, so that the shader above gets invoked for each vertex. Yeah, computation will be done three times per each triangle. If that is a concern (doesn't have to be so) I'd recommend creating compute kernel that produces desired result for each triangle given (so compute kernel gets invoked only once per triangle) and writes it to output buffer. Then code like above can get that second buffer, too, and instead of doing compute_normal just pulls from that second buffer using triangle index (tid).


Hope that helps

Michal