Subdividing Triangles with the Geometry Shader

Started by
1 comment, last by ~Helgon 11 years, 4 months ago
Hi, I've tried to divide a Triangle into more Triangles and in the end it works but some of the new vertices seems at the wrong position but the computation is correct. Maybe u guys know where's the problem

Just 3 Vertices which perform a Triangle ( full file: https://www.dropbox.com/s/6qzdyid1gcdg7co/GeometryShaderExersise.cpp)


std::vector<Vertex::Geo> v(count);
v[0].Pos = XMFLOAT3(0.0f, 0.0f, 0.0f);
v[0].Normal = XMFLOAT3(1.0f, 1.0f, 1.0f);
v[0].Tex = XMFLOAT2(0.0f, 1.0f);
v[1].Pos = XMFLOAT3(1.0f, 2.0f, 0.0f);
v[1].Normal = XMFLOAT3(1.0f, 1.0f, 1.0f);
v[1].Tex = XMFLOAT2(0.0f, 0.0f);
v[2].Pos = XMFLOAT3(2.0f, 0.0f, 0.0f);
v[2].Normal = XMFLOAT3(1.0f, 1.0f, 1.0f);
v[2].Tex = XMFLOAT2(1.0f, 1.0f);
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(Vertex::Geo) * count;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &v[0];
HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &itemVB));
UINT indices[] =
{
0, 1, 2
};


And here the .FX file ( full file: https://www.dropbox.com/s/tw1sesf55rp60yp/Geometry.fx)


struct VertexIn
{
float3 PosL : POSITION;
float3 NormalL : NORMAL;
float2 Tex : TEXCOORD;
};
struct VertexOut
{
float3 PosL : POSITION;
float3 NormalL : NORMAL;
float2 Tex : TEXCOORD;
};
struct GeoOut
{
float4 PosH : SV_POSITION;
float3 PosW : POSITION;
float3 NormalW : NORMAL;
float2 Tex : TEXCOORD;
};
Texture2D gDiffuseMap;
VertexOut VS(VertexIn vin)
{
VertexOut vout;
vout = vin;

// Output vertex attributes for interpolation across triangle.
//vout.Tex = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy;
return vout;
}
void Subdivide(VertexOut inVerts[3], out VertexOut outVerts[6])
{
// 1
// *
// / \
// / \
// m0*-----*m1
// / \ / \
// / \ / \
// *-----*-----*
// 0 m2 2
VertexOut m[3];
// compute edge midpoints
m[0].PosL = 0.5f * (inVerts[0].PosL + inVerts[1].PosL);
m[1].PosL = 0.5f * (inVerts[1].PosL + inVerts[2].PosL);
m[2].PosL = 0.5f * (inVerts[2].PosL + inVerts[0].PosL);
// project onto unti spehre
m[0].PosL = normalize(m[0].PosL);
m[1].PosL = normalize(m[1].PosL);
m[2].PosL = normalize(m[2].PosL);
// derive normals
m[0].NormalL = m[0].PosL;
m[1].NormalL = m[1].PosL;
m[2].NormalL = m[2].PosL;
// interpolate texture coordinates
m[0].Tex = 0.5f * (inVerts[0].Tex + inVerts[1].Tex);
m[1].Tex = 0.5f * (inVerts[1].Tex + inVerts[2].Tex);
m[2].Tex = 0.5f * (inVerts[2].Tex + inVerts[0].Tex);
outVerts[0] = inVerts[0];
outVerts[1] = m[0];
outVerts[2] = m[2];
outVerts[3] = m[1];
outVerts[4] = inVerts[2];
outVerts[5] = inVerts[1];
}
void OutputSubdivision(VertexOut v[6], inout TriangleStream<GeoOut> stream)
{
GeoOut gout[6];
[unroll]
for(int i = 0; i < 6; ++i)
{
// Transform to World Space
gout.PosW = mul(float4(v.PosL, 1.0f), gWorld).xyz;
gout.NormalW = mul(v.NormalL, (float3x3)gWorldInvTranspose);
// Transform to homogeneous clip space
gout.PosH = mul(float4(v.PosL, 1.0f), gWorldViewProj);

gout.Tex = v.Tex;
}
// 1
// *
// / \
// / \
// m0*-----*m1
// / \ / \
// / \ / \
// *-----*-----*
// 0 m2 2
// We can draw the subdivision in two strips:
// strip 1: bottom three triangles
// strip 2: top triangle
[unroll]
for(int j = 0; j < 5; ++j)
{
stream.Append(gout[j]);
}
stream.RestartStrip();
stream.Append(gout[1]);
stream.Append(gout[5]);
stream.Append(gout[3]);
}
[maxvertexcount(8)]
void GS(triangle VertexOut gin[3], inout TriangleStream<GeoOut> stream)
{
VertexOut v[6];
Subdivide(gin, v);
OutputSubdivision(v, stream);
}

float4 PS(GeoOut pin,


I hope that some one knows whats wrong. I think the calculation is right, but then i dont know why the vertices are positioned that strange

Regards Helgon

from time to time i find time

Advertisement
I've realized that my Vertex Positions just were wrong. Now the triangle is subdivided correctly

[attachment=12542:stupid.jpg]

But if i try to "tesselate" a normal box with the geometry shader it totally crushes the objects geometry.
Independent if its a Box, a GeoSpehre or a Cylinder.

Just as example to see what happens with a box

[attachment=12543:wrong.jpg]

Does someone has an idea whats wrong? It's strange because with a simple triangle it seems to work



Regards Helgon

from time to time i find time

Just if someone else ever has this problem

In the previous solution i normalized the new vertices after computing them.

Right is it to also normalize the vertices you are calculating with

And it seems that it only works correct for spheres (GeoSpheres not included)


inVerts[0].PosL = normalize(inVerts[0].PosL);
inVerts[1].PosL = normalize(inVerts[1].PosL);
inVerts[2].PosL = normalize(inVerts[2].PosL);
// compute edge midpoints
m[0].PosL = 0.5f * (inVerts[0].PosL + inVerts[1].PosL);
m[1].PosL = 0.5f * (inVerts[1].PosL + inVerts[2].PosL);
m[2].PosL = 0.5f * (inVerts[2].PosL + inVerts[0].PosL);
m[0].PosL = normalize(m[0].PosL);
m[1].PosL = normalize(m[1].PosL);
m[2].PosL = normalize(m[2].PosL);

from time to time i find time

This topic is closed to new replies.

Advertisement