Jump to content
  • Advertisement
matt77hias

Voxelization cracks

Recommended Posts

2 minutes ago, JoeJ said:

I would download the voxelized data and visualize a cube for each voxel to be sure the bug is not just in your visualization.

The voxels are occupied. Though, the filled voxels for a single plane occur in multiple consecutive slices (due to the slope of the plane)

 

4 minutes ago, JoeJ said:

I assume aligning the grid to view direction is no good idea because voxels will pop like crazy.

I guess that the values stored in the voxels can indeed start fluctuating while moving and changing the camera orientation. Thought, indirect illumination is generally much smoother and low-frequency than direct illumination. But I am curious at the final results too.

For the current debug visualization, the popping is quite strange, since it becomes black. I wouldn't be surprised when the color changes, but black, however, indicates that the voxel is empty.

Share this post


Link to post
Share on other sites
Advertisement

I switched to world space and visualized the voxels, but somehow I still see a camera dependence on the floor and some popping at the walls?

screenshot-2018-02-23-21-34-49.thumb.png.4e9e4165f0fe2c4650d52269f437e1d4.png

I also used a slightly different encoding as WickedEngine (https://turanszkij.wordpress.com/2017/08/30/voxel-based-global-illumination/):

static const float g_max_length = 1.0f;

uint EncodeRadiance(float3 L) {
    const float L_length     = length(L);
    const float L_inv_length = 1.0f / L_length;

    // [0, inf) -> [0,1] -> [0,255]
    const uint length = uint(255.0f * saturate(L_length / g_max_length));
    // [0, L_inv_length)^3 -> [0,1]^3 -> [0,255]^3
    const uint3 color = uint3(255.0f * L * L_inv_length);
    
    // |........|........|........|........|
    // | length |  red   |  green |  blue  |
    const uint encoded_L = (length  << 24u)
                         | (color.x << 16u) 
                         | (color.y <<  8u) 
                         |  color.z;
    return encoded_L;
}

float3 DecodeRadiance(uint encoded_L) {
    static const float u_to_f = 1.0f / 255.0f;
    
    // [0,2^32-1] -> [0,255]^4
    const uint4 uL = 0xFF & uint4(encoded_L >> 24u,
                                  encoded_L >> 16u,
                                  encoded_L >>  8u,
                                  encoded_L);
    // [0,255]^4 -> [0,1]^4
    const float4 fL = uL * u_to_f;
    
    // [0,1] -> [0, g_max_length]
    const float L_length = fL.x * g_max_length;
    // [0,1]^3 -> [0, L_length]^3
    const float3 L = fL.yzw * L_length;
    
    return L;
}

 

Edited by matt77hias

Share this post


Link to post
Share on other sites

Seems the visualization itself is wrong, because some voxels don't have 6 sides but less. Wrong volume data alone can't cause this.

(Look at the single black voxel at the base of a column, near the center of the left half of the image.)

Share this post


Link to post
Share on other sites
15 hours ago, JoeJ said:

Seems the visualization itself is wrong, because some voxels don't have 6 sides but less. Wrong volume data alone can't cause this.

Culling? I am confused about the culling terminology of D3D. If the near face of a cube is parallel to the camera near/far plane and inside the camera frustum, and the cube faces have a clockwise winding order:

 

camera far plane

 

far face front

--------------

far face back

the void of the cube

near face back

--------------

near face front

 

camera near plane

 /\

  |

eye

Rasterizer state:

CullMode                         Back
FrontCounterClockwise    FALSE

 

Is there a possibility that fragments will be generated for the near face front and the far face front (though the normal is pointing away from the camera)? Or does the culling not involve the orientation of the geometric normal at all?

Share this post


Link to post
Share on other sites
14 minutes ago, matt77hias said:

You mean Y: 16 bits and UV: 16 bits?

Yes. Maybe some exponential mapping for Y, or just a half float.

(But i'm still using float4 myself and have not tried anything of this yet...)

5 minutes ago, matt77hias said:

Or does the culling not involve the orientation of the geometric normal at all?

In OpenGL culling only depends on winding order, IIRC

 

Share this post


Link to post
Share on other sites
4 minutes ago, JoeJ said:

In OpenGL culling only depends on winding order, IIRC

Then it should be the visualization.

 

5 minutes ago, JoeJ said:

(But i'm still using float4 myself and have not tried anything of this yet...)

It will probably be better anyway, since the g_max_length seriously caps my radiance.

Share this post


Link to post
Share on other sites

A stripped triangle cube:

0,1,1
1,1,1
0,1,0
1,1,0
1,0,0
1,1,1
1,0,1
0,1,1
0,0,1
0,1,0
0,0,0
1,0,0
0,0,1
1,0,1

This is a cube centered at [0,0,0] with a size of [1,1,1]. I multiply this with my voxel size and add it to the left/lower/near corner

const float3 offset  = OffsettedUnitCube(i) * g_voxel_size;
const float3 p_world = input[0].p_world + offset;

inside a GS. Finally, I transform to camera and projection space.

input[0].p_world is generated in the VS (executed for resolution^3 points)

const uint3 index = UnflattenIndex(vertex_index, uint3(g_voxel_grid_resolution, g_voxel_grid_resolution, g_voxel_grid_resolution));
output.p_world = VoxelIndexToWorld(index);

Transforming between voxel indices and world space:

int3 WorldToVoxelIndex(float3 p_world) {
    // Valid range: [-R/2,R/2]x[R/2,-R/2]x[-R/2,R/2]
    const float3 voxel = (p_world - g_voxel_grid_center) 
                       * g_voxel_inv_size * float3(1.0f, -1.0f, 1.0f);
    // Valid range: [0,R)x(R,0]x[0,R)
    return floor(voxel + 0.5f * g_voxel_grid_resolution);
}
float3 VoxelIndexToWorld(uint3 voxel_index) {
    // Valid range: [-R/2,R/2]x[R/2,-R/2]x[-R/2,R/2]
    const float3 voxel = voxel_index - 0.5f * g_voxel_grid_resolution;
    return voxel * g_voxel_size * float3(1.0f, -1.0f, 1.0f) + g_voxel_grid_center;
}

 

As a side not, I am not really sure if I should round or floor. If you floor you will look straight at four voxels otherwise just one voxel (for a very low voxel grid resolution). But flooring is a bit more symmetrical I guess.

 

The y direction seems to be severely wrong.

screenshot-2018-02-24-16-04-56.thumb.png.20d08bf3abb17f5f170d42e07f4d23b1.png

 

Edited by matt77hias

Share this post


Link to post
Share on other sites
On 24-2-2018 at 2:31 PM, matt77hias said:

Is there a possibility that fragments will be generated for the near face front and the far face front (though the normal is pointing away from the camera)? Or does the culling not involve the orientation of the geometric normal at all?

Of course only fragments will be generated for the near face front which is facing towards the camera.

So no culling already results in a large improvement :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!