Advertisement
Guest User

Untitled

a guest
May 22nd, 2019
474
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.04 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement