zoukankan      html  css  js  c++  java
  • Thinhole类声明和实现

    Thinhole类说白了就是在眼睛处,放一个放大镜。就像我们平时用放大镜观察物体一样。这样实现的效果的是,周围会模糊。原理书上都说的很清楚了,我把算法截图下来了。这个应用我猜测是在竞技游戏比如csgo中,狙击开镜后效果。具体等之后开发游戏时,再测试一下。如下:

    类声明:

    #pragma once
    #ifndef __THINLENS_HEADER__
    #define __THINLENS_HEADER__
    
    #include "camera.h"
    
    class Sampler;
    
    class Thinlens :public Camera {
    public:
    	Thinlens();
    	~Thinlens();
    	Thinlens(const Thinlens& tl);
    	void set_view_distance(const ldouble a);
    	void set_focal_distance(const ldouble a);//这个是放大镜的系数,我默认是取0.8,因为我用的物体是1个像素,比较小。
    	void set_lens_radius(const ldouble rad);//放大镜的半径
    	void set_zoom(const ldouble factor);//缩放
    	void set_angle(const ldouble deg);//旋转角
    	void set_sampler(Sampler* const sampler);//随机采样数组,实现模糊效果
    	Vector3 ray_direction(const Point3& pixel_point, const Point3& lens_point) const;
    	virtual Camera* clone() const;
    	virtual void render_scene(World& w);
    	Thinlens& operator=(const Thinlens& tl);
    private:
    	ldouble lens_radius, d, f, zoom;
    	Sampler* sampler;
    };
    #endif

    类实现

    #include "pch.h"
    #include "thinlens.h"
    #include "../utilities/world.h"
    #include "../utilities/viewplane.h"
    #include "../samplers/sampler.h"
    #include "../tracers/tracer.h"
    
    Thinlens::Thinlens()
        :Camera(), lens_radius(0.5), f(0.8), d(1), zoom(1), sampler(nullptr) {}
    
    Thinlens::~Thinlens() {
        if (sampler)
            delete sampler;
    }
    
    Thinlens::Thinlens(const Thinlens& tl)
        :Camera(tl), lens_radius(tl.lens_radius), f(tl.f), d(tl.d)
        , zoom(tl.zoom), sampler(tl.sampler) {}
    
    void Thinlens::set_view_distance(const ldouble a) {
        d = a;
    }
    
    void Thinlens::set_focal_distance(const ldouble a) {
        f = a;
    }
    
    void Thinlens::set_lens_radius(const ldouble rad) {
        lens_radius = rad;
    }
    
    void Thinlens::set_zoom(const ldouble factor) {
        zoom = factor;
    }
    
    void Thinlens::set_angle(const ldouble deg) {
    	ldouble rad = radian(deg);
    	up = Point3(std::cos(rad) * up.x - std::sin(rad) * up.y,
    		std::sin(rad) * up.x + std::cos(rad) * up.y, up.z);
    }
    
    void Thinlens::set_sampler(Sampler* const sam) {
        if (sampler) {
            delete sampler;
            sampler = nullptr;
        }
        sampler = sam;
        sampler->map_to_unit_disk();
    }
    
    
    Vector3 Thinlens::ray_direction(const Point3& pixel_point, const Point3& lens_point) const {
        Point3 p;
        p.x = pixel_point.x * d * f;
        p.y = pixel_point.y * d * f;
        Vector3 dir = (p.x - lens_point.x) * u + (p.y - lens_point.y) * v - f * w;
        dir.normalize();
        return dir;
    }
    
    Camera* Thinlens::clone() const {
        return new Thinlens(*this);
    }
    
    
    void Thinlens::render_scene(World& w) {
        Ray ray;
        ViewPlane vp(w.vp);
        integer depth = 0;
        Point3 sp, pp, lp;
        w.open_window(vp.hres, vp.vres);
        vp.s = 1 / (vp.s * zoom);
    	for (integer r = vp.vres - 1; r >= 0; r--)//render from left-corner to right-corner
            for (integer c = 0; c < vp.hres; c++) {
                RGBColor color;
                for (integer p = 0; p < vp.nsamples; p++) {
                    sp = vp.sampler->sample_unit_square();
    				pp.x = (c - 0.5 * vp.hres + sp.x) * vp.s;
    				pp.y = (r - 0.5 * vp.vres + sp.y) * vp.s;
                    lp = sampler->sample_unit_square() * lens_radius;
                    ray.o = eye + lp.x * u + lp.y * v;
                    ray.d = ray_direction(pp, lp);
                    color += w.tracer_ptr->trace_ray(ray);
                }
                color /= vp.nsamples;
                color *= exposure_time;
                w.display_pixel(r, c, color);
            }
    }
    
    
    Thinlens& Thinlens::operator=(const Thinlens& tl) {
        if (this == &tl)
            return *this;
    	Camera::operator= (tl);
        lens_radius = tl.lens_radius;
        d = tl.d;
        f = tl.f;
        zoom = tl.zoom;
        sampler = tl.sampler;
        return *this;
    }

    需要修改的World类:

    void World::build() {
    	vp.set_hres(200);
    	vp.set_vres(100);
    	vp.set_sampler(new Hammersley());
    	vp.sampler->map_to_sphere();
    	tracer_ptr = new MultiSphere(this);
    	Geometrics* obj = new Sphere(0, 0.5);
    	obj->set_color(RGBColor(1, 0, 0));
    	add_object(obj);
    	obj = new Sphere(Point3(0, -100.5, 0), 100);
    	obj->set_color(RGBColor(0, 0, 1));
    	add_object(obj);
    	Thinlens* thinlens = new Thinlens();
    	thinlens->set_eye(Point3(0, 0, 1));
    	thinlens->set_lookat(Point3(0));
    	thinlens->set_view_distance(1.5);
    	thinlens->set_sampler(new MultiJittered());//书上是采用多重采样,可以替换为其他采样。不过这个采样效果是比较好的。
    	thinlens->set_angle(-45);
    	//thinlens->set_zoom(2.0);
    	thinlens->compute_uvw();
    	set_camera(thinlens);
    }
    

      

    测试效果图(蓝色和黑色部分已经模糊了,算法测试成功!):

  • 相关阅读:
    shell进行mysql统计
    java I/O总结
    Hbase源码分析:Hbase UI中Requests Per Second的具体含义
    ASP.NET Session State Overview
    What is an ISAPI Extension?
    innerxml and outerxml
    postman
    FileZilla文件下载的目录
    how to use webpart container in kentico
    Consider using EXISTS instead of IN
  • 原文地址:https://www.cnblogs.com/dalgleish/p/12650968.html
Copyright © 2011-2022 走看看