Surface normal to screen angle

I've been struggling to get this working. I simply wish to take a surface normal and convert it to a screen angle.

As an example, assuming we're working with the highlighted surface on the sphere below, where the arrow is the normal, the 2D angle would obviously be PI/4 radians.

Here's one of the many things I've tried to no avail:

``````float4 A = v.vertex;
float4 B = v.vertex + float4(v.normal, 0.0);

A = mul(MVP, A);
B = mul(MVP, B);

A.xy /= A.w;
B.xy /= B.w;

o.theta = atan2(B.y - A.y, B.x - A.x);
``````

I'm finally at my wit's end. Thanks for any and all help.

-
The code you posted looks like it should work. Can you be more specific about how it's not working? Maybe you can add some debug output of the intermediate values? For instance, plot A and B in screen space after transforming and projecting them, so you can see visually if they're getting the right values. – Nathan Reed Jul 2 '13 at 4:52
You're entirely correct. I was just using my own code improperly. Thanks. – Tannz0rz Jul 2 '13 at 5:12
The screen angle is not “obviously” `pi/4`. It is closer to `pi/6`, actually. The normal vector always lies on a line that goes through the centre of the sphere. Here is a more accurate drawing. – sam hocevar Jun 8 '14 at 19:18