How do I convert such technique (from nVidia InstancedTesselation sample) to plain HLSL + DirectX 11 C++ code?
float4 PreprocessedLoDVS( uint id : SV_InstanceID, uniform int method) : LODS
{
float4 tessLevel;
if (method == 1) //Gregory
{
float3 positionControlPoints[20];
// 8 9 10 11
// 12 0\1 2/3 13
// 14 4/5 6\7 15
// 16 17 18 19
LoadGregoryPositionControlPoints(id, positionControlPoints);
tessLevel.x = evaluateEdgeLoD(positionControlPoints[16], positionControlPoints[14], positionControlPoints[12], positionControlPoints[8]);
tessLevel.y = evaluateEdgeLoD(positionControlPoints[19], positionControlPoints[15], positionControlPoints[13], positionControlPoints[11]);
tessLevel.z = evaluateEdgeLoD(positionControlPoints[16], positionControlPoints[17], positionControlPoints[18], positionControlPoints[19]);
tessLevel.w = evaluateEdgeLoD(positionControlPoints[8], positionControlPoints[9], positionControlPoints[10], positionControlPoints[11]);
}
else if (method == 0) { //Regular
float3 positionControlPoints[16];
// 0 1 2 3
// 4 5 6 7
// 8 9 10 11
// 12 13 14 15
LoadRegularControlPoints(id, positionControlPoints);
tessLevel.x = evaluateEdgeLoD(positionControlPoints[ 0], positionControlPoints[ 4], positionControlPoints[ 8], positionControlPoints[12]);
tessLevel.y = evaluateEdgeLoD(positionControlPoints[ 3], positionControlPoints[ 7], positionControlPoints[11], positionControlPoints[15]);
tessLevel.w = evaluateEdgeLoD(positionControlPoints[ 0], positionControlPoints[ 1], positionControlPoints[ 2], positionControlPoints[ 3]);
tessLevel.z = evaluateEdgeLoD(positionControlPoints[12], positionControlPoints[13], positionControlPoints[14], positionControlPoints[15]);
}
else if (method == 2) { //Bezier
float3 positionControlPoints[16];
// 0 1 2 3
// 4 5 6 7
// 8 9 10 11
// 12 13 14 15
LoadBezierPositionControlPoints(id, positionControlPoints);
tessLevel.x = evaluateEdgeLoD(positionControlPoints[ 0], positionControlPoints[ 4], positionControlPoints[ 8], positionControlPoints[12]);
tessLevel.y = evaluateEdgeLoD(positionControlPoints[ 3], positionControlPoints[ 7], positionControlPoints[11], positionControlPoints[15]);
tessLevel.z = evaluateEdgeLoD(positionControlPoints[12], positionControlPoints[13], positionControlPoints[14], positionControlPoints[15]);
tessLevel.w = evaluateEdgeLoD(positionControlPoints[ 0], positionControlPoints[ 1], positionControlPoints[ 2], positionControlPoints[ 3]);
}
else if (method == 3) { //Pm
// 18 14 13 12
// 19 8
// 20 7
// 0 1 2 6
float3 positionControlPoints[24];
LoadPmControlPoints(id, positionControlPoints);
tessLevel.x = evaluateEdgeLoD(positionControlPoints[ 0], positionControlPoints[20], positionControlPoints[19], positionControlPoints[18]);
tessLevel.y = evaluateEdgeLoD(positionControlPoints[ 6], positionControlPoints[ 7], positionControlPoints[ 8], positionControlPoints[12]);
tessLevel.z = evaluateEdgeLoD(positionControlPoints[18], positionControlPoints[14], positionControlPoints[13], positionControlPoints[12]);
tessLevel.w = evaluateEdgeLoD(positionControlPoints[ 0], positionControlPoints[ 1], positionControlPoints[ 2], positionControlPoints[ 6]);
}
else {
tessLevel=float4(2,2,2,2);
}
return tessLevel;
}
technique10 LoDRegularTechnique
{
pass P0
{
SetDepthStencilState( DisableDepthWrites, 0 );
SetVertexShader( CompileShader( vs_4_0, PreprocessedLoDVS(0) ) );
SetGeometryShader( ConstructGSWithSO( CompileShader( vs_4_0, PreprocessedLoDVS(0) ), "LODS.xyzw" ) );
SetPixelShader( NULL );
}
}
PreprocessedLoDVS looks like usual vertex shader, except “LODS” signature, and what about geometry shader?
This link explains it pretty nicely, but basically to summarize.
Compile your shader to blob, using PreprocessedLoDVS and vs_4_0 as profile
Create an Stream output layout, which is an array of D3D11_SO_DECLARATION_ENTRY , that will be LODS semantic with 4 components.
Create your vertex shader using CreateGeometryShaderWithStreamOut
Create a buffer with D3D11_BIND_STREAM_OUTPUT flag (same as you would create any other buffer, from that sample you will need also Shader Resource Flag, since you will need SRV to bind back as Buffer input).
Bind this buffer to stream output (using SOSetTargets)
Set your Vertex Shader to the pipeline and do your draw call.