Advertisement
Guest User

Untitled

a guest
Oct 31st, 2014
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.26 KB | None | 0 0
  1. #include<cstdlib>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<fstream>
  5. #include<vector>
  6. #include<iostream>
  7. #include<cassert>
  8. #ifdef __linux__
  9. #else
  10. #define M_PI 3.141592653589793
  11. #define INFINITY 1e8
  12. #endif
  13. template<typename T>
  14. class Vec3
  15. {
  16. public:
  17.     T x, y, z;
  18.     Vec3() :x(T(0)), y(T(0)), z(T(0)){}
  19.     Vec3(T xx) :x(xx), y(xx), z(xx){}
  20.     Vec3(T xx, T yy, T zz) :x(xx), y(yy), z(zz){}
  21.     Vec3&normalize()
  22.     {
  23.         T nor2 = length2();
  24.         if (nor2>0){
  25.             T invNor = 1 / sqrt(nor2);
  26.             x *= invNor, y *= invNor, z *= invNor;
  27.         }
  28.         return*this;
  29.     }
  30.     Vec3<T>operator*(const T&f)const{ return Vec3<T>(x*f, y*f, z*f); }
  31.     Vec3<T>operator*(const Vec3<T>&v)const{ return Vec3<T>(x*v.x, y*v.y, z*v.z); }
  32.     T dot(const Vec3<T>&v)const{ return x*v.x + y*v.y + z*v.z; }
  33.     Vec3<T>operator-(const Vec3<T>&v)const{ return Vec3<T>(x - v.x, y - v.y, z - v.z); }
  34.     Vec3<T>operator+(const Vec3<T>&v)const{ return Vec3<T>(x + v.x, y + v.y, z + v.z); }
  35.     Vec3<T>&operator+=(const Vec3<T>&v){ x += v.x, y += v.y, z += v.z; return*this; }
  36.     Vec3<T>&operator*=(const Vec3<T>&v){ x *= v.x, y *= v.y, z *= v.z; return*this; }
  37.     Vec3<T>operator-()const{ return Vec3<T>(-x, -y, -z); }
  38.     T length2()const{ return x*x + y*y + z*z; }
  39.     T length()const{ return sqrt(length2()); }
  40.     friend std::ostream&operator<<(std::ostream&os, const Vec3<T>&v)
  41.     {
  42.         os << "[" << v.x << " " << v.y << " " << v.z << "]";
  43.         return os;
  44.     }
  45. };
  46. template<typename T>
  47. class Sphere
  48. {
  49. public:
  50.     Vec3<T>center;
  51.     T radius, radius2;
  52.     Vec3<T>surfaceColor, emissionColor;
  53.     T transparency, reflection;
  54.     Sphere(const Vec3<T>&c, const T&r, const Vec3<T>&sc,
  55.         const T&refl = 0, const T&transp = 0, const Vec3<T>&ec = 0) :
  56.         center(c), radius(r), radius2(r*r), surfaceColor(sc), emissionColor(ec),
  57.         transparency(transp), reflection(refl)
  58.     {}
  59.     bool intersect(const Vec3<T>&rayorig, const Vec3<T>&raydir, T*t0 = NULL, T*t1 = NULL)const
  60.     {
  61.         Vec3<T>l = center - rayorig;
  62.         T tca = l.dot(raydir);
  63.         if (tca<0)return false;
  64.         T d2 = l.dot(l) - tca*tca;
  65.         if (d2>radius2)return false;
  66.         T thc = sqrt(radius2 - d2);
  67.         if (t0 != NULL&&t1 != NULL){
  68.             *t0 = tca - thc;
  69.             *t1 = tca + thc;
  70.         }
  71.         return true;
  72.     }
  73. };
  74. #define MAX_RAY_DEPTH 5
  75. template<typename T>
  76. T mix(const T&a, const T&b, const T&mix)
  77. {
  78.     return b*mix + a*(T(1) - mix);
  79. }
  80. float min(float i, float j){ return(i<j ? i : j); }
  81. float max(float i, float j){ return(i>j ? i : j); }
  82. template<typename T>
  83. Vec3<T>trace(const Vec3<T>&rayorig, const Vec3<T>&raydir,
  84.     const std::vector<Sphere<T>*>&spheres, const int&depth)
  85. {
  86.     T tnear = INFINITY;
  87.     const Sphere<T>*sphere = NULL;
  88.     for (unsigned i = 0; i<spheres.size(); ++i){
  89.         T t0 = INFINITY, t1 = INFINITY;
  90.         if (spheres[i]->intersect(rayorig, raydir, &t0, &t1)){
  91.             if (t0<0)t0 = t1;
  92.             if (t0<tnear){
  93.                 tnear = t0;
  94.                 sphere = spheres[i];
  95.             }
  96.         }
  97.     }
  98.     if (!sphere)return Vec3<T>(2);
  99.     Vec3<T>surfaceColor = 0;
  100.     Vec3<T>phit = rayorig + raydir*tnear;
  101.     Vec3<T>nhit = phit - sphere->center;
  102.     nhit.normalize();
  103.     T bias = 1e-4;
  104.     bool inside = false;
  105.     if (raydir.dot(nhit)>0)nhit = -nhit, inside = true;
  106.     if ((sphere->transparency>0 || sphere->reflection>0) && depth<MAX_RAY_DEPTH){
  107.         T facingratio = -raydir.dot(nhit);
  108.         T fresneleffect = mix<T>(pow(1 - facingratio, 3), 1, 0.1);
  109.         Vec3<T>refldir = raydir - nhit * 2 * raydir.dot(nhit);
  110.         refldir.normalize();
  111.         Vec3<T>reflection = trace(phit + nhit*bias, refldir, spheres, depth + 1);
  112.         Vec3<T>refraction = 0;
  113.         if (sphere->transparency){
  114.             T ior = 1.1, eta = (inside) ? ior : 1 / ior;
  115.             T cosi = -nhit.dot(raydir);
  116.             T k = 1 - eta*eta*(1 - cosi*cosi);
  117.             Vec3<T>refrdir = raydir*eta + nhit*(eta*cosi - sqrt(k));
  118.             refrdir.normalize();
  119.             refraction = trace(phit - nhit*bias, refrdir, spheres, depth + 1);
  120.         }
  121.         surfaceColor = (reflection*fresneleffect +
  122.             refraction*(1 - fresneleffect)*sphere->transparency)*sphere->surfaceColor;
  123.     }
  124.     else{
  125.         for (unsigned i = 0; i<spheres.size(); ++i){
  126.             if (spheres[i]->emissionColor.x>0){
  127.                 Vec3<T>transmission = 1;
  128.                 Vec3<T>lightDirection = spheres[i]->center - phit;
  129.                 lightDirection.normalize();
  130.                 for (unsigned j = 0; j<spheres.size(); ++j){
  131.                     if (i != j){
  132.                         T t0, t1;
  133.                         if (spheres[j]->intersect(phit + nhit*bias, lightDirection, &t0, &t1)){
  134.                             transmission = 0;
  135.                             break;
  136.                         }
  137.                     }
  138.                 }
  139.                 surfaceColor += sphere->surfaceColor*transmission*
  140.                     max(T(0), nhit.dot(lightDirection))*spheres[i]->emissionColor;
  141.             }
  142.         }
  143.     }
  144.     return surfaceColor + sphere->emissionColor;
  145. }
  146. template<typename T>
  147. void render(const std::vector<Sphere<T>*>&spheres)
  148. {
  149.     unsigned width = 64, height = 64;
  150.     Vec3<T>*image = new Vec3<T>[width*height], *pixel = image;
  151.     T invWidth = 1 / T(width), invHeight = 1 / T(height);
  152.     T fov = 90, aspectratio = width / T(height);
  153.     T angle = tan(M_PI*0.5*fov / T(180));
  154.     for (unsigned y = 0; y<height; ++y){
  155.         for (unsigned x = 0; x<width; ++x, ++pixel){
  156.             T xx = (2 * ((x + 0.5)*invWidth) - 1)*angle*aspectratio;
  157.             T yy = (1 - 2 * ((y + 0.5)*invHeight))*angle;
  158.             Vec3<T>raydir(xx, yy, -1);
  159.             raydir.normalize();
  160.             *pixel = trace(Vec3<T>(0), raydir, spheres, 0);
  161.         }
  162.     }
  163.     std::ofstream ofs("./untitled.ppm", std::ios::out | std::ios::binary);
  164.     ofs << "P6\n" << width << " " << height << "\n255\n";
  165.     for (unsigned i = 0; i<width*height; ++i){
  166.         ofs << (unsigned char)(min(T(1), image[i].x) * 255) <<
  167.             (unsigned char)(min(T(1), image[i].y) * 255) <<
  168.             (unsigned char)(min(T(1), image[i].z) * 255);
  169.     }
  170.     ofs.close();
  171.     delete[]image;
  172. }
  173. int main(int argc, char**argv)
  174. {
  175.     std::vector<Sphere<float>*>spheres;
  176.     spheres.push_back(new Sphere<float>(Vec3<float>(0, -10004, -20), 10000, Vec3<float>(0.2), 0, 0.0));
  177.     spheres.push_back(new Sphere<float>(Vec3<float>(0, 0, -20), 4, Vec3<float>(1.00, 0.32, 0.36), 0, 0.0));
  178.     spheres.push_back(new Sphere<float>(Vec3<float>(5, -1, -15), 2, Vec3<float>(0.90, 0.76, 0.46), 0, 0.0));
  179.     spheres.push_back(new Sphere<float>(Vec3<float>(5, 0, -25), 3, Vec3<float>(0.65, 0.77, 0.97), 0, 0.0));
  180.     spheres.push_back(new Sphere<float>(Vec3<float>(-5.5, 0, -15), 3, Vec3<float>(0.90, 0.90, 0.90), 0, 0.0));
  181.     spheres.push_back(new Sphere<float>(Vec3<float>(0, 20, -30), 3, Vec3<float>(0), 0, 0, Vec3<float>(3)));
  182.     render<float>(spheres);
  183.     while (!spheres.empty()){
  184.         Sphere<float>*sph = spheres.back();
  185.         spheres.pop_back();
  186.         delete sph;
  187.     }
  188.     return 0;
  189. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement