3D Line / Tube in geometry shader

Hi,
I’m cooking up a shader based 3D Line thingy.
It basically works with some limitations:

Thoughts and help welcome!

Still to do:

  • Smooth normals!
  • Why is “Maxvertexcount” in geometry shader limited to 64? (Or is it my machine?)
  • Buffer for thickness and individial line segments
  • Caps
  • There are some glitches going on with shadows. I guess it’s an issue with clipping…not sure

shaders.zip (10.0 KB)

Related:

9 Likes

Tubby_Test.zip (11.3 KB)

Update with Caps.

Here is a fixed version that has correct depth output and writes some other values that the pixel shader might need. you could think of adding tangents, if you want to use normal maps.

TubbyShader.zip (10.7 KB)

it also outputs one strip, and not individual triangles, which reduces the vertex output count.

That is important for the shader output limit, it is 1024 32-bit values. so the amount of vertices you can emit is 1024/vertexstride. That can vary, depending on what the pixel shader needs. you can set all stream values in the geometry shader and depending on the material features, your max count will be limited as the output datatype will be dynamically compiled.

you might also need to pass in the up vector along with the points, to avoid flipping.

5 Likes

Re: Vertexstride, I already passed this on to Michael, seemed legit:

https://www.gamedev.net/forums/topic/600141-limit-on-maxvertexcount-gs/

Have you considered using geometry shader instancing? Assuming you are using D3D11 hardware, you can simply execute multiple copies of the geometry shader for each primitive. Then you can process one half of your data in one instance and the other half in the second instance - you would then just need to use the SV_GSInstanceID system value semantic in the shader to select the proper subset of data to produce. You can have up to 32 instances created for each primitive, so you could effectively up the limit to 1024*32.

1 Like

Thanks, very interesting, this discussion leads to this: How To Instance a Geometry Shader - Win32 apps | Microsoft Learn

you can add an [instance(N)] attribute, where N is a number between 1 and 32. And then use SV_GSInstanceID to emit more vertices. But not 100% sure if the SDSL parser knows about that. I’ve never tried it.

I have now and it works :)

TubbyShaderGSInstancing.zip (10.8 KB)

The shader signature should look like this:

[instance(32)]
[maxvertexcount(64)]
stage void GSMain(line Input input[2], inout TriangleStream<Output> triangleStream, uint gsInstanceID : SV_GSInstanceID)

4 Likes

That escalated quickly!

Anyway here is the optimized and fixed version, with unoptimized caps:
Tubby.zip (11.2 KB)

4 Likes

Looks great, they only seem to be missing setting the depth value, I’d recommend using the AppendVertex() method for them as well to be sure that all vertex shader variables are set…

3 Likes

should it be able to have a texture? it turns invisible just leaving the shadow.

It’s caused by this error:

error X8000: Validation Error: Declared output vertex count (64) multiplied by the total number of declared scalar components of out
put data (18) equals 1152.  This value cannot be greater than 1024.

You can decrease the maxvertexcount inside the shader to 56 and it should “work” idk what side effects it causes though.

2 Likes

Thanks, that worked. Where did you get the error from?

Also here is a version of the shader to have texture coordinates from start to end (was segment wise):
Tubby_ShaderFX_texcoord.zip (2.0 KB)

did not change the caps though

4 Likes

The Log window.

2 Likes

what is missing in the shader to make the mesh entity transform work?
i see the one part that is commented:
// override the vertex shader methods that handle position
but no idea what to do with it.

I found a shader from a project that reduces the vertex count a lot by emitting a triangle strip, effectively only creating each vertex position only once, except at the start/end of the angle. This allows to have almost double the resolution.

I’ll need to find it and remove some unrelated code in it…

1 Like

I found another issue, it is not possible to rotate Tubby
TubbyRotate.vl (35.7 KB)

It’s the same issue @tgd posted two messages above.

Try changing line 29 like this:

streams.PositionWS = mul(float4(position, 1.0), World);
2 Likes

something weird is going on when you have a lot of them.


EDIT: I need in total 66607 lines. could it be some GPU thing where it behaves weird if there are too many triangles?

Yes thats it, thanks again!

also noticed these twists when the angles change in certain directions between the segments. seems something with the tangent, bitangent calculations turning negative or something but i am totally lost on this.

Its really the changing up vector and it seems there is no way to compute a continuous twist free up vector in a bare gs shader because you cant store any data between computations of segments:(

One more thing.

Using the texturecoordinate shader, I experience some weird behavior et the ends of the lines. Texurecoordinartes seems fine, except at the ends.
Very visible with low particles count.


Tubby3-stripes.vl (39.2 KB)