如何在光线追踪器中实现景深?

6

请问有人可以帮我实现光线追踪中的景深效果吗?

我正在使用简单的针孔相机模型,如下所示。我想知道如何使用针孔相机模型生成景深效果?(图片来自wikipedia

enter image description here

我的基本光线追踪器工作正常。

我的眼睛在(0,0,0,1),方向为(dx,dy,1.0f,0.0f),其中

float dx = (x * (1.0 / Imgwidth) ) - 0.5;
float dy = (y * (1.0 / Imgheight) ) - 0.5;

现在我到处都在阅读有关采样镜头的内容,这些镜头应该放置在图像平面和场景之间。例如下面显示的图片(来自维基百科):

如果光线来自一个单一的点位置(相机或眼睛),那么如何在图像平面前引入一个镜头?

如果有人可以帮忙,那就太好了!

谢谢

2个回答

12
有三种方法可以实现这一点:
  1. 物理正确的景深需要渲染多个场景。相机拥有景深是因为它们不是真正的针孔模型。相反,它们有一个允许在一定直径内进入光线的光圈。这相当于使用针孔相机,在光圈内拍摄很多照片并将它们平均。

    所以基本上,您需要围绕焦点点轻微旋转相机多次,渲染整个场景,将输出颜色累积到缓冲区中,并将所有值除以渲染次数。

  2. 一个简单的后处理效果 - 不仅渲染场景颜色,还要渲染其深度,然后使用此深度来控制模糊效果的强度。请注意,这种技术需要一些技巧才能在不同模糊级别的对象之间获得无缝转换。

  3. 更复杂的后处理效果 - 创建一个深度缓冲区,然后使用它为原始场景的每个像素渲染一个光圈形状的粒子。像模糊效果强度一样,使用深度来控制粒子大小。

(1)提供了最佳效果,但是是最昂贵的技术;(2)是最便宜的方法,(3)非常棘手,但提供了很好的成本效益平衡。


1
难道不是类似于在摄像机(或眼睛)位置周围取几个样本点,然后从所有这些位置渲染我的场景吗?通过在场景中某个焦点处定义焦点来发送每个样本点到图像平面中每个像素的焦点点的射线。 - sinner
当然可以按像素累积颜色,而不是累积整个场景的渲染结果。 - IneQuation
1
如果我理解正确的话,那么是的,我们在谈论同一件事情。 :) 只需要记住 - 在将不同渲染的像素添加在一起之后,您需要将它们除以渲染数量。 - IneQuation
在这篇文章中,他们说了一个不同的故事。这样做也是正确的方式吗? - sinner
现在我正在获得相同球体的不同深度的副本 :-\ - sinner
显示剩余5条评论

3

这是我编写的生成DOF的代码。

void generateDOFfromEye(Image& img, const Camera& camera, Scene scene, float focusPoint)
{
    float pixelWidth = 1.0f / (float) img.width;
    float pixelHeight = 1.0f / (float) img.height;

    for (int y = 0; y < img.height; ++y)
        {
        for (int x = 0; x < img.width; ++x)
            {
            Color output(0,0,0,0);
            img(x, y) = Color(0,0,0,0);

            //Center of the current pixel
            float px = ( x * pixelWidth) - 0.5;
            float py = ( y * pixelHeight) - 0.5;

            Ray cameraSpaceRay = Ray(Vector(0,0,0,1), Vector(px, py, 1.0f, 0.0f));

            Ray ray = camera.Transform() * cameraSpaceRay;

            int depth = 0;
            int focaldistance = 2502;
            Color blend(0,0,0,0);



             //Stratified Sampling i.e. Random sampling (with 16 samples) inside each pixel to add DOF
                for(int i = 0; i < 16; i++)
                {
                //random values between [-1,1]
                float rw = (static_cast<float>(rand() % RAND_MAX) / RAND_MAX) * 2.0f - 1.0f;
                float rh = (static_cast<float>(rand() % RAND_MAX) / RAND_MAX) * 2.0f - 1.0f;
                // Since eye position is (0,0,0,1) I generate samples around that point with a 3x3 aperture size window.
                float dx =  ( (rw) * 3 * pixelWidth) - 0.5;
                float dy =  ( (rh) * 3 * pixelHeight) - 0.5;

                //Now here I compute point P in the scene where I want to focus my scene
                Vector P = Vector(0,0,0,1) + focusPoint * ray.Direction();
                Vector dir = P - Vector(dx, dy, 0.0f, 1.0f);


                ray  = Ray(Vector(dx,dy,0.0f,1.0f), dir);
                ray = camera.Transform() * ray;

                //Calling the phong shader to render the scene
                blend += phongShader(scene, ray, depth, output);

                }
            blend /= 16.0f;

            img(x, y) += blend;
            }
        } 
}

现在我在代码中没有看到任何问题。但是我得到的结果只是一个模糊的图像,如下所示:focuspoint > 500的值: enter image description here

如果您能告诉我这段代码有什么问题,那将非常有帮助:) 谢谢!


2
这不应该是问题的一部分吗? - Benjamin W.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接