Distance in HLSL problem

Started by
2 comments, last by terryeverlast 8 years, 3 months ago

I subdivided some spheres. With distance they change. In between the changes, i see glitchs and holes in the sphere like,

6ycbqb.png

Here is my distance function


float distance(VertexOut gin[1])
	{
	GeoOut pin;
	
	float4x4 gWorlds;
?	?//identity matrix
	gWorlds[0][0] = 1;gWorlds[0][1] = 0;gWorlds[0][2] = 0;gWorlds[0][3] = 0;gWorlds[1][0] = 0;gWorlds[1][1]= 1;gWorlds[1][2] = 0;gWorlds[1][3] = 0;
	gWorlds[2][0] = 0;gWorlds[2][1] = 0;gWorlds[2][2] = 1;gWorlds[2][3] = 0;gWorlds[3][0] = 0;gWorlds[3][1] = 0;gWorlds[3][2] = 0;gWorlds[3][3] = 0;

		// Transform to World Space
		pin.PosW = mul(float4(gin[0].PosL, 1.0f),  gWorlds).xyz;
	
	// The toEye vector is used in lighting.
	float3 toEye = gEyePosW - pin.PosW; 
	// Cache the distance to the eye from this surface point.
	float distToEye = length(toEye);


	return distToEye;
	}

And


[maxvertexcount(50)]
void GS(triangle VertexOut gin[3], inout TriangleStream<GeoOut> stream)
{	


if(distance(gin[0]) < 10.0f)
{
VertexOut v[15];
Subdivide2(gin, v);
OutputSubdivision2(v,stream);

}
else if(distance(gin[0]) >= 10.0f)
{
VertexOut v[6];
Subdivide(gin, v);
OutputSubdivision(v,stream);
  
}
}
Advertisement
I bet the problem is that different triangles will have different distances, so they may not fit right. Why don't you try to make a single distance parameter per mesh? Wouldn't that make more sense?

PS: Also, use tessellation. Geometry shaders aren't as efficient.

Ive been trying all sorts of stuff for 2 days and i still cant figure this out. Need some help.

Here is my shader code.


cbuffer cbPerFrame
{
	DirectionalLight gDirLights[3];
	float3 gEyePosW;

	float  gFogStart;
	float  gFogRange;
	float4 gFogColor;
};

cbuffer cbPerObject
{
	
	float4x4 gWorld;
	float4x4 gWorldInvTranspose;
	float4x4 gWorldViewProj;
	float4x4 gTexTransform;

	Material gMaterial;
}; 

struct VertexIn
{
	float3 PosL		  : POSITION;
	float3 NormalL	  : NORMAL;
	float2 Tex		  : TEXCOORD;
};

struct VertexOut
{
    float3 PosL		: POSITION;
    float3 NormalL	: NORMAL;
	float2 Tex		: TEXCOORD;
};

struct GeoOut
{
	float4 PosH		: SV_POSITION;
    float3 PosW		: POSITION;
    float3 NormalW	: NORMAL;
	
};


SamplerState samAnisotropic
{
	Filter = ANISOTROPIC;
	MaxAnisotropy = 4;

	AddressU = WRAP;
	AddressV = WRAP;
};

Texture2D gDiffuseMap;


VertexOut VS(VertexIn vin)
{
	VertexOut vout;

	
	// Transform to world space space.
	vout.PosL    = mul(float4(vin.PosL, 1.0f), gWorldInvTranspose).xyz;
	vout.NormalL = mul(vin.NormalL, (float3x3)gWorldInvTranspose);
	

	return vout;
}
	float distance(VertexOut gin)
	{
	GeoOut pin;
	
	
	
	float4x4 gWorlds;
	gWorlds[0][0] = 1;gWorlds[0][1] = 0;gWorlds[0][2] = 0;gWorlds[0][3] = 0;gWorlds[1][0] = 0;gWorlds[1][1]= 1;gWorlds[1][2] = 0;gWorlds[1][3] = 0;
	gWorlds[2][0] = 0;gWorlds[2][1] = 0;gWorlds[2][2] = 1;gWorlds[2][3] = 0;gWorlds[3][0] = 0;gWorlds[3][1] = 0;gWorlds[3][2] = 0;gWorlds[3][3] = 0;

		// Transform to World Space
		pin.PosW = mul(float4(gin.PosL, 1.0f),  gWorlds).xyz;
	
	
	


	// The toEye vector is used in lighting.
	float3 toEye = gEyePosW - pin.PosW; 
	// Cache the distance to the eye from this surface point.
	float distToEye = length(toEye);


	return distToEye;
	}

