• Create Account

#Actualcephalo

Posted 19 April 2013 - 03:12 PM

Well, I tried something similar to PN-Triangles, in that I am interpolating normals from the edge, and here is the result. It's sort of continuous across triangles, but not very well defined like the above example. I may get better results if I increase the order of control points to interpolate, but then we are getting into slow territory. It's a tough problem!

Here is my new hull shader and domain shader. In the hull shader I am using de Casteljau's on the curve made by the edge in order to get the n110, n011 and n101 normals for interpolation. This is a bit different than with standard PN-Triangles:

#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 n200 0
#define n020 1
#define n002 2
#define n110 3
#define n011 4
#define n101 5

struct VertexOutput
{
float3 PositionWorld	: POSITION;
float2 MainTexCoord		: TEXCOORD;
};

struct PatchConstants
{
float EdgeTess[3]	: SV_TessFactor;
float InsideTess	: SV_InsideTessFactor;

float3 NormalCP[6]	: NORMAL;
};

PatchConstants PatchHS(InputPatch<VertexOutput,10> cp, uint patchID : SV_PrimitiveID)
{
PatchConstants pt;

pt.EdgeTess[0] = 12;
pt.EdgeTess[1] = 12;
pt.EdgeTess[2] = 12;
pt.InsideTess = 12;

pt.NormalCP[n200] = float3(0,1,0);
pt.NormalCP[n020] = float3(0,1,0);
pt.NormalCP[n002] = float3(0,1,0);

float t = 0.5f;
float3 bitangent;

float3 p1_0 = (1.0f - t) * cp[p300].PositionWorld + t * cp[p210].PositionWorld;
float3 p1_1 = (1.0f - t) * cp[p210].PositionWorld + t * cp[p120].PositionWorld;
float3 p1_2 = (1.0f - t) * cp[p120].PositionWorld + t * cp[p030].PositionWorld;

float3 p2_0 = (1.0f - t) * p1_0 + t * p1_1;
float3 p2_1 = (1.0f - t) * p1_1 + t * p1_2;

float3 tangent = normalize(p2_1 - p2_0);
float3 offline = normalize(cp[p030].PositionWorld - cp[p300].PositionWorld);
if(cp[p030].PositionWorld.y > cp[p300].PositionWorld.y)
{
bitangent = normalize(cross(offline,tangent));
}
else
{
bitangent = normalize(cross(tangent,offline));
}
pt.NormalCP[n110] = normalize(cross(bitangent, tangent));

p1_0 = (1.0f - t) * cp[p030].PositionWorld + t * cp[p021].PositionWorld;
p1_1 = (1.0f - t) * cp[p021].PositionWorld + t * cp[p012].PositionWorld;
p1_2 = (1.0f - t) * cp[p012].PositionWorld + t * cp[p003].PositionWorld;

p2_0 = (1.0f - t) * p1_0 + t * p1_1;
p2_1 = (1.0f - t) * p1_1 + t * p1_2;

tangent = normalize(p2_1 - p2_0);
offline = normalize(cp[p003].PositionWorld - cp[p030].PositionWorld);
if(cp[p003].PositionWorld.y > cp[p030].PositionWorld.y)
{
bitangent = normalize(cross(offline,tangent));
}
else
{
bitangent = normalize(cross(tangent,offline));
}
pt.NormalCP[n011] = normalize(cross(bitangent, tangent));

p1_0 = (1.0f - t) * cp[p003].PositionWorld + t * cp[p102].PositionWorld;
p1_1 = (1.0f - t) * cp[p102].PositionWorld + t * cp[p201].PositionWorld;
p1_2 = (1.0f - t) * cp[p201].PositionWorld + t * cp[p300].PositionWorld;

p2_0 = (1.0f - t) * p1_0 + t * p1_1;
p2_1 = (1.0f - t) * p1_1 + t * p1_2;

tangent = normalize(p2_1 - p2_0);
offline = normalize(cp[p300].PositionWorld - cp[p003].PositionWorld);
if(cp[p300].PositionWorld.y > cp[p003].PositionWorld.y)
{
bitangent = normalize(cross(offline,tangent));
}
else
{
bitangent = normalize(cross(tangent,offline));
}
pt.NormalCP[n101] = normalize(cross(bitangent, tangent));

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[i];

return hout;
}


And here is the interpolation in the domain shader:

#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 n200 0
#define n020 1
#define n002 2
#define n110 3
#define n011 4
#define n101 5

