5

Ray Tracer での被写界深度の実装について誰か助けてくれませんか?

以下に示すように、単純なピンホール カメラ モデルを使用しています。ピンホール カメラ モデルを使用して DOF 効果を生成する方法を知る必要がありますか? (画像はウィキペディアより引用)

ここに画像の説明を入力

私の基本的なレイトレーサーは正常に動作しています。

私は (dx, dy , 1.0f, 0.0f) の方向で (0,0,0,1) に目を持っています。

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

今私が読んだところはどこでも、イメージ プレーンとシーンの間に配置する必要があるレンズのサンプリングについて話している. たとえば、以下に示すように(ウィキペディアから取得した画像):

光線が 1 つの点の位置 (カメラまたは目) から来ている場合、像面の前にレンズを導入するにはどうすればよいですか?

誰かがそれを助けることができれば、それは素晴らしいことです!

ありがとうございました

4

2 に答える 2

12

これを行うには 3 つの方法があります。

  1. 物理的に正しい DOF には、シーンの複数のレンダリングが必要です。カメラは実際にはピンホール モデルではないため、被写界深度があります。代わりに、特定の直径内の光を許可する開口部があります。これは、ピンホール カメラを使用して、その絞り値内で多くの写真を撮影し、それらを平均化することに相当します。

    したがって、基本的には、フォーカス ポイントを中心にカメラを複数回回転させ、シーン全体をレンダリングし、出力カラーをバッファに蓄積し、すべての値をレンダリング回数で割る必要があります。

  2. シンプルな後処理効果 - シーンの色だけでなくその深度もレンダリングし、この深度を使用してぼかし効果の強さを制御します。これは、さまざまなぼかしレベルでオブジェクト間のシームレスな遷移を取得するためのいくつかのトリックが必要なテクニックであることに注意してください。

  3. より複雑な後処理効果 - 以前のように深度バッファーを作成し、それを使用して、元のシーンのすべてのピクセルに対して開口形状の粒子をレンダリングします。深度を使用して、ぼかし効果の強度に使用するのと同じように粒子サイズを制御します。

(1) 最良の結果が得られますが、最もコストのかかる手法です。(2) が最も安価で、(3) はかなりトリッキーですが、費用対効果のバランスが取れています。

于 2012-04-04T13:56:02.593 に答える
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以下に示すよう に の値のぼやけた画像です。ここに画像の説明を入力

このコードのどこが間違っているかを知ることができれば、非常に役に立ちます :) ありがとう!

于 2012-04-10T16:49:06.433 に答える