Performant way to create a cylinder by a point

Started by
2 comments, last by Adam_42 12 years, 6 months ago
Currently I'm creating cylinders from a point representing the center position of the cylinder. In addition, I specify the radius, segment count and height of a cylinder. Due to performance issues I want to do that in a Gemetry Shader.

The following code (reduced to the position relevant parts) shows my shader code:

[source lang="cpp"]struct VS_OUT
{
float radius : RADIUS;
float height : HEIGHT;
uint segments : SEGMENTS;
float3 pos_l : POSITION;
};

struct GS_OUT
{
float4 pos_h : SV_POSITION;
};


[maxvertexcount(128)]
void gs(point VS_OUT gin[1], inout TriangleStream<GS_OUT> s)
{
const float pi = 3.14159265f;

// Side faces
float phi = 2 * pi / gin[0].segments;
for (uint i = 0; i <= gin[0].segments; ++i)
{
float4 pos_l = float4(gin[0].pos_l.x + gin[0].radius * sin(phi * i), gin[0].pos_l.y,
gin[0].pos_l.z + -gin[0].radius * cos(phi * i), 1.f);

GS_OUT gout;
gout.pos_h = mul(pos_l, g_mat_wvp);
s.Append(gout);

pos_l.y += gin[0].height;
gout.pos_h = mul(pos_l, g_mat_wvp);
s.Append(gout);
}

// Bottom face
s.RestartStrip();
for (int i = gin[0].segments; i >= 0; --i)
{
float4 pos_l = float4(gin[0].pos_l.x + gin[0].radius * sin(phi * i), gin[0].pos_l.y,
gin[0].pos_l.z + -gin[0].radius * cos(phi * i), 1.f);

GS_OUT gout;
gout.pos_h = mul(pos_l, g_mat_wvp);
s.Append(gout);

pos_l.xz = 0;
gout.pos_h = mul(pos_l, g_mat_wvp);
s.Append(gout);
}

// Top face
s.RestartStrip();
for (uint i = 0; i <= gin[0].segments; ++i)
{
float4 pos_l = float4(gin[0].pos_l.x + gin[0].radius * sin(phi * i),
gin[0].pos_l.y + gin[0].height, gin[0].pos_l.z + -gin[0].radius * cos(phi * i), 1.f);

GS_OUT gout;
gout.pos_h = mul(pos_l, g_mat_wvp);
s.Append(gout);

pos_l.xz = 0;
gout.pos_h = mul(pos_l, g_mat_wvp);
s.Append(gout);
}
}[/source]

Is there a way to get this more performant? Thanks in advance.
Advertisement
Surely the fastest option is to create a single static cylinder model (or maybe 2-3 with varying poly counts), and then transform that to the appropriate size and shape in the vertex shader.

If you want to optimize that GS code I believe you shouldn't need to calculate each point so many times - you can cache them in an array. Using sincos() might speed it up a bit too.
If you want to optimize that GS code I believe you shouldn't need to calculate each point so many times - you can cache them in an array.

How can I cache them in an array? I would need to create a dynamic array for doing that and that's not possible in HLSL. Or do I miss something?
With the max vertex count at 128 you can make the array that size too.

If you run into an array size limit you can always do multiple iterations with one section of the cylinder per iteration.

This topic is closed to new replies.

Advertisement