Voxelization fails when surface is practially parallel to axis

Started by
1 comment, last by Migi0027 9 years, 6 months ago

Hi,

I'm having a slight problem when voxelizing my scene, the scene itself is practically voxelized, but, somehow when the suface/triangles normal is parallel to an axis, the voxelization goes beserk.

Example: ( Sponza Scene ) This image shows where the voxels are present, black means no voxels.

gAZoow0.png

The reason why I state that the voxelization fails when the surface is parallel is because when I slightly rotate the sponza scene, the voxelization is good. But, for now I'm not going to do that...

I've vertified that the data is sent correctly to the geometry shader, so I can eliminate that issue. Im using the normal to determine the best possible rasterization.


int GetViewIndex(in float3 normal) // Finds the best view index for the best possible rasterization
{
	float3x3 directionMatrix;
	directionMatrix[0] = -viewDirections[0];
	directionMatrix[1] = -viewDirections[1];
	directionMatrix[2] = -viewDirections[2];
	float3 dotProducts = abs(mul(directionMatrix, normal));
		float maximum = max(max(dotProducts.x, dotProducts.y), dotProducts.z);
	int index = 0;
	if (maximum == dotProducts.x)
		index = 0;
	else if (maximum == dotProducts.y)
		index = 1;
	else
		index = 2;
	return index;
}

void ApplyVP(inout float4 ps, int index, float4 pos) // Just apply the view projection matrices to the position, yeah it can be optimized
{
	if (index == 0)
		ps = mul(pos, mTD);
	else if (index == 1)
		ps = mul(pos, mRL);
	else 
		ps = mul(pos, mBF);

	ps = mul(ps, mProj);
}

[maxvertexcount(3)]
void GShader(triangle VOut input[3], inout TriangleStream<GOut> outputStream)
{
	float3 faceNormal = normalize(input[0].normalWS + input[1].normalWS + input[2].normalWS);

		// Get view, at which the current triangle is most visible, in order to achieve highest
		// possible rasterization of the primitive.
		int viewIndex = GetViewIndex(faceNormal);

	GOut output[3];
	[unroll]
	for (int i = 0; i < 3; i++)
	{
		output[i] = GVertexCopy(input[i]);
		ApplyVP(output[i].positionPS, viewIndex, float4(input[i].positionWS.xyz, 1));
	}

	// Bloat triangle in normalized device space with the texel size of the currently bound 
	// render-target. In this way pixels, which would have been discarded due to the low 
	// resolution of the currently bound render-target, will still be rasterized.
	float2 side0N = normalize(output[1].positionPS.xy - output[0].positionPS.xy);
		float2 side1N = normalize(output[2].positionPS.xy - output[1].positionPS.xy);
		float2 side2N = normalize(output[0].positionPS.xy - output[2].positionPS.xy);

		float texelSize = 1.0f / 64.0f;

	output[0].positionPS.xy += normalize(-side0N + side2N)*texelSize;
	output[1].positionPS.xy += normalize(side0N - side1N)*texelSize;
	output[2].positionPS.xy += normalize(side1N - side2N)*texelSize;

	[unroll]
	for (int j = 0; j < 3; j++)
		outputStream.Append(output[j]);

	outputStream.RestartStrip();
}

float HalfExtendOffset = (GridInfo.vgrid_size) / (2.0f * GridInfo.vgrid_cellSize);

D3DXMatrixLookAtLH(&mBF, &(D3DXVECTOR3(0, 0, HalfExtendOffset) + offset), &D3DXVECTOR3(0, 0, 0), &D3DXVECTOR3(0, 1, 0));

D3DXMatrixLookAtLH(&mRL, &(D3DXVECTOR3(HalfExtendOffset, 0, 0) + offset), &D3DXVECTOR3(0, 0, 0), &D3DXVECTOR3(0, 1, 0));

D3DXMatrixLookAtLH(&mTD, &(D3DXVECTOR3(0, HalfExtendOffset, 0) + offset), &D3DXVECTOR3(0, 0, 0), &D3DXVECTOR3(0, 1, 0));

D3DXMatrixOrthoLH(&mProj, 200, 200, 0.2f, 2.0f*HalfExtendOffset);

I've tested all view matrices for the grid and all seem ok.

All the matrices are transposed before sent to the shader.

Could it be that the mTD matrix ( top down ) is incorrect due to that the view direction is parallel to the up vector?

Thank you for your time.

FastCall22: "I want to make the distinction that my laptop is a whore-box that connects to different network"

Blog about... stuff (GDNet, WordPress): www.gamedev.net/blog/1882-the-cuboid-zone/, cuboidzone.wordpress.com/

Advertisement

I noticed a few people glanced at this thread, thank you!

The error was a rather sneaky one, it was a simple error when finding the view matrix for best possible rasterization:

And I forgot to add 6 lines! Sorry!

Problem:


static float3 g_GridViewDirections[3] = 
{
	float3(0.0f, 0.0f, -1.0f),
	float3(-1.0f, 0.0f, 0.0f), 
	float3(0.0f, -1.0f, 0.0f)
};

int GetViewIndex(in float3 normal)
{
	float3x3 directionMatrix;
	directionMatrix[0] = -viewDirections[0];
	directionMatrix[1] = -viewDirections[1];
	directionMatrix[2] = -viewDirections[2];
	float3 dotProducts = abs(mul(directionMatrix, normal));
		float maximum = max(max(dotProducts.x, dotProducts.y), dotProducts.z);
	int index = 0;
	if (maximum == dotProducts.x)
		index = 0;
	else if (maximum == dotProducts.y)
		index = 1;
	else
		index = 2;
	return index;
}

void ApplyVP(inout float4 ps, int index, float4 pos)
{
	if (index == 0)
		ps = mul(pos, mTD);
	else if (index == 1)
		ps = mul(pos, mBF);
	else
		ps = mul(pos, mLR);

	ps = mul(ps, mProj);
}

When index is 0 this means that the Back Front matrix is most suitable, when 1 its the right left, when 2 its the top down. But! The order I had in ApplyVP was wrong, so I corrected it and woala!

Correct ApplyVP:


void ApplyVP(inout float4 ps, int index, float4 pos)
{
	if (index == 0)
		ps = mul(pos, mBF);
	else if (index == 1)
		ps = mul(pos, mRL);
	else
		ps = mul(pos, mTD);

	ps = mul(ps, mProj);
}

Thank you again, for anyone who took their time.

-MIGI0027

FastCall22: "I want to make the distinction that my laptop is a whore-box that connects to different network"

Blog about... stuff (GDNet, WordPress): www.gamedev.net/blog/1882-the-cuboid-zone/, cuboidzone.wordpress.com/

The final output:

2FGpwe0.png

FastCall22: "I want to make the distinction that my laptop is a whore-box that connects to different network"

Blog about... stuff (GDNet, WordPress): www.gamedev.net/blog/1882-the-cuboid-zone/, cuboidzone.wordpress.com/

This topic is closed to new replies.

Advertisement