#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 PatchConstants
{
float EdgeTess[3]	: SV_TessFactor;
float InsideTess	: SV_InsideTessFactor;

float3 NormalCP[6]	: NORMAL;
};

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(PatchConstants pc, float3 bary : SV_DomainLocation, const OutputPatch<HullOut,10> cp)
{
DomainOut dout;

float3 p1_200 = U * cp[p300].PositionWorld + V * cp[p210].PositionWorld + W * cp[p201].PositionWorld;
float3 p1_110 = U * cp[p210].PositionWorld + V * cp[p120].PositionWorld + W * cp[p111].PositionWorld;
float3 p1_101 = U * cp[p201].PositionWorld + V * cp[p111].PositionWorld + W * cp[p102].PositionWorld;
float3 p1_020 = U * cp[p120].PositionWorld + V * cp[p030].PositionWorld + W * cp[p021].PositionWorld;
float3 p1_011 = U * cp[p111].PositionWorld + V * cp[p021].PositionWorld + W * cp[p012].PositionWorld;
float3 p1_002 = U * cp[p102].PositionWorld + V * cp[p012].PositionWorld + W * cp[p003].PositionWorld;

float3 p2_100 = U * p1_200 + V * p1_110 + W * p1_101;
float3 p2_010 = U * p1_110 + V * p1_020 + W * p1_011;
float3 p2_001 = U * p1_101 + V * p1_011 + W * p1_002;

float3 position = U * p2_100 + V * p2_010 + W * p2_001;

//float3 tangent = p2_010 - p2_100;
//float3 bitangent = p2_001 - p2_100;

//tangent = normalize(tangent);
//bitangent = normalize(bitangent);
float3 normal = pow(U,2) * pc.NormalCP[n200] +
pow(V,2) * pc.NormalCP[n020] +
pow(W,2) * pc.NormalCP[n002] +
U * V * pc.NormalCP[n110] +
U * W * pc.NormalCP[n101] +
V * W * pc.NormalCP[n011];

dout.View = vecEye.xyz - position.xyz;
dout.PositionH = mul(float4(position,1.0f),ViewProjection);
dout.Normal = normalize(normal);
dout.Tangent = float3(0,1,0);
dout.Bitangent = float3(0,1,0);

dout.MainTexCoord = cp[p300].MainTexCoord * U + cp[p030].MainTexCoord * V + cp[p003].MainTexCoord * W;

return dout;
}


#1cephalo

Posted 19 April 2013 - 03:11 PM

Well, I tried something similar to PN-Triangles, in that I am interpolating normals from the edge, and here is the result. It's sort of continuous across triangles, but not very well defined like the above example. I may get better results if I increase the order of control points to interpolate, but then we are getting into slow territory.

Here is my new hull shader and domain shader. In the hull shader I am using de Casteljau's on the curve made by the edge in order to get the n110, n011 and n101 normals for interpolation. This is a bit different than with standard PN-Triangles:

#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 n200 0
#define n020 1
#define n002 2
#define n110 3
#define n011 4
#define n101 5

struct VertexOutput
{
float3 PositionWorld	: POSITION;
float2 MainTexCoord		: TEXCOORD;
};

struct PatchConstants
{
float EdgeTess[3]	: SV_TessFactor;
float InsideTess	: SV_InsideTessFactor;

float3 NormalCP[6]	: NORMAL;
};

PatchConstants PatchHS(InputPatch<VertexOutput,10> cp, uint patchID : SV_PrimitiveID)
{
PatchConstants pt;

pt.EdgeTess[0] = 12;
pt.EdgeTess[1] = 12;
pt.EdgeTess[2] = 12;
pt.InsideTess = 12;

pt.NormalCP[n200] = float3(0,1,0);
pt.NormalCP[n020] = float3(0,1,0);
pt.NormalCP[n002] = float3(0,1,0);

float t = 0.5f;
float3 bitangent;

float3 p1_0 = (1.0f - t) * cp[p300].PositionWorld + t * cp[p210].PositionWorld;
float3 p1_1 = (1.0f - t) * cp[p210].PositionWorld + t * cp[p120].PositionWorld;
float3 p1_2 = (1.0f - t) * cp[p120].PositionWorld + t * cp[p030].PositionWorld;

float3 p2_0 = (1.0f - t) * p1_0 + t * p1_1;
float3 p2_1 = (1.0f - t) * p1_1 + t * p1_2;

float3 tangent = normalize(p2_1 - p2_0);
float3 offline = normalize(cp[p030].PositionWorld - cp[p300].PositionWorld);
if(cp[p030].PositionWorld.y > cp[p300].PositionWorld.y)
{
bitangent = normalize(cross(offline,tangent));
}
else
{
bitangent = normalize(cross(tangent,offline));
}
pt.NormalCP[n110] = normalize(cross(bitangent, tangent));

p1_0 = (1.0f - t) * cp[p030].PositionWorld + t * cp[p021].PositionWorld;
p1_1 = (1.0f - t) * cp[p021].PositionWorld + t * cp[p012].PositionWorld;
p1_2 = (1.0f - t) * cp[p012].PositionWorld + t * cp[p003].PositionWorld;

p2_0 = (1.0f - t) * p1_0 + t * p1_1;
p2_1 = (1.0f - t) * p1_1 + t * p1_2;

tangent = normalize(p2_1 - p2_0);
offline = normalize(cp[p003].PositionWorld - cp[p030].PositionWorld);
if(cp[p003].PositionWorld.y > cp[p030].PositionWorld.y)
{
bitangent = normalize(cross(offline,tangent));
}
else
{
bitangent = normalize(cross(tangent,offline));
}
pt.NormalCP[n011] = normalize(cross(bitangent, tangent));

p1_0 = (1.0f - t) * cp[p003].PositionWorld + t * cp[p102].PositionWorld;
p1_1 = (1.0f - t) * cp[p102].PositionWorld + t * cp[p201].PositionWorld;
p1_2 = (1.0f - t) * cp[p201].PositionWorld + t * cp[p300].PositionWorld;

p2_0 = (1.0f - t) * p1_0 + t * p1_1;
p2_1 = (1.0f - t) * p1_1 + t * p1_2;

tangent = normalize(p2_1 - p2_0);
offline = normalize(cp[p300].PositionWorld - cp[p003].PositionWorld);
if(cp[p300].PositionWorld.y > cp[p003].PositionWorld.y)
{
bitangent = normalize(cross(offline,tangent));
}
else
{
bitangent = normalize(cross(tangent,offline));
}
pt.NormalCP[n101] = normalize(cross(bitangent, tangent));

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[i];

return hout;
}


And here is the interpolation in the domain shader:

#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 n200 0
#define n020 1
#define n002 2
#define n110 3
#define n011 4
#define n101 5

#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 PatchConstants
{
float EdgeTess[3]	: SV_TessFactor;
float InsideTess	: SV_InsideTessFactor;

float3 NormalCP[6]	: NORMAL;
};

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(PatchConstants pc, float3 bary : SV_DomainLocation, const OutputPatch<HullOut,10> cp)
{
DomainOut dout;

float3 p1_200 = U * cp[p300].PositionWorld + V * cp[p210].PositionWorld + W * cp[p201].PositionWorld;
float3 p1_110 = U * cp[p210].PositionWorld + V * cp[p120].PositionWorld + W * cp[p111].PositionWorld;
float3 p1_101 = U * cp[p201].PositionWorld + V * cp[p111].PositionWorld + W * cp[p102].PositionWorld;
float3 p1_020 = U * cp[p120].PositionWorld + V * cp[p030].PositionWorld + W * cp[p021].PositionWorld;
float3 p1_011 = U * cp[p111].PositionWorld + V * cp[p021].PositionWorld + W * cp[p012].PositionWorld;
float3 p1_002 = U * cp[p102].PositionWorld + V * cp[p012].PositionWorld + W * cp[p003].PositionWorld;

float3 p2_100 = U * p1_200 + V * p1_110 + W * p1_101;
float3 p2_010 = U * p1_110 + V * p1_020 + W * p1_011;
float3 p2_001 = U * p1_101 + V * p1_011 + W * p1_002;

float3 position = U * p2_100 + V * p2_010 + W * p2_001;

//float3 tangent = p2_010 - p2_100;
//float3 bitangent = p2_001 - p2_100;

//tangent = normalize(tangent);
//bitangent = normalize(bitangent);
float3 normal = pow(U,2) * pc.NormalCP[n200] +
pow(V,2) * pc.NormalCP[n020] +
pow(W,2) * pc.NormalCP[n002] +
U * V * pc.NormalCP[n110] +
U * W * pc.NormalCP[n101] +
V * W * pc.NormalCP[n011];

dout.View = vecEye.xyz - position.xyz;
dout.PositionH = mul(float4(position,1.0f),ViewProjection);
dout.Normal = normalize(normal);
dout.Tangent = float3(0,1,0);
dout.Bitangent = float3(0,1,0);

dout.MainTexCoord = cp[p300].MainTexCoord * U + cp[p030].MainTexCoord * V + cp[p003].MainTexCoord * W;

return dout;
}


PARTNERS