1) Added descriptions to almost all of functions (needs check and additions)

2) Functions and structers were divided in different namespaces for better view
3) Some minor changes in CMakeLists.txt
pull/19/head
Victor Zadyabin 2020-03-09 16:04:26 +03:00
parent 9dbbdb547d
commit 17bf3d918a
5 changed files with 161 additions and 73 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required (VERSION 2.8)
project (tinyraytracer)
project (raytracer)
include(CheckCXXCompilerFlag)
@ -23,5 +23,5 @@ enable_cxx_compiler_flag_if_supported("-fopenmp")
file(GLOB SOURCES *.h *.cpp)
add_executable(${PROJECT_NAME} ${SOURCES})
add_executable(${PROJECT_NAME} ${SOURCES} raytracing/raytracing.cpp)

25
raytracer.cpp Normal file
View File

@ -0,0 +1,25 @@
#include "raytracing/raytracing.h"
int main() {
raytracing::entities::Material ivory(1.0, Vec4f(0.6, 0.3, 0.1, 0.0), Vec3f(0.4, 0.4, 0.3), 50.);
raytracing::entities::Material glass(1.5, Vec4f(0.0, 0.5, 0.1, 0.8), Vec3f(0.6, 0.7, 0.8), 125.);
raytracing::entities::Material red_rubber(1.0, Vec4f(0.9, 0.1, 0.0, 0.0), Vec3f(0.3, 0.1, 0.1), 10.);
raytracing::entities::Material mirror(1.0, Vec4f(0.0, 10.0, 0.8, 0.0), Vec3f(1.0, 1.0, 1.0), 1425.);
std::vector<raytracing::entities::Sphere> spheres;
spheres.push_back(raytracing::entities::Sphere(Vec3f(-3, 0, -16), 2, ivory));
spheres.push_back(raytracing::entities::Sphere(Vec3f(-1.0, -1.5, -12), 2, glass));
spheres.push_back(raytracing::entities::Sphere(Vec3f( 1.5, -0.5, -18), 3, red_rubber));
spheres.push_back(raytracing::entities::Sphere(Vec3f( 7, 5, -18), 4, mirror));
std::vector<raytracing::entities::Light> lights;
lights.push_back(raytracing::entities::Light(Vec3f(-20, 20, 20), 1.5));
lights.push_back(raytracing::entities::Light(Vec3f( 30, 50, -25), 1.8));
lights.push_back(raytracing::entities::Light(Vec3f( 30, 20, 30), 1.7));
raytracing::render(spheres, lights);
std::cout << "result is saved in build directory in file out.ppm" << std::endl;
return 0;
}

60
raytracing/entities.h Normal file
View File

@ -0,0 +1,60 @@
//
// Created by Виктор Задябин on 09.03.2020.
//
#ifndef TINYRAYTRACER_ENTITIES_H
#define TINYRAYTRACER_ENTITIES_H
namespace raytracing {
namespace entities {
struct Light {
/// Light is a source of light
/// \param p - position of light source
/// \param i - intensity of light source
Light(const Vec3f &p, const float i) : position(p), intensity(i) {}
Vec3f position;
float intensity;
};
struct Material {
/// Material is a
/// \param r
/// \param a
/// \param color
/// \param spec
Material(const float r, const Vec4f &a, const Vec3f &color, const float spec) : refractive_index(r),
albedo(a),
diffuse_color(color),
specular_exponent(spec) {}
Material() : refractive_index(1), albedo(1, 0, 0, 0), diffuse_color(), specular_exponent() {}
float refractive_index;
Vec4f albedo;
Vec3f diffuse_color;
float specular_exponent;
};
struct Sphere {
Vec3f center;
float radius;
Material material;
/// Sphere - object that constructed by
/// \param c - its center
/// \param r - its radius
/// \param m - its material
Sphere(const Vec3f &c, const float r, const Material &m) : center(c), radius(r), material(m) {}
/// ray_intersect - checks if ray intersects sphere
/// \param orig - position of light
/// \param dir - direction of light ray
/// \param t0 - coordinate of intersection
/// \return true if ray intersects sphere, false otherwise
bool ray_intersect(const Vec3f &orig, const Vec3f &dir, float &t0) const;
};
}// namespace entities
}
#endif //TINYRAYTRACER_ENTITIES_H

