Jump to content

Voxel Cone Tracing Part 3 - Raycasting


Josh

3,968 views

 Share

I added a raycast function to the voxel tree class and now I can perform raycasts between any two positions. This is perfect for calculating direct lighting. Shadows are calculated by performing a raycast between the voxel position and the light position, as shown in the screenshot below. Fortunately the algorithm seems to work great an there are no gaps or cracks in the shadow:

Image3.thumb.jpg.aa525b6e6015ce33cd599fe260d7cbd4.jpg

Here is the same scene using a voxel size of 10 centimeters:

Image1.thumb.jpg.3dd4c5b583602d1bcecf77c59f0d3616.jpg

If we move the light a little lower, you can see a shadow appearing near two edges of the floor:

Image4.thumb.jpg.95c15f586949f8884d63ef7014262dae.jpg

Why is this happening? Well, the problem is that at those angles, the raycast is hitting the neighboring voxel on the floor next to the voxel we are testing:

Image5.jpg.3ef85296e80d5608f268ed89d696b730.jpg

You might think that if we just move one end of the ray up to the top of the voxel it will work fine, and you'd be right, in this situation.

Image5.jpg.811e71a97a5f8778c3e24ddc2fb13e9f.jpg

But with slightly different geometry, we have a new problem.

Image52.jpg.5432c5978edb6d2b69efc780402f2a55.jpg

So how do we solve this? At any given time, a voxel can have up to three faces that face the light (but it might have as few as one). In the image below I have highlighted the two voxel faces on the right-most voxel that face the light:

6.jpg.77c53e0728f2abd8c84e44cc06d49ce0.jpg

If we check the neighboring voxels we can see that the voxel to the left is occupied, and therefore the left face does not make a good position to test from:

7.jpg.2d680c35db9b3981d1699b8f51d0f357.jpg

But the top voxel is clear, so we will test from there:

8.jpg.650c71e78cfa061d85903137a2fb567b.jpg

If we apply the same logic to the other geometry configuration I showed, we also get a correct result. Of course, if both neighboring voxels were solid then we would not need to perform a raycast at all because we know the light would be completely blocked at this position.

The code to do this just checks which side of a voxel the light position is on. As it is written now, up to three raycasts may be performed per voxel:

if (lightpos.x < voxel->bounds.min.x)
{
	if (GetSolid(ix - 1, iy, iz) == false)
	{
		result = IntersectsRay(p0 - Vec3(voxelsize * 0.5f, 0.0f, 0.0f), lightpos);
	}
}
if (lightpos.x > voxel->bounds.max.x and result == false)
{
	if (GetSolid(ix + 1, iy, iz) == false)
	{
		result = IntersectsRay(p0 + Vec3(voxelsize * 0.5f, 0.0f, 0.0f), lightpos);
	}
}
if (lightpos.y < voxel->bounds.min.y and result == false)
{
	if (GetSolid(ix, iy - 1, iz) == false)
	{
		result = IntersectsRay(p0 - Vec3(0.0f, voxelsize * 0.5f, 0.0f), lightpos);
	}
}
if (lightpos.y > voxel->bounds.max.y and result == false)
{
	if (GetSolid(ix, iy + 1, iz) == false)
	{
		result = IntersectsRay(p0 + Vec3(0.0f, voxelsize * 0.5f, 0.0f), lightpos);
	}
}
if (lightpos.z < voxel->bounds.min.z and result == false)
{
	if (GetSolid(ix, iy, iz - 1) == false)
	{
		result = IntersectsRay(p0 - Vec3(0.0f, 0.0f, voxelsize * 0.5f), lightpos);
	}
}
if (lightpos.z > voxel->bounds.max.z and result == false)
{
	if (GetSolid(ix, iy, iz + 1) == false)
	{
		result = IntersectsRay(p0 + Vec3(0.0f, 0.0f, voxelsize * 0.5f), lightpos);
	}
}

.With this correction the artifact disappears:

Image7.thumb.jpg.057601b4581814be80a704ac1093fda9.jpg

It even works correctly at a lower resolution:

Image8.thumb.jpg.154d0eb8f7241a4f47d07da98c838437.jpg

Now our voxel raycast algorithm is complete. The next step will be to calculate direct lighting on the voxelized scene using the lights that are present.

  • Like 3
 Share

1 Comment


Recommended Comments

Really impressive stuff this. How you get this done so quickly is beyond me.  I remember having spend weeks on an implementation of marching cubes, to only get a result were it took 3 seconds to render a small blob of voxels.

Link to comment
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...