Constant thickness line shader

Hi,

I’m working on a line rendering shader.
The line is made of billboarded polygons.

The problem is that I would like the line to have a constant thickness wether the camera is far or close to the line. (screen space thickness)

Here is how the system works for now:

C# :

I have a script that generate a mesh following a list of points.
For each vertex I store the position of the vertex that will be on the same line segment in the vertex data.

Vertex Shader :

v2f vert (appdata v)
			{
				v2f o;

				//extrusion direction
				float extrusionDir = v.nextPoint.w;

				//clip space pos
				float4 currentProjected = UnityObjectToClipPos(float4(v.vertex.xyz, 1.0));
				float4 nextProjected = UnityObjectToClipPos(float4(v.nextPoint.xyz, 1.0));
				
				//get 2D screen space with W divide
				float2 currentScreen = currentProjected.xy / currentProjected.w;
				float2 nextScreen = nextProjected.xy / nextProjected.w;
				
				//compute extrusion dir and normal
				float2 dir = normalize(nextScreen.xy - currentScreen.xy);
				float2 normal = float2(-dir.y , dir.x);

				float perspectiveCancel = currentProjected.w;		

				//apply extrusion
				currentProjected += float4((normal * extrusionDir * _LineWidth), 0, 0) * perspectiveCancel ;


				o.vertex = currentProjected;

				return o;
			}

I compute a direction vector in screen space in order to know which way to extrude the line.
And I multiply this vector by currentProjected.w in order to “cancel” the perspective.

This solution is working fine until the camera is too close from the line:

Fine at distance:

Issue at close distance :

as you can see the line is distorted if some of the vertex are behind the camera.
I think that is because the perspectiveCancel value becomes negative ?

What do you think I can do to correct this ?

Thanks !

The answer of this question in the comments by Glurth, Thanks !

I was wrong trying to compute the width of the line based on the distance with the vertex when the vertex is behind the camera.

Has Glurth said the correct way to compute the camera width in this case is to compute the line intersection with the near clip plane,we can then use this intersection coordinates as new coordinates for the vertex, resulting in having the good width.

The final result for the vertex shader is :

			v2f vert (appdata v)
			{
				v2f o;

				//extrusion direction
				float extrusionDir = v.nextPoint.w;

				//clip space pos
				float4 currentProjected = UnityObjectToClipPos(float4(v.vertex.xyz, 1.0));
				float4 nextProjected = UnityObjectToClipPos(float4(v.nextPoint.xyz, 1.0));
				
				//get 2D screen space with W divide
				float2 currentScreen = currentProjected.xy / currentProjected.w;
				float2 nextScreen = nextProjected.xy / nextProjected.w;
				
				//compute extrusion dir and normal
				float2 dir = normalize(nextScreen.xy - currentScreen.xy);
				float2 normal = float2(-dir.y /*_ProjectionParams.x*/, dir.x);

				float perspectiveCancel = currentProjected.w /100;
			
				//special case where vertex is behind the camera clip plane
				if (currentProjected.w <0)
				{
					float3 normalizedClipSpaceDir =  normalize(currentProjected.xyw - nextProjected.xyw);
					float coef = -currentProjected.w / normalizedClipSpaceDir.z;
					float3 intersectionPos = currentProjected.xyw + (normalizedClipSpaceDir * coef);
					float4 clippedPos = float4(intersectionPos.x, intersectionPos.y, 0, intersectionPos.z);

					currentProjected = clippedPos;
				}
				else
				{
					//apply extrusion
					currentProjected += float4((normal * extrusionDir * _LineWidth), 0, 0) * perspectiveCancel;
				}

				o.vertex = currentProjected;

				return o;
			}