View File

@ -1,52 +1,27 @@
#define _USE_MATH_DEFINES
#include "raytracing.h"
#include <cmath>
#include <limits>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include "geometry.h"
struct Light {
Light(const Vec3f &p, const float i) : position(p), intensity(i) {}
Vec3f position;
float intensity;
};
struct Material {
Material(const float r, const Vec4f &a, const Vec3f &color, const float spec) : refractive_index(r), albedo(a), diffuse_color(color), specular_exponent(spec) {}
Material() : refractive_index(1), albedo(1,0,0,0), diffuse_color(), specular_exponent() {}
float refractive_index;
Vec4f albedo;
Vec3f diffuse_color;
float specular_exponent;
};
struct Sphere {
Vec3f center;
float radius;
Material material;
Sphere(const Vec3f &c, const float r, const Material &m) : center(c), radius(r), material(m) {}
bool ray_intersect(const Vec3f &orig, const Vec3f &dir, float &t0) const {
Vec3f L = center - orig;
float tca = L*dir;
float d2 = L*L - tca*tca;
if (d2 > radius*radius) return false;
float thc = sqrtf(radius*radius - d2);
t0 = tca - thc;
float t1 = tca + thc;
if (t0 < 0) t0 = t1;
if (t0 < 0) return false;
return true;
}
};
//TODO : description
/// reflect
/// \param I
/// \param N
/// \return
Vec3f reflect(const Vec3f &I, const Vec3f &N) {
return I - N*2.f*(I*N);
return I - N * 2.f * (I * N);
}
//TODO : description
/// refract
/// \param I
/// \param N
/// \param eta_t
/// \param eta_i
/// \return
Vec3f refract(const Vec3f &I, const Vec3f &N, const float eta_t, const float eta_i=1.f) { // Snell's law
float cosi = - std::max(-1.f, std::min(1.f, I*N));
if (cosi<0) return refract(I, -N, eta_i, eta_t); // if the ray comes from the inside the object, swap the air and the media
@ -55,7 +30,7 @@ Vec3f refract(const Vec3f &I, const Vec3f &N, const float eta_t, const float eta
return k<0 ? Vec3f(1,0,0) : I*eta + N*(eta*cosi - sqrtf(k)); // k<0 = total reflection, no ray to refract. I refract it anyways, this has no physical meaning
}
bool scene_intersect(const Vec3f &orig, const Vec3f &dir, const std::vector<Sphere> &spheres, Vec3f &hit, Vec3f &N, Material &material) {
bool scene_intersect(const Vec3f &orig, const Vec3f &dir, const std::vector<raytracing::entities::Sphere> &spheres, Vec3f &hit, Vec3f &N, raytracing::entities::Material &material) {
float spheres_dist = std::numeric_limits<float>::max();
for (size_t i=0; i < spheres.size(); i++) {
float dist_i;
@ -81,9 +56,17 @@ bool scene_intersect(const Vec3f &orig, const Vec3f &dir, const std::vector<Sphe
return std::min(spheres_dist, checkerboard_dist)<1000;
}
Vec3f cast_ray(const Vec3f &orig, const Vec3f &dir, const std::vector<Sphere> &spheres, const std::vector<Light> &lights, size_t depth=0) {
//TODO : description
/// cast_ray
/// \param orig
/// \param dir
/// \param spheres
/// \param lights
/// \param depth
/// \return
Vec3f cast_ray(const Vec3f &orig, const Vec3f &dir, const std::vector<raytracing::entities::Sphere> &spheres, const std::vector<raytracing::entities::Light> &lights, size_t depth=0) {
Vec3f point, N;
Material material;
raytracing::entities::Material material;
if (depth>4 || !scene_intersect(orig, dir, spheres, point, N, material)) {
return Vec3f(0.2, 0.7, 0.8); // background color
@ -103,7 +86,7 @@ Vec3f cast_ray(const Vec3f &orig, const Vec3f &dir, const std::vector<Sphere> &s
Vec3f shadow_orig = light_dir*N < 0 ? point - N*1e-3 : point + N*1e-3; // checking if the point lies in the shadow of the lights[i]
Vec3f shadow_pt, shadow_N;
Material tmpmaterial;
raytracing::entities::Material tmpmaterial;
if (scene_intersect(shadow_orig, light_dir, spheres, shadow_pt, shadow_N, tmpmaterial) && (shadow_pt-shadow_orig).norm() < light_distance)
continue;
@ -113,13 +96,38 @@ Vec3f cast_ray(const Vec3f &orig, const Vec3f &dir, const std::vector<Sphere> &s
return material.diffuse_color * diffuse_light_intensity * material.albedo[0] + Vec3f(1., 1., 1.)*specular_light_intensity * material.albedo[1] + reflect_color*material.albedo[2] + refract_color*material.albedo[3];
}
void render(const std::vector<Sphere> &spheres, const std::vector<Light> &lights) {
const int width = 1024;
const int height = 768;
const float fov = M_PI/3.;
namespace raytracing {
namespace entities{
bool Sphere::ray_intersect(const Vec3f &orig, const Vec3f &dir, float &t0) const {
Vec3f L = center - orig;
float tca = L*dir;
float d2 = L*L - tca*tca;
if (d2 > radius*radius) return false;
float thc = sqrtf(radius*radius - d2);
t0 = tca - thc;
float t1 = tca + thc;
if (t0 < 0) t0 = t1;
if (t0 < 0) return false;
return true;
}
}// namespace entities
void render(const std::vector<entities::Sphere> &spheres, const std::vector<entities::Light> &lights) {
const int width = 1920;
const int height = 1080;
const float fov = M_PI/3.; ///that's a viewing angle
std::vector<Vec3f> framebuffer(width*height);
#pragma omp parallel for
#pragma omp parallel for
for (size_t j = 0; j<height; j++) { // actual rendering loop
for (size_t i = 0; i<width; i++) {
float dir_x = (i + 0.5) - width/2.;
@ -143,25 +151,4 @@ void render(const std::vector<Sphere> &spheres, const std::vector<Light> &lights
ofs.close();
}
int main() {
Material ivory(1.0, Vec4f(0.6, 0.3, 0.1, 0.0), Vec3f(0.4, 0.4, 0.3), 50.);
Material glass(1.5, Vec4f(0.0, 0.5, 0.1, 0.8), Vec3f(0.6, 0.7, 0.8), 125.);
Material red_rubber(1.0, Vec4f(0.9, 0.1, 0.0, 0.0), Vec3f(0.3, 0.1, 0.1), 10.);
Material mirror(1.0, Vec4f(0.0, 10.0, 0.8, 0.0), Vec3f(1.0, 1.0, 1.0), 1425.);
std::vector<Sphere> spheres;
spheres.push_back(Sphere(Vec3f(-3, 0, -16), 2, ivory));
spheres.push_back(Sphere(Vec3f(-1.0, -1.5, -12), 2, glass));
spheres.push_back(Sphere(Vec3f( 1.5, -0.5, -18), 3, red_rubber));
spheres.push_back(Sphere(Vec3f( 7, 5, -18), 4, mirror));
std::vector<Light> lights;
lights.push_back(Light(Vec3f(-20, 20, 20), 1.5));
lights.push_back(Light(Vec3f( 30, 50, -25), 1.8));
lights.push_back(Light(Vec3f( 30, 20, 30), 1.7));
render(spheres, lights);
return 0;
}
}// namespace raytracing

16
raytracing/raytracing.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef TINYRAYTRACER_RAYTRACING_H
#define TINYRAYTRACER_RAYTRACING_H
#include "../geometry.h"
#include "entities.h"
namespace raytracing {
/// render - function for filling image with blue color, also for adding spheres and lights to
/// picture,
/// \param spheres - vector of spheres
/// \param lights - vector of lights
void render(const std::vector<entities::Sphere> &spheres, const std::vector<entities::Light> &lights);
}//namespace raytracing
#endif //TINYRAYTRACER_RAYTRACING_H