当眼睛处于水中,产生类似的鱼眼视角,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度):

posted on 2020-04-07 04:28  dalgleish  阅读(198)  评论(0编辑  收藏  举报