有没有更有效的射线投射方法?

huangapple go评论54阅读模式
英文:

Is there a more efficient way to do raycasting?

问题

以下是您要翻译的部分:

这里有个故事。我想学习图形编程,但发现OpenGL的语法很难,所以我在.Net C#中创建了一个渲染器,将图像保存到位图中。我找不到关于如何进行光线投射(raycasting)的信息,因此我想出了自己的方法,通过在循环中将一个点从相机移动到近平面上的某一点,然后继续移动直到它击中某物或到达远平面。以下是代码的简化片段:

// 遍历近平面上的每个点,根据分辨率进行划分
for (int y = 0; y < nearPlanePoints.GetLength(1); y++)
{
    for (int x = 0; x < nearPlanePoints.GetLength(0); x++)
	{
	    bool doBreak = false;
        // 获取从相机指向近平面上当前像素的方向
	    Vector3 rayDirection = new Vector3(nearPlanePoints[x,y], nearPlane).Normalized;
        // 移动点,每次移动rayStep距离,直到达到远平面
		for (float z = 0; z <= farPlane; z+=rayStep)
		{
			Vector3 point = position + rayDirection * z;
            // 检查与“场景”中对象的碰撞(由于我使用半径,我只能渲染球体)
			for (int i = 0; i < sceneObjects.Length; i++)
			{
				if (Vector3.Distance(point, sceneObjects[i].position) <= sceneObjects[i].radius)
				{
                    // 当碰撞时,将相应像素的颜色设置为对象的颜色
					renderedImage[(y * Program.image_width) + x] = sceneObjects[i].color;
                    // 不再继续搜索碰撞
					doBreak = true;
					break;
				}
			}
			if (doBreak)
				break;
			else
                // 如果搜索结束没有碰撞,将相应像素的颜色设置为预定义的背景颜色
				renderedImage[(y * Program.image_width) + x] = backgroundColor;
		}
	}
}
return renderedImage;

问题在于,当远平面非常远并且不与任何物体碰撞时,光线投射会变得明显较慢,这让我相信可能有更高效的光线投射方法。当然,它在CPU上运行也会变慢,但我无法使用任何.Net GPU API(只能使用.Net提供的默认命名空间),所以无法改变这一点。

如果您可以指导我找到答案的网站,或者任何可以在这个旅程中帮助我的网站,那将不胜感激!

我一直在努力谷歌如何做事,但更多时候我找不到任何信息,只能自己想出解决方案,因此我的方法可能非常低效。非常感谢您的理解。

提前感谢您的任何回答!

英文:

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!

答案1

得分: 0

我找到的有效方法受到一种叫做“射线行进”的技术的启发,在这种方法中,你找到最近的物体(在我的情况下是一个点减去它的半径),获取射线点与这个物体之间的距离,然后向前移动这么多距离,然后重复。

英文:

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.

huangapple
  • 本文由 发表于 2023年2月24日 03:45:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/75549636.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定