# Subdivision of a triangle in HLSL

How can I subdivide a triangle more than once. I can not use recursion as directx 11 hlsl will not allow it. Are there any links to a HLSL code. This has to be done in the geometry shader as my book says.

my code that will subdivide once is:

  void Subdivide(VertexOut inVerts[3], out VertexOut outVerts[6])
{
//          1
//          *
//         / \
//        /   \
//     m0*-----*m1
//      / \   / \
//     /   \ /   \
//    *-----*-----*
//   0     m2     2

VertexOut m[3];

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);

// 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[i].PosW = mul(float4(v[i].PosL, 1.0f), gWorld).xyz;
gout[i].NormalW = mul(v[i].NormalL, (float3x3)gWorldInvTranspose);

// Transform to homogeneous clip space
gout[i].PosH = mul(float4(v[i].PosL, 1.0f), gWorldViewProj);

gout[i].Tex = v[i].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);
}


How can I subdivide twice or even three or four times. thx

• Out of interest, why would one subdivide a triangle in a shader? The normals etc. of the sub triangles remain the same as the source so I am wondering what the application of this technique would be. – Felsir Jan 4 '16 at 8:56

Although you can use the geometry shader to sub-divide primitives, I would suggest looking into tessellation. It is a new feature that has been added in DirectX 11, which allows you to sub-divide low level primitives into high-detailed primitives. This feature is highly optimized to do the exact thing you are describing. See the image below for an example.

Without going into too much detail, the tessellation pipeline consists of three new stages: hull shader, fixed-function tessellator and domain shader. Simply put, the hull shader defines the positions of new points inside original primitive, which are passed to the fixed-function tessellator stage. The domain shader runs on the output of the tessellator. You can think of the domain shader as a replacement of the vertex shader of sorts, as stuff that you would normally put in the vertex shader are now placed in the domain shader.

To get any more information I would suggest to look for documentation and tutorials (like this one, for example)

I found a post on a different site:
http://www.gamedev.net/topic/635147-subdividing-triangles-with-the-geometry-shader/ Try to use their code, and correct the Vertex Positions

Edit:In response to DMGregory's comment, I am implementing some additions ;)

Try creating a method that implements a barycentric function, and use the generated coords to create 3 triangle. I have an example : You should generate this: .] Use the coordinates of the line segments that form 3 equal triangles

I have a bit of code to generate a barrycentric function, but it is written in Java, so you may have to "Translate"

public static float barryCentric(Vector3f p1,Vector3f p2, Vector3f p3, Vector2f pos){
float det = (p2.z - p3.z) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.z - p3.z);
float eleven = ((p2.z - p3.z) * (pos.x - p3.x) + (p3.x - p2.x) * (pos.y - p3.z)) /det;
float tweleve = ((p3.z - p1.z) * (pos.x - p3.x) + (p1.x - p3.x) * (pos.y - p3.z)) /det;
float thirteen = 1.0f - eleven - tweleve;
return eleven * p1.y + tweleve * p2.y + thirteen * p3.y;
}

• This answer would be better if it summarized the main techniques demonstrated by the link, so that it can stand on its own if that forum thread ever becomes unavailable. – DMGregory Jan 3 '16 at 23:41