void Subdivide(VertexOut inVerts[3], out VertexOut outVerts[6])
{
	//			1
	//			*
	//		   / \
	//		  /   \
	//	   m0*-----*m1
	//	    / \	  /	\
	//     /   \ /   \
	//    *-----*-----*
	//   0     m2     2

	VertexOut m[3];


// compute edge midpoints
m[0].PosL = 0.5f * (inVerts[0].PosL + inVerts[1].PosL);
m[1].PosL = 0.5f * (inVerts[1].PosL + inVerts[2].PosL);
m[2].PosL = 0.5f * (inVerts[2].PosL + inVerts[0].PosL);
m[0].PosL = normalize(m[0].PosL);
m[1].PosL = normalize(m[1].PosL);
m[2].PosL = normalize(m[2].PosL);

	// derive normals
	m[0].NormalL = m[0].PosL;
	m[1].NormalL = m[1].PosL;
	m[2].NormalL = m[2].PosL;

	// interpolate texture coordinates
	
	outVerts[0] = inVerts[0];
	outVerts[1] = m[0];
	outVerts[2] = m[2];
	outVerts[3] = m[1];
	outVerts[4] = inVerts[2];
	outVerts[5] = inVerts[1];
}

void OutputSubdivision(VertexOut v[6], inout TriangleStream<GeoOut> stream)
{
	GeoOut gout[6];

	[unroll]
	for(int i = 0; i < 6; ++i)
	{
		// Transform to World Space
		gout[i].PosW = mul(float4(v[i].PosL, 1.0f), gWorld).xyz;
		gout[i].NormalW = mul(v[i].NormalL, (float3x3)gWorldInvTranspose);

		// Transform to homogeneous clip space
		gout[i].PosH = mul(float4(v[i].PosL, 1.0f), gWorldViewProj);
		
	}

	//			1
	//			*
	//		   / \
	//		  /   \
	//	   m0*-----*m1
	//	    / \	  /	\
	//     /   \ /   \
	//    *-----*-----*
	//   0     m2     2

	// We can draw the subdivision in two strips:
	// strip 1: bottom three triangles
	// strip 2: top triangle

	[unroll]
	for(int j = 0; j < 5; ++j)
	{
		stream.Append(gout[j]);
	}
	stream.RestartStrip();

	stream.Append(gout[1]);
	stream.Append(gout[5]);
	stream.Append(gout[3]);

		}



void Subdivide2(VertexIn inVerts[3], out VertexOut outVerts[15])
{
	//			1
	//			*
	//		   / \
	//		  /   \
	//	   m0*-----*m1
	//	    / \	  /	\
	//     /   \ /   \
	//    *-----*-----*
	//   0     m2     2

	VertexOut m[3];
	VertexOut n[15];


// compute edge midpoints
m[0].PosL = 0.5f * (inVerts[0].PosL + inVerts[1].PosL);
m[1].PosL = 0.5f * (inVerts[1].PosL + inVerts[2].PosL);
m[2].PosL = 0.5f * (inVerts[2].PosL + inVerts[0].PosL);
n[0].PosL = 0.5f * (inVerts[0].PosL + m[0].PosL); 
n[1].PosL = 0.5f * (inVerts[0].PosL + m[2].PosL); 
n[2].PosL = 0.5f * (m[0].PosL + m[2].PosL); 
n[3].PosL = m[2].PosL; 
n[4].PosL = 0.5f * (m[2].PosL + m[1].PosL); 
n[5].PosL = 0.5f * (inVerts[2].PosL + m[2].PosL); 
n[6].PosL = 0.5f * (inVerts[2].PosL + m[1].PosL); 
n[7].PosL = 0.5f * (m[0].PosL + m[1].PosL); 
n[8].PosL = 0.5f * (m[0].PosL + inVerts[1].PosL);
n[9].PosL = 0.5f * (m[1].PosL + inVerts[1].PosL); 


n[0].PosL = normalize(n[0].PosL);
n[1].PosL = normalize(n[1].PosL);
n[2].PosL = normalize(n[2].PosL);
n[3].PosL = normalize(n[3].PosL);
n[4].PosL = normalize(n[4].PosL);
n[5].PosL = normalize(n[5].PosL);
n[6].PosL = normalize(n[6].PosL);
n[7].PosL = normalize(n[7].PosL);
n[8].PosL = normalize(n[8].PosL);
n[9].PosL = normalize(n[9].PosL);

m[0].PosL = normalize(m[0].PosL);
m[1].PosL = normalize(m[1].PosL);
m[2].PosL = normalize(m[2].PosL);

	// derive normals
m[0].NormalL = m[0].PosL;
m[1].NormalL = m[1].PosL;
m[2].NormalL = m[2].PosL;
n[0].NormalL = n[0].PosL;
n[1].NormalL = n[1].PosL;
n[2].NormalL = n[2].PosL;
n[3].NormalL = n[3].PosL;
n[4].NormalL = n[4].PosL;
n[5].NormalL = n[5].PosL;
n[6].NormalL = n[6].PosL;
n[7].NormalL = n[7].PosL;
n[8].NormalL = n[8].PosL;
n[9].NormalL = n[9].PosL;

	

	outVerts[0] = inVerts[0];
	outVerts[1] = n[0]; 
	outVerts[2] = n[1]; 
	outVerts[3] = n[2]; 
	outVerts[4] = n[3]; 
	outVerts[5] = n[4]; 
	outVerts[6] = n[5]; 
	outVerts[7] = n[6]; 
	outVerts[8] = inVerts[2];
	outVerts[9] = m[0];
	outVerts[10] = n[7];
	outVerts[11] = m[1];
	outVerts[12] = n[8];
	outVerts[13] = n[9];
	outVerts[14] = inVerts[1];



	

}

