• 12
• 12
• 9
• 10
• 13

# Billboarding a line

## Recommended Posts

Let me preface this by acknowledging that I suck at math.

I'm trying to billboard a volumetric spline ribbon with the option to keep it constant width. I don't want to project the end result, because I still want it to be depth tested. Here's the relevant bit from my geometry shader with my own comments on what I think the math does. I'm pretty sure I'm wrong, though:

	// seg has two points, a and b, whose position is in world space

// convert the end points to view space
vec4 vsp1 = gd_matModelView * vec4(seg.a.position.xyz, 1);
vec4 vsp2 = gd_matModelView * vec4(seg.b.position.xyz, 1);

// direction is an interpolated normal along the spline at knots (seg.a.position and seg.b.position);
// convert these to view space as well
vec4 vsn1 = gd_matModelView * vec4(seg.dir1, 1);
vec4 vsn2 = gd_matModelView * vec4(seg.dir2, 1);

// project and normalize
dir1 = vec3(normalize(vsn1.xy), 0);
dir2 = vec3(normalize(vsn2.xy), 0);

// this part is definitely wrong, but I'm not sure what it should be; the idea is to avoid
// segments whose end points change orientation from becoming twists (see below screenshot).
// I'm basically trying to smooth out the discontinuity that arises at oblique angles.
if(dot(dir1, dir2) < 0)
dir2 = -dir2;

// calculate the right vectors in view space
vec3 n1 = vec3(-dir1.y, dir1.x, 0);
vec3 n2 = vec3(-dir2.y, dir2.x, 0);

....

// the segments are issued as:
// 	vsn1 + n1 * thickness1
//	vsn1 - n1 * thickness1
// 	vsn2 + n2 * thickness2
// 	vsn2 - n2 * thickness2

....

// and finally, vertices are emitted after converting to clip space:
gl_Position	= gd_matProjection * position;


There are several issues here, most of which are hilighted in the screenshot below. For this example I set the line thickness to something constant. The thickness is not adjusted for by distance.

From most directions the ribbon actually seems fine, but when the camera points increasingly down the direction of the spline:

1) the ribbon generates a twist

2) projection does not seem to work the way my little brain assumes it should

What am I doing wrong?

##### Share on other sites

I'm not totally sure what your after, but it looks like the line thickness is the exact same throughout the entire thing, it appears to be 1 pixel thick all the way through.

If you don't want it to look like its smaller the further away it gets, could you try an orthographic projection matrix instead of a perspective projection?

##### Share on other sites
6 minutes ago, iedoc said:

I'm not totally sure what your after, but it looks like the line thickness is the exact same throughout the entire thing, it appears to be 1 pixel thick all the way through.

If you don't want it to look like its smaller the further away it gets, could you try an orthographic projection matrix instead of a perspective projection?

Just to clarify, by thickness I mean width :). The line has no actual volumetric thickness - it's just a flat ribbon.

##### Share on other sites

Ah OK, what about that twist? You don't want the twist?

##### Share on other sites
5 minutes ago, iedoc said:

Ah OK, what about that twist? You don't want the twist?

No, I want all segments to be billboarded (facing the camera) so that the line is viewable from any direction and the desired width/thickness is maintained at all times. Right now my code fails to billboard the segments properly and also generates an undesirable twist.

##### Share on other sites

this won't help the twist issue, but if you change gd_matProjection to be an orthographic projection, everything will appear the same size no matter how far away from the camera it is

EDIT: I just realized what you are talking about with the twists. You want the direction to be reversed once it's facing away from the camera, so once it reaches the point where its about to face away from the camera, the direction is reversed

##### Share on other sites
1 minute ago, iedoc said:

this won't help the twist issue, but if you change gd_matProjection to be an orthographic projection, everything will appear the same size no matter how far away from the camera it is

Like I said in my original post, I want to keep the line in 3D as I want it to be depth tested. Orthographic projection doesn't help me here.

##### Share on other sites

I'm probably still not understanding 100%, but orthographic projection would still get you depth. the only difference between orthographic projection and perspective projection is that in perspective projection, things further away appear smaller. depth is still written to the depth buffer in both of them.

##### Share on other sites
1 hour ago, iedoc said:

I'm probably still not understanding 100%, but orthographic projection would still get you depth. the only difference between orthographic projection and perspective projection is that in perspective projection, things further away appear smaller. depth is still written to the depth buffer in both of them.

Okay - that would be an alternative to just scaling things based on distance in the shader. I prefer scaling things manually anyway, because that does not entail changing the projection mode on the client side. That being said, getting things to appear constant size is secondary right now as my primary concern is that my math for calculating the billboarded segments isn't working in the first place.

If you could tell me what is still unclear about my initial query, perhaps I could elaborate?

##### Share on other sites

I'm not sure exactly what your doing in your geometry shader to get the final position, but it looks to me like your not taking the camera position into account. For the dot product, you should dot the normal of your segments with the camera-to-segment direction.

something like this maybe:

dot(segmentNormal, camPosition - segmentPosition) > 0) // reverse segment direction because segment is now facing away from camera