Given a point light source, a eye position, we can find the silhouette (outline) of the given model. We can first find the silhouette edge, project the model into a 2-D plane, then traverse all silhouette edges. But when it comes to concave model, some part of the silhouette edges should not be included in the model outline. How to find those parts? Also, can we do this without projecting the model into a 2-D plane?
I'll explain the "geometric way" of solving the problem since that's the solution you seem to be after, instead of using rasterization that Dan suggested in the comments.
You can get the list of potential silhouette edges without 2D projection by first iterating through all edges and taking dot product of the normal of the attached two triangles against the eye->edge vector (any point on the edge will do, e.g. one of the end-points). If the dot products for the two triangles on the edge have different signs, then it's a potential silhouette edge. If the object is convex, then you are done and got the list of silhouette edges.
For concave objects it gets more complicated. For concave objects it could be that an edge is only partially a silhouette edge and can be potentially split to N fragments that all belong to the silhouette. So you need to process the list of potential edges and clip them with the geometry. The way you can do the clipping is to extrude every triangle in the geometry away from eye and use this volume to clip the list of potential silhouette edges. The remaining edge fragments that are not clipped away are your silhouette.