Attached is the example from the particles workshop at node15, it does a constrain solver to generate some lines, I’d like to turn the lines into tubes, preferably with normals so they can be shaded.
I’ve attempted to hack this together but failed, I imagine its pretty straight forward, but haven’t managed to crack it yet.
The other question I have is whether you can perform a RestartStrip() at the end of each line rather than discarding in the ps

From node15 particles workshop (281.9 kB)

``````void GSOutputPoint( float3x3 m, float3 inpos, int i, inout TriangleStream<PSInput> gsout )
{
PSInput output;

float3 pos = mul(TubeRes[i](i),m ) * fRad;

float3 norm = normalize(pos);
norm = mul(float4(norm,0),tV).xyz;

pos += inpos;
output.pos = mul( float4(pos,1), tVP );
output.norm = norm;

gsout.Append(output);
}

[maxvertexcount(20)](maxvertexcount(20))
void GS(line GSInput input[2](2), inout TriangleStream<PSInput> gsout)
{
/*Stuff to create rotation matrices for tube,
from ms samples and quite sucks, need replacement at some point,
but for thin objects it's cool */

float3 n1 = float3(0,0,1);
float3 n2 = float3(0,0,1);
float3 left0 = cross( input[0](0).dir, n1 );
float3x3 m0 = float3x3( -left0, n1, input[0](0).dir );
float3 left1 = cross( input[1](1).dir, n2);
float3x3 m1 = float3x3( -left1, n2, input[1](1).dir );

float3 pos0 = input[0](0).pos;
float3 pos1 = input[1](1).pos;

//Build a little tube from the segment above
for(int i=0; i < TUBE_RES + 1; i++)
{
GSOutputPoint( m1, pos1, i, gsout );
GSOutputPoint( m0, pos0, i, gsout );
}
gsout.RestartStrip();
}
``````

the tube code i got

is TubeResi a predefined structure?
You got a working shader you could post that I could take apart?

``````float3x3 rotationAlign(float3 d, float3 z)
{
float3  v = cross( z, d );
float c = dot( z, d );
float k = 1.0f/(1.0f+c);

return float3x3( v.x*v.x*k + c,     v.y*v.x*k - v.z,    v.z*v.x*k + v.y,
v.x*v.y*k + v.z,   v.y*v.y*k + c,      v.z*v.y*k - v.x,
v.x*v.z*k - v.y,   v.y*v.z*k + v.x,    v.z*v.z*k + c    );
}

[maxvertexcount(64)](maxvertexcount(64))
void GS(line vs2ps gsInput[2](2), inout TriangleStream<vs2ps> outStream)
{
vs2ps output = (vs2ps)0;

float4 p1 = gsInput[0](0).PosWVP;
float4 p2 = gsInput[1](1).PosWVP;
float3 dir = normalize(p1-p2).xyz;

float3x3 rot1 = rotationAlign( float3(1,0,0), dir);
float3x3 rot2 = rotationAlign( float3(1,0,0), dir);

float4x4 tWVP = mul(tW,tVP);
for (int i=0; i<res+1; i++)
{
float phi = (i/(float)res)*3.14*2;
float3 up = (float3)0;
sincos(phi,up.y,up.z);

float3 bt1 = normalize(mul(normalize(up),rot1));
output.PosWVP.w = 1;

output.PosWVP = mul(output.PosWVP, tWVP);

outStream.Append(output);

float3 bt2 = normalize(mul(normalize(up),rot1));
output.PosWVP.w = 1;

output.PosWVP = mul(output.PosWVP,tWVP);

outStream.Append(output);
}

outStream.RestartStrip();
}
``````

kind of makes the tubes work, but still need to find a way to not connect it all into 1 tube but split at a set length eg 10 in this case…

``````if ((gsInput[1](1).iv2%StrandLength) == 0) {p2=p1;} //dont connect strips
``````

which seems to fix that, now I need shading/uv’s

``````- define TUBE_RES_3 3
- define TUBE_RES_4 4
- define TUBE_RES_6 6

- ifndef TUBE_RES
#define TUBE_RES TUBE_RES_6
- endif

- if TUBE_RES == TUBE_RES_3
static const float3 TubeRes[4](4) : IMMUTABLE =
{
float3(1.0000,0.0000,0.0000),
float3(-0.5000,0.8660,0.0000),
float3(-0.5000,-0.8660,0.0000),
float3(1.0000,0.0000,0.0000),
};
- endif

- if TUBE_RES == TUBE_RES_4
static const float3 TubeRes[5](5) : IMMUTABLE =
{
float3(1.0000,0.0000,0.0000),
float3(0.0000,1.0000,0.0000),
float3(-1.0000,0.0000,0.0000),
float3(0.0000,-1.0000,0.0000),
float3(1.0000,0.0000,0.0000),
};
- endif

- if TUBE_RES == TUBE_RES_6
static const float3 TubeRes[7](7) : IMMUTABLE =
{
float3( 1.0f, 0.0f,    0 ),
float3( 0.5f, 0.866f,  0 ),
float3( -0.5f, 0.866f, 0 ),
float3( -1.0f, 0.0f,   0 ),
float3( -0.5, -0.866f, 0 ),
float3( 0.5, -0.866f,  0 ),
float3( 1.0f, 0.0f,    0 ),
};
- endif``````