[maxvertexcount(3)]
void GS(triangle GSInputPositionNormalTexture input[3],
inout TriangleStream< PSInputPositionNormalTexture > output_stream) {
const float3 abs_n = abs(cross(input[1].p_view - input[0].p_view,
input[2].p_view - input[0].p_view));
const uint dir_xy = (abs_n.x > abs_n.y) ? 0u : 1u;
const uint dir = (abs_n.z > abs_n[dir_xy]) ? 2u : dir_xy;
PSInputPositionNormalTexture output[3];
// Project the triangle in the dominant direction for rasterization (p),
// but not for lighting (p_view).
[unroll]
for (uint i = 0u; i < 3u; ++i) {
[flatten]
switch (dir) {
case 0u:
output[i].p.xy = input[i].p_view.yz;
break;
case 1u:
output[i].p.xy = input[i].p_view.zx;
break;
default:
output[i].p.xy = input[i].p_view.xy;
break;
}
// [m_view] * [voxels/m_view] -> [voxels]
output[i].p.xy *= g_voxel_inv_size;
...
}
// For each projected triangle, a slightly larger bounding triangle ensures
// that any projected triangle touching a pixel will necessarily touch the
// center of this pixel and thus will get a fragment emitted by the rasterizer.
const float2 delta_10 = normalize(output[1].p.xy - output[0].p.xy);
const float2 delta_21 = normalize(output[2].p.xy - output[1].p.xy);
const float2 delta_02 = normalize(output[0].p.xy - output[2].p.xy);
// [voxels] * [2 m_ndc/voxels] -> [-1,1]
const float voxel_to_ndc = 2.0f * g_voxel_grid_inv_resolution;
// Move vertices for conservative rasterization.
output[0].p.xy = (output[0].p.xy + normalize(delta_02 - delta_10)) * voxel_to_ndc;
output[1].p.xy = (output[1].p.xy + normalize(delta_10 - delta_21)) * voxel_to_ndc;
output[2].p.xy = (output[2].p.xy + normalize(delta_21 - delta_02)) * voxel_to_ndc;
...
}
I tried to voxelize the scene into a regular 3D voxel grid centered around the camera. This results in some odd cutouts and temporal disappearances of triangles which seems to dependent on the camera angles.
With conservative rasterization:
output[0].p.xy = (output[0].p.xy) * voxel_to_ndc;
output[1].p.xy = (output[1].p.xy) * voxel_to_ndc;
output[2].p.xy = (output[2].p.xy) * voxel_to_ndc;
Without conservative rasterization:
output[0].p.xy = (output[0].p.xy + normalize(delta_02 - delta_10)) * voxel_to_ndc;
output[1].p.xy = (output[1].p.xy + normalize(delta_10 - delta_21)) * voxel_to_ndc;
output[2].p.xy = (output[2].p.xy + normalize(delta_21 - delta_02)) * voxel_to_ndc;
This should shift the voxel-space vertex coordinates outwards over one voxel. Though, if I scale this (by a factor 2 for example), the problems remain. So I wonder if this is still somehow related to conservative rasterization or not?
It even gets more extreme, since complete planes disappear depending on the camera angles:
float g_voxel_size = 0.1f; // The size of a voxel in meters (view space)
float g_voxel_inv_size = 10.0f;
uint g_voxel_grid_resolution = 128u; // The resolution of the voxel grid
float g_voxel_grid_inv_resolution = 0.0078125f;