SHARE
TWEET

Untitled

a guest May 22nd, 2019 459 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include<vector>
  2. #include<iostream>
  3. #include <algorithm>
  4. #include <chrono>
  5. using namespace std;
  6.  
  7. #include <glew.h>
  8. #include <freeglut.h>
  9.  
  10. #include "Vec3.h"
  11. #include "Image.h"
  12. #include "Ray.h"
  13. #include "Sphere.h"
  14. #include "algebra.h"
  15.  
  16.  
  17. Light * light = new Light(Vec3f(0.f, 0.f, 0.f), Vec3f(0.8f, 0.8f, 0.8f));
  18.  
  19. Vec3f * backgroundColor = new Vec3f(0.08f, 0.0f, 0.0209312f); //background color
  20. float ambientIntensity = 0.1f;
  21. int jumpLimit = 100;
  22. float phongShininessCoefficient = 1024.f;
  23. int xRes = 1440, yRes = 1080;
  24. Camera * _camera = new Camera(Vec3f(0.f, 0.f, 10.f), Vec3f(0.f, 0.f, 0.f), xRes, yRes);
  25. unsigned long int amount_of_intersections = 0;
  26.  
  27.  
  28.  
  29. class Scene {
  30. public:
  31.     vector<Sphere> spheres;
  32.  
  33.     Scene(void) {
  34.  
  35.     }
  36.     void add(const Sphere & s) {
  37.         spheres.push_back(s);
  38.         //cout << "Sphere added: " << "r = " << spheres[spheres.size()-1].r << endl;
  39.     }
  40.  
  41.     void load(char * fileName) {
  42.         // load a file with spheres for your scene here ...
  43.     }
  44.  
  45. };
  46.  
  47. void AddSpheres(Scene * scene);
  48.  
  49.  
  50. void glSetPixel(int x, int y, Vec3f & c) {
  51.     glColor3f(c.r, c.g, c.b);
  52.     glBegin(GL_POINTS);
  53.     glVertex2i(x, y);
  54.     glEnd();
  55. }
  56.  
  57. class SimpleRayTracer {
  58. private:
  59.     Scene * scene;
  60.     Image * image;
  61.  
  62.     Vec3f getEyeRayDirection(int x, int y) {
  63.         //Uses a fix camera looking along the negative z-axis
  64.         static float z = -5.0f;
  65.         static float sizeX = 4.0f;
  66.         static float sizeY = 3.0f;
  67.         static float left = -sizeX * 0.5f;
  68.         static float bottom = -sizeY * 0.5f;
  69.         static float dx = sizeX / float(image->getWidth());
  70.         static float dy = sizeY / float(image->getHeight());
  71.  
  72.         return Vec3f(left + x * dx, bottom + y * dy, z).normalize();
  73.     }
  74.  
  75.  
  76. public:
  77.     SimpleRayTracer(Scene * scene, Image * image) {
  78.         this->scene = scene;
  79.         this->image = image;
  80.     }
  81.  
  82.     void searchClosestHit(const Ray & ray, HitRec & hitRec) {
  83.         hitRec.anyHit = false;
  84.         hitRec.tHit = 0.f;
  85.         hitRec.primIndex = 0;
  86.         int closestHit = -1;
  87.         float smallestT = 0.f;
  88.         for (int i = 0; i < scene->spheres.size(); i++) {
  89.             amount_of_intersections++;
  90.             scene->spheres[i].hit(ray, hitRec);
  91.             if (hitRec.anyHit == true)
  92.             {
  93.                 if (hitRec.tHit < smallestT)
  94.                 {
  95.                     smallestT = hitRec.tHit;
  96.                     closestHit = i;
  97.                 }
  98.                 else if (smallestT == 0.f)
  99.                 {
  100.                     smallestT = hitRec.tHit;
  101.                     closestHit = i;
  102.                 }
  103.             }
  104.         }
  105.         hitRec.tHit = smallestT;
  106.         hitRec.primIndex = closestHit;
  107.     }
  108.  
  109.     float clamp(const float &lo, const float &hi, const float &v)
  110.     {
  111.         return std::max(lo, std::min(hi, v));
  112.     }
  113.     Vec3f refraction(const Vec3f &I, const Vec3f &N, float refractionIndex) {
  114.         float cosValue = clamp(-1.f, 1.f, DotProduct(I, N));
  115.         //float cosValue = 1;
  116.         float airRefraction = 1, sphereRefraction = refractionIndex;
  117.         Vec3f n = N;
  118.         float eta;
  119.  
  120.         if (cosValue < 0) { //if normal is going wrong direction we flip
  121.             cosValue = -cosValue;
  122.             eta = airRefraction / sphereRefraction;
  123.  
  124.         }
  125.         else {
  126.             swap(airRefraction, sphereRefraction);
  127.             n = -N;
  128.             eta = airRefraction;
  129.         }
  130.  
  131.         float k = 1 - eta * eta * (1 - cosValue * cosValue);
  132.         Vec3f temp;
  133.         temp.x = eta * I.x + n.x*(eta * cosValue - sqrt(k));
  134.         temp.y = eta * I.y + n.y*(eta * cosValue - sqrt(k));
  135.         temp.z = eta * I.z + n.z*(eta * cosValue - sqrt(k));
  136.         return k < 0 ? Vec3f(0.f, 0.f, 0.f) : temp;
  137.  
  138.  
  139.     }
  140.  
  141.     float fresnel(const Vec3f &I, const Vec3f &N, const float &refractionIndex) {
  142.         float cosValue = clamp(-1.f, 1.f, DotProduct(I, N));
  143.         float airRefraction = 1.f, sphereRefraction = refractionIndex;
  144.         if (cosValue > 0.f) {
  145.             swap(airRefraction, sphereRefraction);
  146.         }
  147.         float sinValue = airRefraction / sphereRefraction * sqrtf(max(0.f, 1.f - cosValue * cosValue));
  148.  
  149.         if (sinValue >= 1.f) {
  150.             return 1.0f;
  151.         }
  152.         else {
  153.             float cost = sqrtf(max(0.f, 1.f - sinValue * sinValue));
  154.             cosValue = fabsf(cosValue);
  155.             float Rs = ((sphereRefraction * cosValue) - (airRefraction * cost)) / ((sphereRefraction * cosValue) + (airRefraction * cost));
  156.             float Rp = ((airRefraction * cosValue) - (sphereRefraction * cost)) / ((airRefraction * cosValue) + (sphereRefraction * cost));
  157.             return (Rs * Rs + Rp * Rp) / 2.f; //kr is amount of light reflected
  158.         }
  159.  
  160.     }
  161.  
  162.     Vec3f RayCasting(Ray ray, Sphere sphere, float &t, int rayJump) {
  163.         if (rayJump >= jumpLimit)
  164.         {
  165.             return Vec3f(1.0, 1.0, 1.0);
  166.         }
  167.  
  168.         Vec3f color;
  169.  
  170.         Vec3f V = ray.d;
  171.         Vec3f P = Vec3f(ray.o + V * t);
  172.         Vec3f N = Vec3f(P - sphere.c);
  173.         N = N.normalize();
  174.  
  175.         Vec3f lightDirection = Vec3f(light->getPosition() - P);
  176.         lightDirection.normalize();
  177.  
  178.         Vec3f viewDirection = Vec3f(ray.o - P);
  179.         viewDirection.normalize();
  180.  
  181.         Vec3f lightReflection = Vec3f(Vec3f(N) * 2 * DotProduct(lightDirection, N));
  182.         lightReflection -= Vec3f(lightDirection);
  183.  
  184.         Vec3f viewReflection = Vec3f(Vec3f(N) * 2 * DotProduct(viewDirection, N));
  185.         viewReflection -= Vec3f(viewDirection);
  186.  
  187.         Vec3f refractedColor = Vec3f(0.f, 0.f, 0.f);
  188.  
  189.  
  190.         Ray reflectionRay;
  191.         reflectionRay.o = P;
  192.         reflectionRay.d = viewReflection;
  193.         Ray shadowRay;
  194.         shadowRay.o = P;
  195.         shadowRay.d = lightDirection;
  196.         HitRec hRec;
  197.         Vec3f reflectedColor = Vec3f(0.f, 0.f, 0.f);
  198.         Vec3f refractionDir, refractionRayOrig;
  199.         Ray refractionRay;
  200.  
  201.  
  202.         switch (sphere.type)
  203.         {
  204.         case Reflective:
  205.             searchClosestHit(shadowRay, hRec); //Checks point to lightsource for shadowing spheres
  206.             if (hRec.anyHit == true && scene->spheres[hRec.primIndex].type != Reflective_and_Refractive) //if transparent we wont shade
  207.             {
  208.                 color = CalculateLight(sphere, P, ray, lightReflection, lightDirection, N, true); //if true we stop phong model at ambient
  209.             }
  210.             else
  211.             {
  212.                 color = CalculateLight(sphere, P, ray, lightReflection, lightDirection, N, false);
  213.             }
  214.             color *= (1.f - sphere.reflectiveIndex);
  215.             color += reflectedColor * sphere.reflectiveIndex;
  216.  
  217.             searchClosestHit(reflectionRay, hRec);
  218.             if (hRec.anyHit == true)
  219.             {
  220.                 reflectedColor = RayCasting(reflectionRay, scene->spheres[hRec.primIndex], hRec.tHit, rayJump + 1);
  221.  
  222.                 if (reflectedColor.x < 0 || reflectedColor.y < 0 || reflectedColor.z < 0)
  223.                     cout << "NegativeColor!";
  224.  
  225.                 color *= (1.f - sphere.reflectiveIndex);
  226.                 color += reflectedColor * sphere.reflectiveIndex;
  227.             }
  228.  
  229.             break;
  230.         case Reflective_and_Refractive:
  231.  
  232.             refractionDir = refraction(V, N, sphere.refractiveIndex);
  233.             refractionDir = refractionDir.normalize();
  234.  
  235.             refractionRayOrig = (DotProduct(refractionDir, N) < 0) ?
  236.                 P - N * 0.0001 :
  237.                 P + N * 0.0001;
  238.             refractionRay.o = refractionRayOrig;//P - N*0.0001;
  239.             refractionRay.d = refractionDir;
  240.  
  241.             searchClosestHit(refractionRay, hRec);
  242.             if (hRec.anyHit = true)
  243.             {
  244.                 //Vec3f outP = (refractionRay.o + refractionRay.d*hRec.tHit);
  245.                 Vec3f outRefractionDir = refraction(refractionRayOrig, N, sphere.refractiveIndex);
  246.                 outRefractionDir = outRefractionDir.normalize();
  247.                 Vec3f outRefractionOrig = (DotProduct(outRefractionDir, N) < 0) ?
  248.                     refractionRayOrig - N * 0.0001 :
  249.                     refractionRayOrig + N * 0.0001;
  250.                 Ray outRay;
  251.                 outRay.o = outRefractionOrig;
  252.                 outRay.d = outRefractionDir;
  253.  
  254.                 refractedColor = RayCasting(outRay, scene->spheres[hRec.primIndex], hRec.tHit, rayJump + 1);
  255.  
  256.                 float kr = fresnel(V, N, sphere.refractiveIndex);
  257.  
  258.  
  259.                 color = reflectedColor * kr + refractedColor * (1.f - kr);
  260.             }
  261.             else
  262.                 color = reflectedColor;
  263.             break;
  264.         default: //for objects not reflective or refractive
  265.             searchClosestHit(shadowRay, hRec); //Checks point to lightsource for shadowing spheres
  266.             if (hRec.anyHit == true && scene->spheres[hRec.primIndex].type != Reflective_and_Refractive) //if transparent we wont shade
  267.             {
  268.                 color = CalculateLight(sphere, P, ray, lightReflection, lightDirection, N, true); //if true we stop phong model at ambient
  269.             }
  270.             else
  271.             {
  272.                 color = CalculateLight(sphere, P, ray, lightReflection, lightDirection, N, false);
  273.             }break;
  274.         }
  275.  
  276.  
  277.  
  278.  
  279.  
  280.         if (color.x < 0 || color.y < 0 || color.z < 0) //Failsafe to report if values get below 0 or cut them if they get to high and keep ratio between colours
  281.             cout << "NegativeColor!";
  282.  
  283.         if (color.x > 1)
  284.         {
  285.             float diff = 1 / color.x;
  286.             color *= diff;
  287.  
  288.         }
  289.         if (color.y > 1)
  290.         {
  291.             float diff = 1 / color.y;
  292.             color *= diff;
  293.         }
  294.         if (color.z > 1)
  295.         {
  296.             float diff = 1 / color.z;
  297.             color *= diff;
  298.         }
  299.  
  300.         return color;
  301.     }
  302.  
  303.     Vec3f CalculateLight(Sphere sphere, Vec3f HitPos, Ray ray, Vec3f reflectionDir, Vec3f lightDirection, Vec3f norm, bool isShadowed)
  304.     {
  305.         Vec3f ambient = light->getIntensity() * ambientIntensity;
  306.         ambient = ambient.multCoordwise(sphere.materialAmbient);
  307.  
  308.         Vec3f result = Vec3f(ambient);
  309.         if (isShadowed)
  310.             return result;
  311.  
  312.         float diff = max(norm.dot(lightDirection), 0.f);
  313.         Vec3f diffuse = Vec3f(sphere.materialDiffuse) * diff;
  314.         diffuse = diffuse.multCoordwise(light->getIntensity());
  315.  
  316.         Vec3f viewDir = Normalize(ray.o - HitPos);
  317.         float spec = pow(max(DotProduct(reflectionDir, viewDir), 0.f), phongShininessCoefficient);
  318.         Vec3f specular = Vec3f(sphere.materialSpecular * spec);
  319.         specular = specular.multCoordwise(light->getIntensity());
  320.  
  321.         result += diffuse + specular;
  322.         return result;
  323.     }
  324.  
  325.     void fireRays(void) {
  326.         Ray ray;
  327.         HitRec hitRec;
  328.         bool hit = false;
  329.         ray.o = _camera->eyePoint; //Set the start position of the eye rays to the origin of the camera
  330.  
  331.         for (int y = 0; y < image->getHeight(); y++) {
  332.             for (int x = 0; x < image->getWidth(); x++) {
  333.                 ray.d = getEyeRayDirection(x, y);
  334.                 hitRec.anyHit = false;
  335.                 searchClosestHit(ray, hitRec);
  336.                 if (hitRec.anyHit) {
  337.                     Vec3f color = Vec3f(0.f, 0.f, 0.f);
  338.                     color = RayCasting(ray, scene->spheres[hitRec.primIndex], hitRec.tHit, 0);
  339.                     image->setPixel(x, y, color);
  340.                     glSetPixel(x, y, color);
  341.                 }
  342.                 else {
  343.                     image->setPixel(x, y, *backgroundColor);
  344.                     glSetPixel(x, y, *backgroundColor);
  345.                 }
  346.             }
  347.         }
  348.     }
  349. };
  350.  
  351.  
  352.  
  353. SimpleRayTracer * rayTracer;
  354.  
  355. void display(void) {
  356.     auto start = chrono::steady_clock::now();
  357.     amount_of_intersections = 0;
  358.     glClear(GL_COLOR_BUFFER_BIT);
  359.  
  360.     glMatrixMode(GL_MODELVIEW);
  361.     glLoadIdentity();
  362.  
  363.     rayTracer->fireRays();
  364.     auto end = chrono::steady_clock::now();
  365.     cout << "Number of sphere intersection tests made to render this image: " << amount_of_intersections << "\n";
  366.     cout << "Elapsed time in nanoseconds: " << chrono::duration_cast<chrono::nanoseconds>(end - start).count() << " ns\n";
  367.     cout << "Elapsed time in microseconds: " << chrono::duration_cast<chrono::microseconds>(end - start).count() << " microseconds\n";
  368.     cout << "Elapsed time in milliseconds: " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << " ms\n";
  369.     cout << "Elapsed time in seconds: " << chrono::duration_cast<chrono::seconds>(end - start).count() << " sec\n";
  370.  
  371.  
  372.     glFlush();
  373. }
  374.  
  375. void changeSize(int w, int h) {
  376.     glMatrixMode(GL_PROJECTION);
  377.     glLoadIdentity();
  378.     gluOrtho2D(0, w, 0, h);
  379.     glViewport(0, 0, w, h);
  380. }
  381.  
  382. void init(void)
  383. {
  384.  
  385.     glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
  386.     glutInitWindowSize(xRes, yRes);
  387.     glutCreateWindow("SimpleRayTracer");
  388.     glutDisplayFunc(display);
  389.     glutReshapeFunc(changeSize);
  390.     //glutKeyboardFunc(keypress);
  391.  
  392.     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
  393.  
  394.     Scene * scene = new Scene;
  395.  
  396.  
  397.  
  398.     AddSpheres(scene);
  399.  
  400.  
  401.  
  402.  
  403.  
  404.     Image * image = new Image(xRes, yRes);
  405.  
  406.     rayTracer = new SimpleRayTracer(scene, image);
  407.  
  408. }
  409.  
  410. void AddSpheres(Scene * scene)
  411. {
  412.     scene->add(Sphere(Vec3f(3.78f, -3.0f, -20.0f), 3.0f));  //Orange stor
  413.     scene->spheres[0].materialDiffuse = Vec3f(1.f, 0.3f, 0.00f);
  414.     scene->spheres[0].materialSpecular = Vec3f(1.f, 0.5f, 0.0f);
  415.     scene->spheres[0].materialAmbient = Vec3f(1.f, 0.3f, 0.008f);
  416.     scene->spheres[0].reflectiveIndex = 0.f;
  417.     scene->spheres[0].refractiveIndex = 1.f;
  418.  
  419.  
  420.     scene->add(Sphere(Vec3f(-5.0f, -2.7f, -16.0f), 2.0f)); // Grön
  421.     scene->spheres[1].materialDiffuse = Vec3f(0.2f, 0.7f, 0.2f);
  422.     scene->spheres[1].materialSpecular = Vec3f(0.35f, 0.9f, 0.35f);
  423.     scene->spheres[1].materialAmbient = Vec3f(0.2f, 0.7f, 0.2f);
  424.     scene->spheres[1].reflectiveIndex = 0.f;
  425.     scene->spheres[1].refractiveIndex = 1.f;
  426.  
  427.     scene->add(Sphere(Vec3f(3.0f, 0.0f, -17.0f), 2.0f));  //Gul
  428.     scene->spheres[2].materialDiffuse = Vec3f(0.8f, 0.9f, 0.2f);
  429.     scene->spheres[2].materialSpecular = Vec3f(0.84f, 0.95f, 0.3f);
  430.     scene->spheres[2].materialAmbient = Vec3f(0.7f, 0.72f, 0.2f);
  431.     scene->spheres[2].reflectiveIndex = 0.f;
  432.     scene->spheres[2].refractiveIndex = 1.f;
  433.  
  434.     scene->add(Sphere(Vec3f(13.0f, 3.f, -40.0f), 15.0f));       //Gertrud
  435.     scene->spheres[3].materialDiffuse = Vec3f(0.4f, 0.4f, 0.97f);
  436.     scene->spheres[3].materialSpecular = Vec3f(0.5f, 0.5f, 0.97f);
  437.     scene->spheres[3].materialAmbient = Vec3f(0.4f, 0.4f, 0.97f);
  438.     scene->spheres[3].reflectiveIndex = 0.5f;
  439.     scene->spheres[3].refractiveIndex = 1.f;
  440.     scene->spheres[3].setType(Reflective);
  441.  
  442.     scene->add(Sphere(Vec3f(-6.0f, 5.0f, -27.0f), 2.0f));           //Blågrå badboll
  443.     scene->spheres[4].materialDiffuse = Vec3f(0.13f, 0.32f, 0.39f);
  444.     scene->spheres[4].materialSpecular = Vec3f(0.18f, 0.38f, 0.52f);
  445.     scene->spheres[4].materialAmbient = Vec3f(0.13f, 0.32f, 0.39f);
  446.     scene->spheres[4].reflectiveIndex = 0.38f;
  447.     scene->spheres[4].refractiveIndex = 1.f;
  448.     scene->spheres[4].setType(Reflective);
  449.  
  450.     scene->add(Sphere(Vec3f(4.0f, -2.f, -15.f), 1.5f));     //Röda lilla i mitten
  451.     scene->spheres[5].materialDiffuse = Vec3f(0.87f, 0.12f, 0.12f);
  452.     scene->spheres[5].materialSpecular = Vec3f(0.93f, 0.18f, 0.18f);
  453.     scene->spheres[5].materialAmbient = Vec3f(0.87f, 0.12f, 0.12f);
  454.     scene->spheres[5].reflectiveIndex = 0.5f;  
  455.     scene->spheres[5].refractiveIndex = 1.3f;
  456.     scene->spheres[5].setType(Reflective_and_Refractive);
  457.  
  458.     scene->add(Sphere(Vec3f(-7.0f, 0.0f, -30.0f), 4.0f));    //Blänkande rosa/lila på sidan
  459.     scene->spheres[6].materialDiffuse = Vec3f(0.7f, 0.38f, 0.78f);
  460.     scene->spheres[6].materialSpecular = Vec3f(0.9f, 0.45f, 0.93f);
  461.     scene->spheres[6].materialAmbient = Vec3f(0.7f, 0.38f, 0.78f);
  462.     scene->spheres[6].reflectiveIndex = 0.99;
  463.     scene->spheres[6].refractiveIndex = 1.f;
  464.     scene->spheres[6].setType(Reflective);
  465.  
  466.     scene->add(Sphere(Vec3f(0.0f, -2.0f, -12.0f), 2.0f));   //Bruna i mitten
  467.     scene->spheres[7].materialDiffuse = Vec3f(0.46f, 0.19f, 0.03f);
  468.     scene->spheres[7].materialSpecular = Vec3f(0.5f, 0.23f, 0.08f);
  469.     scene->spheres[7].materialAmbient = Vec3f(0.46f, 0.19f, 0.03f);
  470.     scene->spheres[7].reflectiveIndex = 0.f;
  471.     scene->spheres[7].refractiveIndex = 1.f;
  472.  
  473.     scene->add(Sphere(Vec3f(30.0f, 10.0f, -30.0f), 5.f));       //Lilla mörkgröna
  474.     scene->spheres[8].materialDiffuse = Vec3f(0.f, 0.56f, 0.00f);
  475.     scene->spheres[8].materialSpecular = Vec3f(0.f, 0.78f, 0.f);
  476.     scene->spheres[8].materialAmbient = Vec3f(0.0f, 0.56f, 0.0f);
  477.     scene->spheres[8].reflectiveIndex = 0.f;
  478.     scene->spheres[8].refractiveIndex = 1.f;
  479.  
  480.     /*scene->add(Sphere(Vec3f(-4.0f, -0.5f, -15.f), 1.0f));     //transparent
  481.     scene->spheres[9].materialDiffuse = Vec3f(0.87f, 0.12f, 0.12f);
  482.     scene->spheres[9].materialSpecular = Vec3f(0.93f, 0.18f, 0.18f);
  483.     scene->spheres[9].materialAmbient = Vec3f(0.87f, 0.12f, 0.12f);
  484.     scene->spheres[9].reflectiveIndex = 0.5f;
  485.     scene->spheres[9].refractiveIndex = 1.3f;
  486.     scene->spheres[9].setType(Reflective_and_Refractive);*/
  487. }
  488.  
  489. void main(int argc, char **argv) {
  490.     glutInit(&argc, argv);
  491.     init();
  492.     glutMainLoop();
  493. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top