Jump to content

  • Log In with Google      Sign In   
  • 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!

[attachment=15126:Bad Normals5.jpg]

 

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.

[attachment=15126:Bad Normals5.jpg]

 

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