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);
}
测试效果图(蓝色和黑色部分已经模糊了,算法测试成功!):

Thinhole类声明和实现的更多相关文章
- EC笔记,第二部分:7.为多态基类声明虚析构函数
7.为多态基类声明虚析构函数 1.为多态基类声明虚析构函数 code1: class A{ public: int* a; A():a(new int(5)) {} ~A(){ delete a; } ...
- C++ 中的模板类声明头文件和实现文件分离后,如何能实现正常编译?
C++ 中的模板类声明头文件和实现文件分离后,如何能实现正常编译? 这个feature叫做Export Template,即外名模板,它的作用在于使得模板代码可依照C/C++语言习惯,将模板声明和实现 ...
- [Effective C++ --007]为多态基类声明virtual析构函数
引言: 我们都知道类的一个很明显的特性是多态,比如我们声明一个水果的基类: class Fruit { public: Fruit() {}; ~Fruit(){}; } 那么我们根据这个Fruit基 ...
- c++,基类声明的指针变量和引用类型变量可以指向派 生类的对象
基类声明的指针变量和引用类型变量可以指向派生类的对象,而反过来派生类的指针却不能指向基类变量. 这与基类和派生类之间,被允许的赋值方向是相反的. 但是从逻辑上很容易推敲其合理性.
- error C2248: “CObject::operator =”: 不可访问 private 员(于“CObject”类声明)
MFC如果编码错误: 演出:error C2248: "CObject::operator =": 不可访问 private 员(于"CObject"类声明) ...
- 类声明、类作用域、前向声明、this指针、嵌套类、PIMPL 技法 等
一.类声明 //类是一种用户自定义类型,声明形式: class 类名称 { public: 公有成员(外部接口) private: 私有 ...
- C++模板类内友元(友元函数,友元类)声明的三种情况
根据<C++ Primer>第三版16.4节的叙述,C++类模板友元分为以下几种情况 1.非模板友元类或友元函数. 书上给了一个例子: class Foo{ void bar(); ...
- Pinhole类声明和实现
针孔相机,带旋转,移动等功能. 类声明: #pragma once #ifndef __PINHOLE_HEADER__ #define __PINHOLE_HEADER__ #include &qu ...
- 07——为多态基类声明为virtual析构函数
当基类确定被继承的时候,析构函数声明为virtual是必须的 当返回的派生类的指针或引用的时候,调用析构函数容易发生内存泄漏 当基类作为抽象类使用,声明pure virtual析构函数 析构函数的顺序 ...
随机推荐
- 用python解决打标签时将xml文件的标签名打错
用python解决打标签时将xml文件的标签名打错 问题描述:再进行达标签时将magnetic_tile的标签名错误的打成了magnetic_title,又不想一张一张的修改 出现问题的xml文件 & ...
- SpringBoot+Mybatis-Plus整合Sharding-JDBC5.1.1实现单库分表【全网最新】
一.前言 小编最近一直在研究关于分库分表的东西,前几天docker安装了mycat实现了分库分表,但是都在说mycat的bug很多.很多人还是倾向于shardingsphere,其实他是一个全家桶,有 ...
- 支付宝开放平台--网页&移动应用(一)
前提是先在支付宝上签约自己需要的支付宝功能,然后支付宝开放平台才能设置你需要的功能 一:支付宝开放平台登录 登录进入支付宝开放平台 二:根据自己的需求创建应用(我是用的网页&移动应用) 三:点 ...
- centos6搭建mysql
目前CentOS6.5及一下版本基本上被官方给放弃更新了,但是考虑到忠实粉丝迟迟不肯放手,所以还留了入口但是非常有限 1.搭建mysql 可参照:https://blog.csdn.net/huang ...
- 左右手切换工具xmouse v1.2版本发布
Xmouse 方便的切换鼠标左右键,因为功能非常简单,所以支持.net framework 2.0及以上 windows环境就可以了,目前已测试win7.win10可用. 关于为什么做这么个东西,那是 ...
- 领导:谁再用redis过期监听实现关闭订单,立马滚蛋!
日前拜读阿牛老师的大作 领导:谁再用定时任务实现关闭订单,立马滚蛋! 发现其方案有若干瑕疵,特此抛砖引玉讨论一二. 在电商.支付等领域,往往会有这样的场景,用户下单后放弃支付了,那这笔订单会在指定的时 ...
- Pisa-Proxy 之 SQL 解析实践
SQL 语句解析是一个重要且复杂的技术,数据库流量相关的 SQL 审计.读写分离.分片等功能都依赖于 SQL 解析,而 Pisa-Proxy 作为 Database Mesh 理念的一个实践,对数据库 ...
- nginx源码层面探究request_time、upstream_response_time、upstream_connect_time与upstream_header_time指标具体含义
背景概述 最近计划着重分析一下线上各api的HTTP响应耗时情况,检查是否有接口平均耗时.99分位耗时等相关指标过大的情况,了解到nginx统计请求耗时有四个指标:request_time.upstr ...
- 初学python常用,python模块安装和卸载的几种方法
兄弟们常常因为遇到模块不会安装,或者遇到报错就懵了,就很耽误学习进度,今天我们就一次性了解Python几种安装模块的方法~不过~ 实在是懒得看 点击此处找管理员小姐姐手把手教你安装 一.命令提示符窗口 ...
- 自己动手实现 HashMap(Python字典),彻底系统的学习哈希表(上篇)——不看血亏!!!
HashMap(Python字典)设计原理与实现(上篇)--哈希表的原理 在此前的四篇长文当中我们已经实现了我们自己的ArrayList和LinkedList,并且分析了ArrayList和Linke ...