Ok, I believe that I am using the right blend state, and I believe that my ProjectionView matrix is ok, and I've eliminated relevant DX11 warnings and errors, but I still can't get anything to appear on screen. I'm greatly hampered by the fact that there is no way to debug my tessellation shaders with SharpDX and VS2012 express. This is my first stab at tessellation so I probably am doing something obviously wrong, so I would like to post my shaders to see if anything jumps out at anyone. What I am trying to do is draw instanced 3rd order bezier triangles. Besides the above, what other things might I check when nothing is drawn?
Here is the VS:
cbuffer PerFrameBuffer : register(b0)
{
//float4x4 World; This is just the identity matrix, so not needed
float4x4 ViewProjection;
float4 vecEye;
float4 LightDirection;
float4 LightColor;
};
struct VertexInput
{
//imediate data
float3 PositionLocal : POSITION0;
int index : BLENDINDICES;
//instance data
float3 Translation : POSITION1;
float Altitudes[4] : PSIZE;
};
struct VertexOutput
{
float3 PositionWorld : POSITION;
float2 MainTexCoord : TEXCOORD;
};
VertexOutput VS(VertexInput vin)
{
VertexOutput vout;
//Add altitudes
float3 transPos = vin.PositionLocal + vin.Translation;
transPos.y += vin.Altitudes[vin.index];
vout.MainTexCoord = transPos.xz;
vout.PositionWorld = transPos;
return vout;
}
Here is the pass thru Hull shader:
struct VertexOutput
{
float3 PositionWorld : POSITION;
float2 MainTexCoord : TEXCOORD;
};
struct PatchTess
{
float EdgeTess[3] : SV_TessFactor;
float InsideTess : SV_InsideTessFactor;
};
PatchTess PatchHS(InputPatch<VertexOutput,10> patch, uint patchID : SV_PrimitiveID)
{
PatchTess pt;
pt.EdgeTess[0] = 6;
pt.EdgeTess[1] = 6;
pt.EdgeTess[2] = 6;
pt.InsideTess = 6;
return pt;
}
struct HullOut
{
float3 PositionWorld : POSITION;
float2 MainTexCoord : TEXCOORD;
};
[domain("tri")]
[partitioning("fractional_even")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(10)]
[patchconstantfunc("PatchHS")]
HullOut HS(InputPatch<VertexOutput,10> p, uint i : SV_OutputControlPointID, uint patchId : SV_PrimitiveID)
{
HullOut hout;
hout = p;
return hout;
}
Here is the domain shader, where the meat of the intended operation is. The math here might be wrong, but should still produce visible geometry:
#define p300 0
#define p030 1
#define p003 2
#define p210 3
#define p201 4
#define p120 5
#define p021 6
#define p012 7
#define p102 8
#define p111 9
#define U bary.x
#define V bary.y
#define W bary.z
cbuffer PerFrameBuffer : register(b0)
{
//float4x4 World; This is just the identity matrix, so not needed
float4x4 ViewProjection;
float4 vecEye;
float4 LightDirection;
float4 LightColor;
};
struct PatchTess
{
float EdgeTess[3] : SV_TessFactor;
float InsideTess : SV_InsideTessFactor;
};
struct HullOut
{
float3 PositionWorld : POSITION;
float2 MainTexCoord : TEXCOORD;
};
struct DomainOut
{
float4 PositionH : SV_Position;
float3 Normal : NORMAL0;
float3 Tangent : TANGENT0;
float3 Bitangent : BITANGENT0;
float3 View : NORMAL1;
float2 MainTexCoord : TEXCOORD0;
};
[domain("tri")]
DomainOut DS(PatchTess patchTess, float3 bary : SV_DomainLocation, const OutputPatch<HullOut,10> cp)
{
DomainOut dout;
float3 position =
cp[p300].PositionWorld * pow(U,3) +
cp[p030].PositionWorld * pow(V,3) +
cp[p003].PositionWorld * pow(W,3) +
cp[p210].PositionWorld * 3 * pow(U,2) * V +
cp[p201].PositionWorld * 3 * pow(U,2) * W +
cp[p120].PositionWorld * 3 * U * pow(V,2) +
cp[p021].PositionWorld * 3 * pow(V,2) * W +
cp[p012].PositionWorld * 3 * V * pow(W,2) +
cp[p102].PositionWorld * 3 * U * pow(W,2) +
cp[p111].PositionWorld * 6 * U * V * W;
float3 tangent =
cp[p300].PositionWorld * pow(U,2) +
cp[p120].PositionWorld * pow(V,2) +
cp[p102].PositionWorld * pow(W,2) +
cp[p201].PositionWorld * 2 * U * W +
cp[p210].PositionWorld * 2 * U * V +
cp[p111].PositionWorld * 2 * V * W;
float3 bitangent =
cp[p030].PositionWorld * pow(V,2) +
cp[p012].PositionWorld * pow(W,2) +
cp[p210].PositionWorld * pow(U,2) +
cp[p120].PositionWorld * 2 * U * V +
cp[p021].PositionWorld * 2 * V * W +
cp[p111].PositionWorld * 2 * U * W;
tangent = normalize(tangent);
bitangent = normalize(bitangent);
float3 normal = normalize(cross(tangent,bitangent));
dout.View = vecEye.xyz - position.xyz;
dout.PositionH = mul(float4(position,1.0f),ViewProjection);
dout.Normal = normal;
dout.Tangent = tangent;
dout.Bitangent = bitangent;
dout.MainTexCoord = cp[p300].MainTexCoord * U + cp[p030].MainTexCoord * V + cp[p003].MainTexCoord * W;
return dout;
}
Last is the pixel shader, which has a simple shading algorithm that has been disabled to merely produce one color. I'm really hoping to see that color 'Reddish' but it's not happening:
cbuffer PerFrameBuffer : register(b0)
{
//float4x4 World; This is just the identity matrix, so not needed
float4x4 ViewProjection;
float4 vecEye;
float4 LightDirection;
float4 LightColor;
};
struct DomainOut
{
float4 PositionH : SV_Position;
float3 Normal : NORMAL0;
float3 Tangent : TANGENT0;
float3 Bitangent : BITANGENT0;
float3 View : NORMAL1;
float2 MainTexCoord : TEXCOORD0;
};
float4 PS(DomainOut input) : SV_Target
{
float4 Color = float4 (0, 0, 0, 1);
float4 Reddish = float4 (0.8,0.5,0.8,1.0);
float4 specularColor = float4(1,1,1,1);
float4 diffuse = {LightColor.rgb, 1.0f};
float4 ambient = { 0.03f, 0.03f, 0.03f, 1.0f};
float3 LightDir = normalize(LightDirection.xyz);
float3 ViewDir = normalize(input.View);
float4 diff = saturate(dot(input.Normal, LightDir)); // diffuse component
// R = 2 * (N.L) * N - L
float3 Reflect = normalize(2 * diff * input.Normal - LightDir);
float specular = pow(saturate(dot(Reflect, ViewDir)), 15); // R.V^n
// I = Acolor + Dcolor * N.L + (R.V)n
Color += ambient + diffuse * diff + specular * (specularColor * LightColor);
float4 Final = Color * Reddish;
Final.a = 1.0;
//return Final;
return Reddish;
}