Camer.h
#pragma once
#ifndef __CAMERA_H__
#define __CAMERA_H__
#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 lower_left_corner;
vec3 horizontal;
vec3 vertical;
vec3 origin;
};
#endif
hitable.h
#pragma once
#ifndef __HITABLE__H__
#define __HITABLE__H__
#include "ray.h"
struct hit_record {
float 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;
};
#endif
hitableist.h
#pragma once
#ifndef __HITABLELIST_H__
#define __HITABLELIST_H__
#include "hitable.h"
class hitable_list :public hitable {
public:
hitable_list() {};
hitable_list(hitable **l, int n) { list = l; list_size = n; }
virtual bool hit(const ray&r, float tmin, float tmax, hit_record& rec)const;
hitable **list;
int list_size;
};
#endif
main.cpp
#include <stdlib.h>
#ifdef _WIN64
#define GLUT_NO_LIB_PRAGMA
#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glut64.lib")
#endif
#ifdef _WIN32
#include "glut.h"
#include "glext.h"
#define GET_PROC_ADDRESS( str ) wglGetProcAddress( str )
#endif
#include "vec3.h"
#include "ray.h"
#define WIDTH 400
#define HEIGHT 200
unsigned char *Pixels;
#include "hitable.h"
#include "Sphere.h"
#include "hitablelist.h"
#define MAXFLOAT 20.0
#include "camera.h"
#include "time.h"
vec3 color(const ray&r, hitable *world) {
hit_record rec;
if (world->hit(r, 0.0, MAXFLOAT, rec))
return 0.5*vec3(rec.normal.x() + 1, rec.normal.y() + 1, rec.normal.z() + 1);
else {
vec3 unit_direction = unitVector(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);
}
}
void Draw(void) {
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawPixels(WIDTH, HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, Pixels);
glFlush();
}
int main() {
srand(time(NULL));
Pixels = (unsigned char*)malloc(WIDTH*HEIGHT * sizeof(unsigned char) * 4);
hitable *list[2];
list[0] = new sphere(vec3(0.0, 0.0, -2.0), 1.3);
list[1] = new sphere(vec3(0, 0, -0.5), 0.2);
hitable *world = new hitable_list(list, 2);
camera cam;
int ns = 100;
for (int j = 0; j < HEIGHT; j ++ ) {
for (int i = 0; i < WIDTH; i++ ) {
vec3 col(0, 0, 0);
for (int s = 0; s < ns; s++) {
float u = float(i + rand() / (RAND_MAX + 1.0)) / float(WIDTH);
float v = float(j + rand() / (RAND_MAX + 1.0)) / float(HEIGHT);
ray r = cam.get_ray(u, v);
vec3 p = r.pointAtParameter(2.0);
col += color(r, world);
}
col /= float(ns);
int offset = (WIDTH * j + i) * 4;
Pixels[offset + 0] = (unsigned char)255.99*col[0];
Pixels[offset + 1] = (unsigned char)255.99*col[1];
Pixels[offset + 2] = (unsigned char)255.99*col[2];
Pixels[offset + 3] = 255;
}
}
int argc = 0; char *argv = const_cast<char*>("");
glutInit(&argc, &argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowSize(WIDTH, HEIGHT);
glutCreateWindow("bitmap");
glutDisplayFunc(Draw);
glutMainLoop();
}
sphere.cpp
#include "sphere.h"
bool sphere::hit(const ray&r, float t_min, float t_max, hit_record&rec)const {
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) {
float temp = (-b - sqrt(discriminant)) / (2.0*a);
if (temp < t_max && temp > t_min) {
rec.t = temp;
rec.p = r.pointAtParameter(rec.t);
rec.normal = (rec.p - center) / radius;
return true;
}
temp = (-b + sqrt(discriminant)) / (2.0*a);
if (temp < t_max && temp > t_min) {
rec.t = temp;
rec.p = r.pointAtParameter(rec.t);
rec.normal = (rec.p - center) / radius;
return true;
}
}
return false;
}