当眼睛处于水中,产生类似的鱼眼视角,fov永远是psi_max的2倍。具体算法参考书籍。
类声明:
#pragma once #ifndef __FISHHOLE_HEADER__ #define __FISHHOLE_HEADER__ #include "camera.h" class Fishhole :public Camera { public: Fishhole(); ~Fishhole(); Fishhole(const Fishhole& fh); void set_fov(const ldouble fov); void set_angle(const ldouble deg); Vector3 ray_direction(const Point3& pp, const integer hres, const integer vres, const ldouble s, ldouble& r_squared) const; virtual Camera* clone() const; virtual void render_scene(World& w); Fishhole& operator=(const Fishhole& fh); private: ldouble psi_max;//fov/2 }; #endif
类实现:
#include "pch.h" #include "fishhole.h" #include "../utilities/world.h" #include "../utilities/viewplane.h" #include "../samplers/sampler.h" #include "../tracers/tracer.h" Fishhole::Fishhole() :Camera(), psi_max(180) {} Fishhole::~Fishhole() {} Fishhole::Fishhole(const Fishhole& fh) : Camera(fh), psi_max(fh.psi_max) {} void Fishhole::set_fov(const ldouble fov) { psi_max = fov / 2; } void Fishhole::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); } Vector3 Fishhole::ray_direction(const Point3& pp, const integer hres, const integer vres, const ldouble s, ldouble& r_squared) const { Point3 pn(2.0 / (s * hres) * pp.x, 2.0 / (s * vres) * pp.y, 0); r_squared = pn.x * pn.x + pn.y * pn.y; Vector3 dir; if (r_squared <= 1.0) { ldouble r = std::sqrt(r_squared); ldouble psi = r * radian(psi_max); ldouble sin_psi = std::sin(psi), cos_psi = std::cos(psi), sin_alpha = pn.y / r, cos_alpha = pn.x / r; dir = sin_psi * cos_alpha * u + sin_psi * sin_alpha * v - cos_psi * w; } return dir; } Camera* Fishhole::clone() const { return new Fishhole(*this); } void Fishhole::render_scene(World& w) { Ray ray; ViewPlane vp(w.vp); integer depth = 0; Point3 sp, pp; ldouble r_squared; w.open_window(vp.hres, vp.vres); ray.o = eye; vp.s = 1 / vp.s; 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; ray.d = ray_direction(pp, vp.hres, vp.vres, vp.s, r_squared); if (r_squared <= 1.0) color += w.tracer_ptr->trace_ray(ray); } color /= vp.nsamples; color *= exposure_time; w.display_pixel(r, c, color); } } Fishhole& Fishhole::operator=(const Fishhole& fh) { if (this == &fh) return *this; Camera::operator=(fh); psi_max = fh.psi_max; return *this; }
测试效果图(fov是180度):