void OutputSubdivision2(VertexOut v[15], inout TriangleStream<GeoOut> stream)
{
	GeoOut gout[15];

	[unroll]
	for(int i = 0; i < 15; ++i)
	{
		// Transform to World Space
		gout[i].PosW = mul(float4(v[i].PosL, 1.0f), gWorld).xyz;
		gout[i].NormalW = mul(v[i].NormalL, (float3x3)gWorldInvTranspose);

		// Transform to homogeneous clip space
		gout[i].PosH = mul(float4(v[i].PosL, 1.0f), gWorldViewProj);
		
		
		
	}

	//			1
	//			*
	//		   / \
	//		  /   \
	//	   m0*-----*m1
	//	    / \	  /	\
	//     /   \ /   \
	//    *-----*-----*
	//   0     m2     2

	// We can draw the subdivision in two strips:
	// strip 1: bottom three triangles
	// strip 2: top triangle

	[unroll]
	for(int j = 0; j < 9; j++)
	{
		stream.Append(gout[j]);
	}
	stream.RestartStrip();

		stream.Append(gout[1]);
	stream.Append(gout[9]);
	stream.Append(gout[3]);
		stream.Append(gout[10]);
	stream.Append(gout[5]);
	stream.Append(gout[11]);
		stream.Append(gout[7]);

		stream.RestartStrip();

		stream.Append(gout[9]);
	stream.Append(gout[12]);
	stream.Append(gout[10]);
		stream.Append(gout[13]);
	stream.Append(gout[11]);
		stream.RestartStrip();


		stream.Append(gout[12]);
	stream.Append(gout[14]);
	stream.Append(gout[13]);
	

	
	


	}
	


	
[maxvertexcount(50)]
void GS(triangle VertexOut gin[3], inout TriangleStream<GeoOut> stream)
{	


if(distance(gin[0]) < 10.0f)
{
VertexOut v[15];
Subdivide2(gin, v);
OutputSubdivision2(v,stream);

}
else if(distance(gin[0]) >= 10.0f && distance(gin[1]) >= 10.0f && distance(gin[2]) >= 10.0f)
{
VertexOut v[6];
Subdivide(gin, v);
OutputSubdivision(v,stream);
  
}
}


float4 PS(GeoOut pin, uniform int gLightCount, uniform bool gUseTexure, uniform bool gAlphaClip, uniform bool gFogEnabled) : SV_Target
{

	// Interpolating normal can unnormalize it, so normalize it.
    pin.NormalW = normalize(pin.NormalW);

	// The toEye vector is used in lighting.
	float3 toEye = gEyePosW - pin.PosW; 
	
	// Cache the distance to the eye from this surface point.


	float distToEye = length(toEye);



	
		// Normalize.
	toEye /= distToEye;
	
    // Default to multiplicative identity.
    float4 texColor = float4(1, 1, 1, 1);
   
	 
	//
	// Lighting.
	//
	
	float4 litColor = texColor;
	if( gLightCount > 0  )
	{  
		// Start with a sum of zero. 
		float4 ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
		float4 diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
		float4 spec    = float4(0.0f, 0.0f, 0.0f, 0.0f);

		// Sum the light contribution from each light source.  
		[unroll]
		for(int i = 0; i < gLightCount; ++i)
		{
			float4 A, D, S;
			ComputeDirectionalLight(gMaterial, gDirLights[i], pin.NormalW, toEye, A, D, S);

			ambient += A;
			diffuse += D;
			spec    += S;
		}

		// Modulate with late add.
		litColor = texColor * (ambient + diffuse) + spec;
	}
//	float4 litColor = float4(0.0f, 0.0f, 0.0f, 0.0f);
//	litColor += float4(0.1f,0.05f,0.05f,0.1f);

	//
	// Fogging
	//

	if( gFogEnabled )
	{
		float fogLerp = saturate( (distToEye - gFogStart) / gFogRange ); 

		// Blend the fog color and the lit color.
		litColor = lerp(litColor, gFogColor, fogLerp);
	}

	// Common to take alpha from diffuse material and texture.
	litColor.a *= texColor.a;

    return litColor;
	

	
	



	
}


First the sphere subdivided twice

55h6hj.png

When the distance starts right at 10

kb4m77.png

then it turns into the sphere divided only once

29gmqmr.png

To LHLaurini and others, how do I make a distance for the whole mesh in the geometry shader if it getting fed only 3 vertices at a time?

This topic is closed to new replies.

Advertisement