I am just through implementing scene voxelization myself, and I am doing the dominant axis selection for a primitive like this in the geometry shader:
// First calculate the face normal
float3 facenormal = abs(normalize(input[0].normal + input[1].normal + input[2].normal));
// Then the dominant axis is the face normal's max component:
uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;
maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;
for( uint i = 0; i < 3; ++i )
{
// The position is in World space, transform to voxel space:
output[i].pos = float4((input[i].pos.xyz - (float3)VoxelSceneCenterPos / (float)VoxelSceneScale, 1);
// Projection matrix is unnecessary, just a swizzle is enough:
if (maxi == 0)
{
output[i].pos.xyz = output[i].pos.zyx;
}
else if (maxi == 1)
{
output[i].pos.xyz = output[i].pos.xzy;
}
// And if the dominant axis is Z, then I do nothing because that is the default projection plane for me.
// Then I just project the voxel space pos like this:
output[i].pos.xy /= (float)VoxelSceneResolution;
output[i].pos.zzw = 1;
// After this step, the output[i].pos is in clip space, the rasterization will take place on this value.
}
In my code, input
is the three vertices from the vertex shader stage, output
is the TriangleStream which the geometry shader emits (which is also three vertices).
VoxelSceneCenterPos
is a uniform from a constant buffer which is the center of the voxelization (for example (0,0,0) vector).
VoxelSceneScale
is a uniform from a constant buffer which is the size of a single voxel (default value is 1).
VoxelSceneResolution
is a uniform from a constant buffer which is the resolution of the voxel grid (for example for a 256256256 grid this value is 256).
My main idea comes from this cool presentation by NVIDIA.
Good luck!