See also:

I’m working on a shader that’s used to draw instanced lines connecting pairs of points.

The endpoints for each line are passed in through instanced custom attributes (`TDInstanceCustomAttrib2()`

etc).

The input geometry is just a line with some points and an attribute indicating how far along each point is within the line.

The vertex shader replaces the position for each vertex with a linear interpolation between the two points for that instance.

All of that part works fine.

I’ve even been able to add position-based noise to make the lines wiggle while keeping their endpoints in place.

Where I’m having difficulty is attempting to go from a wireframe line to a tube. In my initial attempt, the input geometry is a tube with an equivalent attribute based on how far each point is along the Y axis. Then I’m trying to take that original tube position (which includes some amount of offset on X and Z) and map that to where it should go based on the end points. I tried using TDRotateToVector() to reorient it then adding the offset of the center point between the two ends.

The offsetting works fine but the angles are wrong.

And I suspect the tubes would end up with inconsistent widths even if it were correct.

If possible I’d like to do this without involving a geometry shader, since there could be 30+ vertices for each line, each with noise applied, which I think would cause performance issues. Also I’d still need to figure out the spatial conversions.

Original code (simplified a bit):

```
in float lineEnd; // how far along the line the point is, in 0...1
void main()
{
vec4 worldSpacePos = TDDeform(P);
vec3 pos1 = TDInstanceCustomAttrib0().xyz;
vec3 pos2 = TDInstanceCustomAttrib1().xyz;
vec3 pos = mix(pos1, pos2, lineEnd);
// add noise to pos based on pos, etc...
worldSpacePos.xyz = pos;
gl_Position = TDWorldToProj(worldSpacePos);
}
```

Tube attempt:

```
uniform float uThickness;
in float lineEnd;
void main()
{
float angleAroundAxis = atan(P.y, P.x);
vec4 worldSpacePos = TDDeform(P);
vec3 pos;
vec3 pos1 = TDInstanceCustomAttrib0().xyz;
vec3 pos2 = TDInstanceCustomAttrib1().xyz;
vec3 lineVec = pos2 - pos1;
float lineLength = length(lineVec);
vec3 midPoint = (pos1 + pos2) / 2.;
vec3 localPos;
localPos.y = -lineLength/2 + lineLength * lineEnd;
localPos.x = uThickness * cos(angleAroundAxis);
localPos.z = uThickness * sin(angleAroundAxis);
pos = localPos * TDRotateToVector(lineVec, vec3(0, 1, 0)); // probably the issue
pos += midPoint;
// add noise, etc.
worldSpacePos.xyz = pos;
gl_Position = TDWorldToProj(worldSpacePos);
```