Search code examples
c#.netgraphicsrenderingraycasting

Is there a more efficient way to do raycasting?


Here's the story. I wanted to get into graphics programming, but found OpenGL's syntax hard, so I made a renderer in .Net C# that saves the image into a bitmap. I couldn't find any information on how to do raycasting, so I came up with my own way to do it, where I move a point with a for loop from the camera towards a point on the nearplane and beyond until it either hits something, or it reaches the far plane. Here's a simplified snippet of the code

// Go through every point on the near plane, divided by the resolution
for (int y = 0; y < nearPlanePoints.GetLength(1); y++)
{
    for (int x = 0; x < nearPlanePoints.GetLength(0); x++)
    {
        bool doBreak = false;
        // Get the direction from the camera towards the current pixel on the near plane
        Vector3 rayDirection = new Vector3(nearPlanePoints[x,y], nearPlane).Normalized;
        // Move the point by rayStep ammount until reaching the far plane
        for (float z = 0; z <= farPlane; z+=rayStep)
        {
            Vector3 point = position + rayDirection * z;
            // Check for collision with object in the "scene" (since I use radius, I can only render spheres) 
            for (int i = 0; i < sceneObjects.Length; i++)
            {
                if (Vector3.Distance(point, sceneObjects[i].position) <= sceneObjects[i].radius)
                {
                    // When collides, paint the corresponding pixel to the color of the object
                    renderedImage[(y * Program.image_width) + x] = sceneObjects[i].color;
                    // Don't continue to search for collision
                    doBreak = true;
                    break;
                }
            }
            if (doBreak)
                break;
            else
                // If the search ended without a collision, paint the corresponding pixel to a predefined background color
                renderedImage[(y * Program.image_width) + x] = backgroundColor;
        }
    }
}
return renderedImage;

The thing is, the raycasts get significantly slower when the far plane is really far and it doesn't collide with anything, leading me to believe that there might be a more efficient way to do raycasting. Of course, the fact that it runs on the CPU also makes it slower, however I am unable to use any of the .Net GPU APIs (I can only use the default namespaces offered by .Net), so that cannot be helped.

If you could direct me to a website where I can find an answer, or just any website that might help me with this journey in general, that would be greatly appreciated!

I've been trying my best to Google how I should do things, but more often than not, I couldn't find anything and I had to come up with a solution myself, so my methods may be incredibly inefficient. Thank you for understanding.

Thank you in advance for any answers!


Solution

  • What I've found to work was inspired by a technique called ray marching, where you find the closest object (in my case a point minus it's radius), get the distance between the ray's point and this object, and move that much forward, then repeat.