I've been implementing Tessellation into my DX11/C++ game engine and I can't seem to get it working. I've cross checked my shaders with almost every example I've found and they look ok. Running my engine in the Visual Studio Graphics Analyzer shows me that there is something a miss:
My Vertex, Hull and Domain shaders are extremely simple:
Vertex Shader:
struct VertexShaderInput
{
float3 Position : SV_POSITION;
float2 UV : TEXCOORD;
float3 Normal : NORMAL;
float3 Tangent : TANGENT;
float3 Binormal : BINORMAL;
};
struct HullInputType
{
float4 Position : SV_POSITION;
float2 UV : TEXCOORD0;
float3 Normal : TEXCOORD1;
float3 Tangent : TANGENT;
float3 Binormal : BINORMAL;
};
HullInputType main(VertexShaderInput input)
{
HullInputType output = (HullInputType)0;
output.Position = float4(input.Position, 1.0);
return output;
}
Hull Shader:
struct VertexShaderOutput
{
float4 Position : SV_POSITION;
float2 UV : TEXCOORD0;
float3 Normal : TEXCOORD1;
float3 Tangent : TANGENT;
float3 Binormal : BINORMAL;
};
struct HullOutputType
{
float4 Position : SV_POSITION;
float2 UV : TEXCOORD0;
float3 Normal : TEXCOORD1;
float3 Tangent : TANGENT;
float3 Binormal : BINORMAL;
};
struct ConstantOutputType
{
float edges[4] : SV_TessFactor;
float inside[2] : SV_InsideTessFactor;
};
[domain("quad")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(4)]
[patchconstantfunc("ConstantHS")]
[maxtessfactor(64.0)]
HullOutputType hullShader(InputPatch<VertexShaderOutput, 4> inputPatch, uint controlPointID : SV_OutputControlPointID, uint PatchID : SV_PrimitiveID)
{
HullOutputType output;
// Copy inputs to outputs
output.Position = inputPatch[controlPointID].Position;
output.UV = inputPatch[controlPointID].UV;
output.Normal = inputPatch[controlPointID].Normal;
output.Tangent = inputPatch[controlPointID].Tangent;
output.Binormal = inputPatch[controlPointID].Binormal;
return output;
}
ConstantOutputType ConstantHS(InputPatch<VertexShaderOutput, 4> inputPatch, uint patchID : SV_PrimitiveID)
{
ConstantOutputType output;
float density = 4.0f;
output.edges[0] = density;
output.edges[1] = density;
output.edges[2] = density;
output.edges[3] = density;
output.inside[0] = density;
output.inside[1] = density;
return output;
}
Domain Shader:
// the object buffer is updated for each draw call
cbuffer ObjectBuffer : register(b0)
{
row_major matrix gWMatrix;
};
// the frame buffer is updated once per frame
cbuffer FrameBuffer : register(b1)
{
row_major matrix gVPMatrix;
};
struct ConstantOutputType
{
float edges[4] : SV_TessFactor;
float inside[2] : SV_InsideTessFactor;
};
struct HullOutputType
{
float4 Position : SV_POSITION;
float2 UV : TEXCOORD0;
float3 Normal : TEXCOORD1;
float3 Tangent : TANGENT;
float3 Binormal : BINORMAL;
};
struct PixelInputType
{
float4 Position : SV_POSITION;
float2 UV : TEXCOORD0;
float3 Normal : TEXCOORD1;
float3 Tangent : TANGENT;
float3 Binormal : BINORMAL;
};
[domain("quad")]
PixelInputType domainShader(ConstantOutputType input, float2 domain : SV_DomainLocation, const OutputPatch<HullOutputType, 4> patch)
{
PixelInputType output;
// Determine the position of the new vertex.
float3 worldPosition = lerp(
lerp(patch[0].Position, patch[1].Position, domain.x),
lerp(patch[2].Position, patch[3].Position, domain.x),
domain.y);
worldPosition = mul(float4(worldPosition, 1.0), gWMatrix);
output.Position = mul(worldPosition, gVPMatrix);
// Send the input color into the pixel shader.
output.UV = patch[0].UV;
output.Normal = lerp(
lerp(patch[0].Normal, patch[1].Normal, domain.x),
lerp(patch[2].Normal, patch[3].Normal, domain.x),
domain.y);
output.Tangent = lerp(
lerp(patch[0].Tangent, patch[1].Tangent, domain.x),
lerp(patch[2].Tangent, patch[3].Tangent, domain.x),
domain.y);
output.Binormal = lerp(
lerp(patch[0].Binormal, patch[1].Binormal, domain.x),
lerp(patch[2].Binormal, patch[3].Binormal, domain.x),
domain.y);
return output;
}
My pixel shader is more complex, but everything works fine without the Hull and Domain shaders. I'm setting everything correctly, the input layouts are right, the topology is correct, all the buffers are set correctly, in DX Debug mode, no errors are returned but for some reason I can't see the rendered object (it's a simple flat quad).
The Input/Output in the vertex shader look correct to me - I've removed all the normal and tangent/binormal code for brevity. The Input/Output for the Hull shader only shows the input:
Has anyone seen this behaviour before in the Graphics Analyzer? Or any tips on what I may have missed on tessellation? Everything looks the same as Rastertek, apart from the fact that I'm using SV_POSITION all the way through the pipeline, they use POSITION.