Chapter 5. Surface normals and multiple objects.

You must first include iostream and fstream on top of this code.


#include "ray.h"

float hit_sphere(const vec3& center, float radius, const ray&r) {

vec3 oc = r.origin() - center;
float a = dot(r.direction(), r.direction());
float b = 2.0*dot(oc, r.direction());
float c = dot(oc, oc) - radius*radius;
float discriminant = b*b - 4 * a*c;

if (discriminant 0) {
vec3 N = unit_vector(r.point_at_parameter(t) - vec3(0, 0, -1));
return 0.5*vec3(N.x() + 1, N.y() + 1, N.z() + 1);
}

vec3 unit_direction = unit_vector(r.direction());
t = 0.5*(unit_direction.y() + 1.0);
return (1.0 - t)*vec3(1.0, 1.0, 1.0) + t*vec3(0.5, 0.7, 1.0);

}

int main() {

std::ofstream fout;
fout.open("D:\\RayTracer\\code0\\img\\Chap5_1.ppm");

int nx = 200;
int ny = 100;

fout << "P3\n" << nx << " " << ny <= 0; j--) {
for (int i = 0; i < nx; i++) {

float u = float(i) / float(nx);
float v = float(j) / float(ny);

ray r(origin, lower_left_corner + u*horizontal + v*vertical);

vec3 col = color(r);

int ir = int(255.99*col[0]);
int ig = int(255.99*col[1]);
int ib = int(255.99*col[2]);

fout << ir << " " << ig << " " << ib << "\n";
}
}

fout.close();

return 0;
}

This code outputs the following image.

chap5_1

Chapter 4: Adding a sphere

This is the modified version of main.cpp

You should first include iostream and fstream on top of this code.

This code outputs following image:
chap4


#include "ray.h"

bool hit_sphere(const vec3& center, float radius, const ray&r) {

vec3 oc = r.origin() - center;
float a = dot(r.direction(), r.direction());
float b = 2.0*dot(oc, r.direction());
float c = dot(oc, oc) - radius*radius;
float discriminant = b*b - 4 * a*c;
return (discriminant > 0);

}

vec3 color(const ray& r) {

if (hit_sphere(vec3(0, 0, -1), 0.5, r))
{
return vec3(1, 0, 0);
}

vec3 unit_direction = unit_vector(r.direction());
float t = 0.5*(unit_direction.y() + 1.0);
return (1.0 - t)*vec3(1.0, 1.0, 1.0) + t*vec3(0.5, 0.7, 1.0);

}

int main() {

std::ofstream fout;
fout.open("D:\\RayTracer\\code0\\img\\Chap4.ppm");

int nx = 200;
int ny = 100;

fout << "P3\n" << nx << " " << ny <= 0; j--) {
for (int i = 0; i < nx; i++) {

float u = float(i) / float(nx);
float v = float(j) / float(ny);

ray r(origin, lower_left_corner + u*horizontal + v*vertical);

vec3 col = color(r);

int ir = int(255.99*col[0]);
int ig = int(255.99*col[1]);
int ib = int(255.99*col[2]);

fout << ir << " " << ig << " " << ib << "\n";
}
}

fout.close();

return 0;
}

Chapter 3-2: Rays, a simple camera, and background

This is the code of main.cpp

You must first include iostream and fstream first on top of this code.


#include "ray.h"

vec3 color(const ray& r) {

vec3 unit_direction = unit_vector(r.direction());
float t = 0.5*(unit_direction.y() + 1.0);
return (1.0 - t)*vec3(1.0, 1.0, 1.0) + t*vec3(0.5, 0.7, 1.0);

}

int main() {

std::ofstream fout;
fout.open("D:\\RayTracer\\code0\\img\\Chap3.ppm");

int nx = 200;
int ny = 100;

fout << "P3\n" << nx << " " << ny <= 0; j--) {
for (int i = 0; i < nx; i++) {

float u = float(i) / float(nx);
float v = float(j) / float(ny);

ray r(origin, lower_left_corner + u*horizontal + v*vertical);

vec3 col = color(r);

int ir = int(255.99*col[0]);
int ig = int(255.99*col[1]);
int ib = int(255.99*col[2]);

fout << ir << " " << ig << " " << ib << "\n";
}
}

fout.close();

return 0;
}

This code outputs following image. 

chap3

Chapter2. The vec3 class

First include math.h, stdlib.h and iostream on top of this code.


class vec3 {

public:

vec3() {}
vec3(float e0, float e1, float e2) { e[0] = e0; e[1] = e1; e[2] = e2; }
inline float x() const { return e[0]; }
inline float y() const { return e[1]; }
inline float z() const { return e[2]; }
inline float r() const { return e[0]; }
inline float g() const { return e[1]; }
inline float b() const { return e[2]; }

//unary operator
inline const vec3& operator+() const { return *this; }
inline vec3 operator-() const { return vec3(-e[0], -e[1], -e[2]); }
inline float operator[] (int i) const{ return e[i]; }
inline float& 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 float t);
inline vec3& operator/=(const float t);

inline float length() const { return sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]); }
inline float squared_length() const { return e[0] * e[0] + e[1] * e[1] + e[2] * e[2]; }
inline void make_unit_vector();

float 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() {
float 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*(float t, const vec3 &v) {
return vec3(t * v.e[0], t * v.e[1], t * v.e[2]);
}

inline vec3 operator/(vec3 v, float t) {
return vec3(v.e[0] / t, v.e[1] / t, v.e[2] / t);
}

inline vec3 operator*(const vec3 &v, float t) {
return vec3(t * v.e[0], t * v.e[1], t * v.e[2]);
}

inline float 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 float t) {
e[0] *= t;
e[1] *= t;
e[2] *= t;
return *this;
}

inline vec3& vec3::operator/=(const float t) {

float 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();
}

 

Chapter 1. Output an image

This code outputs following PPM image.
test0

WordPress do not know how to handle brackets…
On top of this code, you should first include iostream, fstream.

#include "vec3.h"

int main() {

std::ofstream fout;
fout.open("D:\\RayTracer\\code0\\img\\test0.ppm");

int nx = 200;
int ny = 100;
fout << "P3\n" << nx << " " << ny <= 0; j--) {
for (int i = 0; i < nx; i++) {
float r = float(i) / float(nx);
float g = float(j) / float(ny);
float b = 0.2;
int ir = int(255.99*r);
int ig = int(255.99*g);
int ib = int(255.99*b);
fout << ir << " " << ig << " " << ib << "\n";
}
}

fout.close();

return 0;
}