vec3.h
#pragma once
#include
#include
#include
class vec3
{
public:
vec3() {}
vec3(double e0, double e1, double e2) { e[0] = e0; e[1] = e1; e[2] = e2; }
inline double x() const { return e[0]; }
inline double y() const { return e[1]; }
inline double z() const { return e[2]; }
inline double r() const { return e[0]; }
inline double g() const { return e[1]; }
inline double b() const { return e[2]; }
inline const vec3& operator+() const { return *this; }
inline vec3 operator-() const { return vec3(-e[0], -e[1], -e[2]); }
inline double operator[](int i) const { return e[i]; }
inline double& operator[](int i) { return e[i]; }
inline vec3& operator+=(const vec3 &v2);
inline vec3& operator-=(const vec3 &v2);
inline vec3& operator*=(const vec3 &v2);
inline vec3& operator/=(const vec3 &v2);
inline vec3& operator*=(const double t);
inline vec3& operator/=(const double t);
inline double length() const { return sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]); }
inline double squared_length() const { return e[0] * e[0] + e[1] * e[1] + e[2] * e[2]; }
inline void make_unit_vector();
double e[3];
};
//文件读取流
inline std::istream& operator >> (std::istream &is, vec3 &t) {
is >> t.e[0] >> t.e[1] >> t.e[2];
return is;
}
//文件输出流
inline std::ostream& operator<<(std::ostream &os, const vec3 &t) {
os << t.e[0] << " " << t.e[1] << " " << t.e[2];
return os;
}
//规整化
inline void vec3::make_unit_vector() {
double k = 1.0 / sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]);
e[0] *= k; e[1] *= k; e[2] *= k;
}
inline vec3 operator+(const vec3 &v1, const vec3 &v2) {
return vec3(v1.e[0] + v2.e[0], v1.e[1] + v2.e[1], v1.e[2] + v2.e[2]);
}
inline vec3 operator-(const vec3 &v1, const vec3 &v2) {
return vec3(v1.e[0] - v2.e[0], v1.e[1] - v2.e[1], v1.e[2] - v2.e[2]);
}
inline vec3 operator*(const vec3 &v1, const vec3 &v2) {
return vec3(v1.e[0] * v2.e[0], v1.e[1] * v2.e[1], v1.e[2] * v2.e[2]);
}
inline vec3 operator/(const vec3 &v1, const vec3 &v2) {
return vec3(v1.e[0] / v2.e[0], v1.e[1] / v2.e[1], v1.e[2] / v2.e[2]);
}
inline vec3 operator*(double t, const vec3 &v) {
return vec3(t*v.e[0], t*v.e[1], t*v.e[2]);
}
inline vec3 operator/(vec3 v, double t) {
return vec3(v.e[0] / t, v.e[1] / t, v.e[2] / t);
}
inline vec3 operator*(const vec3 &v, double t) {
return vec3(t*v.e[0], t*v.e[1], t*v.e[2]);
}
inline double dot(const vec3 &v1, const vec3 &v2) {
return v1.e[0] * v2.e[0] + v1.e[1] * v2.e[1] + v1.e[2] * v2.e[2];
}
inline vec3 cross(const vec3 &v1, const vec3 &v2) {
return vec3((v1.e[1] * v2.e[2] - v1.e[2] * v2.e[1]),
(-(v1.e[0] * v2.e[2] - v1.e[2] * v2.e[0])),
(v1.e[0] * v2.e[1] - v1.e[1] * v2.e[0]));
}
inline vec3& vec3::operator+=(const vec3 &v) {
e[0] += v.e[0];
e[1] += v.e[1];
e[2] += v.e[2];
return *this;
}
inline vec3& vec3::operator*=(const vec3 &v) {
e[0] *= v.e[0];
e[1] *= v.e[1];
e[2] *= v.e[2];
return *this;
}
inline vec3& vec3::operator/=(const vec3 &v) {
e[0] /= v.e[0];
e[1] /= v.e[1];
e[2] /= v.e[2];
return *this;
}
inline vec3& vec3::operator-=(const vec3& v) {
e[0] -= v.e[0];
e[1] -= v.e[1];
e[2] -= v.e[2];
return *this;
}
inline vec3& vec3::operator*=(const double t) {
e[0] *= t;
e[1] *= t;
e[2] *= t;
return *this;
}
inline vec3& vec3::operator/=(const double t) {
double k = 1.0 / t;
e[0] *= k;
e[1] *= k;
e[2] *= k;
return *this;
}
inline vec3 unit_vector(vec3 v) {
return v / v.length();
}
#pragma once
#include "vec3.h"
class ray
{
public:
ray() = default;
ray(const vec3& a, const vec3& b, double ti = 0) { A = a; B = b; _time = ti; }
vec3 origin() const { return A; }
vec3 direction() const { return B; }
double time() const { return _time; }
vec3 point_at_parameter(double t) const { return A + t * B; }
vec3 A;
vec3 B;
double _time;
};
#pragma once
#include "Ray.h"
struct hit_record
{
double t;
vec3 p;
vec3 normal;
};
class hitable
{
public:
virtual bool hit(const ray& r, float t_min, float t_max, hit_record& rec) const = 0;
};
class sphere : public hitable
{
public:
sphere() = default;
sphere(vec3 cen, float r) : center(cen), radius(r){}
virtual bool hit(const ray& r, float t_min, float t_max, hit_record& rec) const override
{
vec3 oc = r.origin() - center;
double a = dot(r.direction(), r.direction());
double b = dot(oc, r.direction());
double c = dot(oc, oc) - radius * radius;
double discripminant = b * b - a * c;
if (discripminant > 0)
{
double temp = (-b - sqrt(b * b - a * c)) / a;
if (temp < t_max && temp > t_min)
{
rec.t = temp;
rec.p = r.point_at_parameter(rec.t);
rec.normal = (rec.p - center) / radius;
return true;
}
}
return false;
}
vec3 center;
float radius;
};
class hitable_list : public hitable
{
public:
hitable_list() = default;
hitable_list(hitable **l, int n)
{
list = l;
list_size = n;
}
virtual bool hit(const ray& r, float t_min, float t_max, hit_record& rec) const override
{
hit_record temp_rec;
bool hit_anything = false;
double closest_so_far = t_max;
for (int i = 0; ihit(r,t_min,closest_so_far,temp_rec))
{
hit_anything = true;
closest_so_far = temp_rec.t;
rec = temp_rec;
}
}
return hit_anything;
}
hitable **list;
int list_size;
};
Camera.h
#pragma once
#include "Ray.h"
class camera
{
public:
camera()
{
lower_left_corner = vec3(-2.0, -1.0, -1.0);
horizontal = vec3(4.0, 0.0, 0.0);
vertical = vec3(0.0, 2.0, 0.0);
origin = vec3(0.0, 0.0, 0.0);
}
ray get_ray(float u, float v)
{
return ray(origin, lower_left_corner + u * horizontal + v * vertical - origin);
}
vec3 origin;
vec3 lower_left_corner;
vec3 horizontal;
vec3 vertical;
};
#include
#include
#include "Ray.h"
#include "float.h"
#include "HitShap.h"
#include "Camera.h"
#include
#include
std::default_random_engine reng(time(nullptr));
std::uniform_real_distribution uni_dist(0.0f, 1.0f);
using namespace std;
vec3 radom_unit_sphere()
{
vec3 p;
do
{
p = 2.0 * vec3(uni_dist(reng), uni_dist(reng), uni_dist(reng)) - vec3(1.0f, 1.0f, 1.0f);
} while (p.squared_length() >= 1.0);
return p;
}
vec3 color(const ray& r, hitable* world)
{
hit_record rec;
if (world->hit(r, 0.0f, DBL_MAX, rec))
{
vec3 target = rec.p + rec.normal + radom_unit_sphere();
return 0.5f * color(ray(rec.p, target - rec.p), world);
}
else
{
vec3 unit_direction = unit_vector(r.direction());
double t = 0.5f * (unit_direction.y() + 1.0);
return (1.0f - t) * vec3(1.0f, 1.0f, 1.0f) + t * vec3(0.5f, 0.7f, 1.0f);
}
}
int main()
{
int nx = 600;
int ny = 300;
int ns = 64;
ofstream fout("image.ppm");
fout << "P3\n" << nx << " " << ny << "\n255\n";
cout << "渲染中。。。。" << endl;
hitable *list[2];
list[0] = new sphere(vec3(0, 0, -1), 0.5);
list[1] = new sphere(vec3(0, -100.5, -1), 100);
hitable* world = new hitable_list(list, 2);
camera cam;
for (int j = ny - 1; j >= 0; j--)
{
for (int i = 0; i < nx; i++)
{
vec3 col(0, 0, 0);
for (int s = 0; s < ns; s++)
{
float u = float(i) / float(nx);
float v = float(j) / float(ny);
ray r = cam.get_ray(u, v);
vec3 p = r.point_at_parameter(2.0);
col += color(r, world);
}
col /= float(ns);
col = vec3(sqrt(col[0]), sqrt(col[1]), sqrt(col[2]));
int ir = int(255.99f * col[0]);
int ig = int(255.99f * col[1]);
int ib = int(255.99f * col[2]);
fout << ir << " " << ig << " " << ib << "\n";
}
}
cout << "渲染完毕" << endl;
fout.close();
//system("Pause");
}