问题二十八:ray tracing中的散焦模糊(defocus blur)

198 篇文章 12 订阅
195 篇文章 27 订阅

 “散焦模糊”在摄影上又称“景深”。

在现实的相机中,我们需要做“散焦模糊”的原因是:我们需要一个更大的孔来收集光线增加图片的亮度(而不是“针孔”)。我们称“更大的孔”为“光圈”。

For a real camera, if you need more light,you make the aperture bigger, and will get more defocus blur.

For our virtual camera, we can have aperfect sensor and never need more light, so we only have an aperture when wewant defocus blur.

 

光圈的增大,导致图片出现散焦而模糊。

但是我们可以调节成像的位置,改变图片的清晰度,使图片在当前光圈条件下尽可能清晰。

 

所以,接下来,我们会引入两个参数:aperture(光圈)和focus_dist(成像位置)。

 

关于成像位置,

在原点的标准正交基e1 = (1, 0, 0), e2 = (0, 1, 0), e3 = (0, 0, 1)的坐标系,成像位置之前被设置在- e3平面(即z=-1的平面);

在任意点的标准正交基u,v,w的坐标系,成像位置之前被设置在-w平面。

引入参数focus_dist之后,成像位置将会是-focus_dist* e3 或者-focus_dist*w平面。图片的高宽都需要乘以参数focus_dist.


关于光圈,


看code的改变吧:

----------------------------------------------camera.h------------------------------------------

camera.h

#ifndef CAMERA_H
#define CAMERA_H

#include "ray.h"

vec3 random_in_unit_disk();

class camera
{
    public:
       camera(vec3 lookfrom, vec3 lookat, vec3 vup, float vfov, float aspect, float aperture, float focus_dist) { // vfov is top to bottom in degrees
            lens_radius = aperture / 2;
            float theta = vfov*M_PI/180;
            float half_height = tan(theta/2);
            float half_width = aspect * half_height;
            origin = lookfrom;
            w = unit_vector(lookfrom - lookat);
            u = unit_vector(cross(vup, w));
            v = cross(w, u);
            lower_left_corner = origin - half_width*focus_dist*u - half_height*focus_dist*v -focus_dist*w;
            horizontal = 2*half_width*focus_dist*u;
            vertical = 2*half_height*focus_dist*v;
        }
        ray get_ray(float s, float t) {
            vec3 rd = lens_radius*random_in_unit_disk();
            vec3 offset = u * rd.x() + v * rd.y();
            return ray(origin + offset, lower_left_corner + s*horizontal + t*vertical - origin - offset);
        }

        vec3 origin;
        vec3 lower_left_corner;
        vec3 horizontal;
        vec3 vertical;
        vec3 u, v, w;
        float lens_radius;
};

#endif // CAMERA_H


----------------------------------------------camera.cpp------------------------------------------

camera.cpp


#include "camera.h"
vec3 random_in_unit_disk() {
/*在z=0平面上产生一个“起点在原点,长度小于1,方向随机”的向量。为什么是z=0平面,这个和相机的倾斜方向有关。(相机的倾斜方向为view up (简称vup,一般设置为(0,1,0)))*/
    vec3 p;
    do {
        p = 2.0*vec3((rand()%(100)/(float)(100)), (rand()%(100)/(float)(100)), 0) - vec3(1,1,0);
    } while (dot(p,p) >= 1.0);
    return p;
}

贴一张书上产生的图片。

----------------------------------------------main.cpp------------------------------------------

main.cpp

        hitable *list[5];
        list[0] = new sphere(vec3(0,0,-1), 0.5, new lambertian(vec3(0.1, 0.2, 0.5)));
        list[1] = new sphere(vec3(0,-100.5,-1), 100, new lambertian(vec3(0.8, 0.8, 0.0)));
        list[2] = new sphere(vec3(1,0,-1), 0.5, new metal(vec3(0.8, 0.6, 0.2), 0.0));
        list[3] = new sphere(vec3(-1,0,-1), 0.5, new dielectric(1.5));
        list[4] = new sphere(vec3(-1,0,-1), -0.45, new dielectric(1.5));
        hitable *world = new hitable_list(list,5);

        vec3 lookfrom(3,3,2);
        vec3 lookat(0,0,-1);
        float dist_to_focus = (lookfrom - lookat).length();
        float aperture = 2.0;
        camera cam(lookfrom, lookat, vec3(0,1,0), 20, float(nx)/float(ny), aperture, dist_to_focus);

结果图片如下:




  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Ray Tracing光线追踪)是一种在计算机图形使用的技术,用于生成高度逼真的图像。它通过跟踪光线从视点开始的路径,来模拟光在场景的运动,计算出光线与物体的交点以及光线在经过物体时的反射、折射等效果,并最终生成图像。 以下是光线追踪的基本步骤[^1]: 1. 从相机位置发出一条光线。 2. 确定该光线与场景物体的交点。 3. 计算该交点处的光照强度,包括直接光照和间接光照。 4. 根据物体的表面特性,计算反射或折射光线的方向和强度。 5. 递归计算反射或折射光线的路径,直到达到最大递归深度或光线不再与物体相交。 6. 将所有光线的颜色值组合在一起,得到最终的图像。 下面是一个简单的 Python 代码示例,演示了如何使用 Pygame 和 PyOpenGL 库实现简单的光线追踪效果[^2]: ```python import pygame from OpenGL.GL import * # 初始化 Pygame 和 PyOpenGL pygame.init() display = (800, 600) pygame.display.set_mode(display, pygame.DOUBLEBUF | pygame.OPENGL) # 设置相机位置和方向 glMatrixMode(GL_MODELVIEW) glLoadIdentity() gluLookAt(0, 0, 0, 0, 0, -1, 0, 1, 0) # 设置场景的物体 glColor3f(1, 1, 1) glBegin(GL_TRIANGLES) glVertex3f(-1, -1, -5) glVertex3f(1, -1, -5) glVertex3f(0, 1, -5) glEnd() # 定义光线追踪函数 def raytrace(x, y): glReadBuffer(GL_BACK) color = glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT) return color # 创建主循环 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() # 绘制场景和光线 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glBegin(GL_LINES) glVertex3f(0, 0, 0) glVertex3f(0, 0, -5) glEnd() # 调用光线追踪函数 x, y = pygame.mouse.get_pos() w, h = display color = raytrace(w - x, h - y) # 输出光线追踪结果 print("Color at (%d, %d): %s" % (x, y, color)) # 更新 Pygame 显示窗口 pygame.display.flip() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值