Guest User

Untitled

a guest
Jan 6th, 2021
319
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. Title : A Simple CPU Side Ray Tracer
  3. Reference : https://raytracing.github.io/books/RayTracingInOneWeekend.html
  4. By : Samuel Wesley Rasquinha (@swr06)
  5. */
  6.  
  7. #define THREAD_SPAWN_COUNT 4
  8.  
  9. #include <stdio.h>
  10. #include <iostream>
  11. #include <array>
  12. #include <random>
  13. #include <string>
  14. #include <thread>
  15. #include <vector>
  16. #include <chrono>
  17. #include <memory>
  18.  
  19. #include <glad/glad.h>          
  20. #include <GLFW/glfw3.h>
  21.  
  22. #include <glm/glm.hpp>
  23.  
  24. #include "Core/Application.h"
  25. #include "Core/VertexBuffer.h"
  26. #include "Core/VertexArray.h"
  27. #include "Core/Shader.h"
  28.  
  29. using namespace RayTracer;
  30. typedef uint32_t uint;
  31. typedef unsigned char byte;
  32. typedef double floatp; // float precision
  33.  
  34. // Helpers
  35. struct i8vec2
  36. {
  37.     uint8_t x, y;
  38. };
  39.  
  40. struct i16vec2
  41. {
  42.     uint16_t x, y;
  43. };
  44.  
  45. class RGB
  46. {
  47. public:
  48.  
  49.     RGB(byte R, byte G, byte B)
  50.     {
  51.         r = R;
  52.         g = G;
  53.         b = B;
  54.     }
  55.  
  56.     RGB() : r(0), g(0), b(0)
  57.     {}
  58.  
  59.     inline glm::vec3 ToVec3() const noexcept
  60.     {
  61.         glm::vec3 vec;
  62.         vec.r = static_cast<float>(r);
  63.         vec.g = static_cast<float>(g);
  64.         vec.b = static_cast<float>(b);
  65.  
  66.         return vec;
  67.     }
  68.  
  69.     byte r;
  70.     byte g;
  71.     byte b;
  72. };
  73.  
  74. struct RayHitRecord
  75. {
  76.     glm::vec3 Point;
  77.     glm::vec3 Normal;
  78.     float T = 0.0f;
  79.     bool Inside = false;
  80. };
  81.  
  82. // Needs to be 16:9 aspect ratio
  83. // 1024, 576
  84. const uint g_Width = 1024;
  85. const uint g_Height = 576;
  86. GLubyte* const g_PixelData = new GLubyte[g_Width * g_Height * 3];
  87. GLuint g_Texture = 0;
  88.  
  89. std::unique_ptr<GLClasses::VertexBuffer> g_VBO;
  90. std::unique_ptr<GLClasses::VertexArray> g_VAO;
  91. std::unique_ptr<GLClasses::Shader> g_RenderShader;
  92.  
  93. // Utility
  94. const double _INFINITY = std::numeric_limits<double>::infinity();
  95. const double PI = 3.14159265354;
  96.  
  97. inline double RandomFloat()
  98. {
  99.     static std::uniform_real_distribution<float> distribution(0.0, 1.0);
  100.     static std::mt19937 generator;
  101.     return distribution(generator);
  102. }
  103.  
  104. inline float RandomFloat(float min, float max)
  105. {
  106.     return min + (max - min) * RandomFloat();
  107. }
  108.  
  109. /* Functions */
  110.  
  111. RGB ToRGB(const glm::ivec3& v)
  112. {
  113.     RGB rgb;
  114.     glm::ivec3 val = v;
  115.  
  116.     val.r = glm::clamp(val.r, 0, 255);
  117.     val.g = glm::clamp(val.g, 0, 255);
  118.     val.b = glm::clamp(val.b, 0, 255);
  119.  
  120.     rgb.r = static_cast<byte>(val.r);
  121.     rgb.g = static_cast<byte>(val.g);
  122.     rgb.b = static_cast<byte>(val.b);
  123.  
  124.     return rgb;
  125. }
  126.  
  127. RGB ToRGB(const glm::vec3& v)
  128. {
  129.     glm::vec3 val = v;
  130.     RGB rgb;
  131.  
  132.     glm::ivec3 _col = val;
  133.  
  134.     _col.r = glm::clamp(_col.r, 0, 255);
  135.     _col.g = glm::clamp(_col.g, 0, 255);
  136.     _col.b = glm::clamp(_col.b, 0, 255);
  137.  
  138.     rgb.r = static_cast<byte>(_col.r);
  139.     rgb.g = static_cast<byte>(_col.g);
  140.     rgb.b = static_cast<byte>(_col.b);
  141.  
  142.     return rgb;
  143. }
  144.  
  145. RGB ToRGBVec3_01(const glm::vec3& v)
  146. {
  147.     glm::vec3 val = v;
  148.     RGB rgb;
  149.  
  150.     val.x = v.x * 255.0f;
  151.     val.y = v.y * 255.0f;
  152.     val.z = v.z * 255.0f;
  153.  
  154.     glm::ivec3 _col = val;
  155.  
  156.     _col.r = glm::clamp(_col.r, 0, 255);
  157.     _col.g = glm::clamp(_col.g, 0, 255);
  158.     _col.b = glm::clamp(_col.b, 0, 255);
  159.  
  160.     rgb.r = static_cast<byte>(_col.r);
  161.     rgb.g = static_cast<byte>(_col.g);
  162.     rgb.b = static_cast<byte>(_col.b);
  163.  
  164.     return rgb;
  165. }
  166.  
  167. glm::vec3 Lerp(const glm::vec3& v1, const glm::vec3& v2, float t)
  168. {
  169.     return (1.0f - t) * v1 + t * v2;
  170. }
  171.  
  172. glm::vec3 ConvertTo0_1Range(const glm::vec3& v)
  173. {
  174.     return 0.5f * (v + 1.0f);
  175. }
  176.  
  177. class RayTracerApp : public Application
  178. {
  179. public:
  180.  
  181.     RayTracerApp()
  182.     {
  183.         m_Width = g_Width;
  184.         m_Height = g_Height;
  185.         memset(g_PixelData, 255, g_Width * g_Height * 3);
  186.     }
  187.  
  188.     void OnUserCreate(double ts) override
  189.     {
  190.  
  191.     }
  192.  
  193.     void OnUserUpdate(double ts) override
  194.     {
  195.  
  196.     }
  197.  
  198.     void OnImguiRender(double ts) override
  199.     {
  200.         ImGuiWindowFlags window_flags = 0;
  201.  
  202.         if (ImGui::Begin("Settings"))
  203.         {
  204.             ImGui::Text("Simple Ray Tracer v01 :)");
  205.  
  206.         }
  207.  
  208.         ImGui::End();
  209.     }
  210.  
  211.     void OnEvent(Event e) override
  212.     {
  213.  
  214.     }
  215.  
  216. };
  217.  
  218. RayTracerApp g_App;
  219.  
  220. /* Creating the ray traced texture */
  221. void InitializeForRender()
  222. {
  223.     g_VBO = std::unique_ptr<GLClasses::VertexBuffer>(new GLClasses::VertexBuffer);
  224.     g_VAO = std::unique_ptr<GLClasses::VertexArray>(new GLClasses::VertexArray);
  225.     g_RenderShader = std::unique_ptr<GLClasses::Shader>(new GLClasses::Shader);
  226.  
  227.     g_RenderShader->CreateShaderProgramFromFile("Core/Shaders/BasicVert.glsl", "Core/Shaders/BasicFrag.glsl");
  228.     g_RenderShader->CompileShaders();
  229.  
  230.     float Vertices[] =
  231.     {
  232.         -1.0f,  1.0f,  0.0f, 1.0f, -1.0f, -1.0f,  0.0f, 0.0f,
  233.          1.0f, -1.0f,  1.0f, 0.0f, -1.0f,  1.0f,  0.0f, 1.0f,
  234.          1.0f, -1.0f,  1.0f, 0.0f,  1.0f,  1.0f,  1.0f, 1.0f
  235.     };
  236.  
  237.     g_VAO->Bind();
  238.     g_VBO->Bind();
  239.     g_VBO->BufferData(sizeof(Vertices), Vertices, GL_STATIC_DRAW);
  240.     g_VBO->VertexAttribPointer(0, 2, GL_FLOAT, 0, 4 * sizeof(GLfloat), 0);
  241.     g_VBO->VertexAttribPointer(1, 2, GL_FLOAT, 0, 4 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
  242.     g_VAO->Unbind();
  243. }
  244.  
  245. void CreateRenderTexture()
  246. {
  247.     glCreateTextures(GL_TEXTURE_2D, 1, &g_Texture);
  248.     glBindTexture(GL_TEXTURE_2D, g_Texture);
  249.     glTextureStorage2D(g_Texture, 1, GL_RGB8, g_Width, g_Height);
  250.     glTextureParameteri(g_Texture, GL_TEXTURE_WRAP_S, GL_REPEAT);
  251.     glTextureParameteri(g_Texture, GL_TEXTURE_WRAP_T, GL_REPEAT);
  252.     glTextureParameteri(g_Texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  253.     glTextureParameteri(g_Texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  254.     glGenerateMipmap(GL_TEXTURE_2D);
  255. }
  256.  
  257. void BufferTextureData()
  258. {
  259.     glBindTexture(GL_TEXTURE_2D, g_Texture);
  260.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  261.     glTextureSubImage2D(g_Texture, 0, 0, 0, g_Width, g_Height, GL_RGB, GL_UNSIGNED_BYTE, g_PixelData);
  262. }
  263.  
  264. void Render()
  265. {
  266.     glDisable(GL_CULL_FACE);
  267.     glDisable(GL_DEPTH_TEST);
  268.     glBindFramebuffer(GL_FRAMEBUFFER, 0);
  269.  
  270.     g_RenderShader->Use();
  271.     g_RenderShader->SetInteger("u_Texture", 0);
  272.  
  273.     glActiveTexture(GL_TEXTURE0);
  274.     glBindTexture(GL_TEXTURE_2D, g_Texture);
  275.  
  276.     g_VAO->Bind();
  277.     glDrawArrays(GL_TRIANGLES, 0, 6);
  278.     g_VAO->Unbind();
  279. }
  280.  
  281. /* Pixel putter and getter functions */
  282.  
  283. inline void PutPixel(const glm::ivec2& loc, const RGB& col) noexcept
  284. {
  285.     if (loc.x >= g_Width || loc.y >= g_Height) { return; }
  286.  
  287.     uint _loc = (loc.x + loc.y * g_Width) * 3;
  288.     g_PixelData[_loc + 0] = col.r;
  289.     g_PixelData[_loc + 1] = col.g;
  290.     g_PixelData[_loc + 2] = col.b;
  291. }
  292.  
  293. RGB GetPixel(const glm::ivec2& loc)
  294. {
  295.     RGB col;
  296.     uint _loc = (loc.x + loc.y * g_Width) * 3;
  297.  
  298.     col.r = g_PixelData[_loc + 0];
  299.     col.g = g_PixelData[_loc + 1];
  300.     col.b = g_PixelData[_loc + 2];
  301.  
  302.     return col;
  303. }
  304.  
  305. /* Render Method */
  306. void DoRenderLoop()
  307. {
  308.     static unsigned long long m_CurrentFrame = 0;
  309.  
  310.     while (!glfwWindowShouldClose(g_App.GetWindow()))
  311.     {
  312.         if (m_CurrentFrame % 15 == 0)
  313.         {
  314.             BufferTextureData();
  315.         }
  316.  
  317.         glViewport(0, 0, g_Width, g_Height);
  318.  
  319.         g_App.OnUpdate();
  320.         Render();
  321.         g_App.FinishFrame();
  322.  
  323.         m_CurrentFrame++;
  324.     }
  325. }
  326.  
  327. /* Ray Tracing and Rendering Stuff Begins Here */
  328.  
  329. // Ray Tracing Constants
  330.  
  331. /* Helper Classes */
  332.  
  333. class Ray
  334. {
  335. public:
  336.  
  337.     Ray() : m_Origin(glm::vec3(0.0f)), m_Direction(glm::vec3(0.0f))
  338.     {  }
  339.  
  340.     Ray(const glm::vec3& origin, const glm::vec3& direction) :
  341.         m_Origin(origin), m_Direction(direction)
  342.     {
  343.         //
  344.     }
  345.  
  346.     inline const glm::vec3& GetOrigin() const noexcept
  347.     {
  348.         return m_Origin;
  349.     }
  350.  
  351.     inline const glm::vec3& GetDirection() const noexcept
  352.     {
  353.         return m_Direction;
  354.     }
  355.  
  356.     inline glm::vec3 GetAt(floatp scale) const noexcept
  357.     {
  358.         return m_Origin + (m_Direction * glm::vec3(scale));
  359.     }
  360.  
  361.     inline void SetOrigin(const glm::vec3& origin) noexcept
  362.     {
  363.         m_Origin = origin;
  364.     }
  365.  
  366.     inline void SetDirection(const glm::vec3& dir) noexcept
  367.     {
  368.         m_Direction = dir;
  369.     }
  370.  
  371. private:
  372.  
  373.     glm::vec3 m_Origin;
  374.     glm::vec3 m_Direction;
  375. };
  376.  
  377. enum class Material
  378. {
  379.     Invalid = -1,
  380.     Glass,
  381.     Diffuse,
  382.     Metal
  383. };
  384.  
  385. class Sphere
  386. {
  387. public:
  388.  
  389.     glm::vec3 Center;
  390.     glm::vec3 Color;
  391.     float Radius;
  392.     Material SphereMaterial;
  393.     float FuzzLevel;
  394.  
  395.     Sphere(const glm::vec3& center, const glm::vec3& color, float radius, Material mat, float fuzz = 0.0f) :
  396.         Center(center),
  397.         Color(color),
  398.         Radius(radius),
  399.         SphereMaterial(mat),
  400.         FuzzLevel(fuzz)
  401.     {
  402.  
  403.     }
  404.  
  405.     Sphere() :
  406.         Center(glm::vec3(0.0f)),
  407.         Color(glm::vec3(0.0f)),
  408.         Radius(0.0f),
  409.         SphereMaterial(Material::Invalid),
  410.         FuzzLevel(0.0f)
  411.     {
  412.  
  413.     }
  414. };
  415.  
  416. inline bool PointIsInSphere(const glm::vec3& point, float radius)
  417. {
  418.     return ((point.x * point.x) + (point.y * point.y) + (point.z * point.z)) < (radius * radius);
  419. }
  420.  
  421. inline glm::vec3 GeneratePointInUnitSphere()
  422. {
  423.     glm::vec3 ReturnVal;
  424.  
  425.     ReturnVal.x = RandomFloat(-1.0f, 1.0f);
  426.     ReturnVal.y = RandomFloat(-1.0f, 1.0f);
  427.     ReturnVal.z = RandomFloat(-1.0f, 1.0f);
  428.  
  429.     while (!PointIsInSphere(ReturnVal, 1.0f))
  430.     {
  431.         ReturnVal.x = RandomFloat(-1.0f, 1.0f);
  432.         ReturnVal.y = RandomFloat(-1.0f, 1.0f);
  433.         ReturnVal.z = RandomFloat(-1.0f, 1.0f);
  434.     }
  435.  
  436.     return ReturnVal;
  437. }
  438.  
  439. class Camera
  440. {
  441. public:
  442.  
  443.     Camera(const glm::vec3& lookfrom, const glm::vec3& lookat, const glm::vec3& up,
  444.         float fov) : m_FOV(fov)
  445.     {
  446.         float theta = glm::radians(fov);
  447.         float H = glm::tan(theta / 2.0f);
  448.  
  449.         m_ViewportHeight = 2.0f * H;
  450.         m_ViewportWidth = m_ViewportHeight * m_AspectRatio;
  451.  
  452.         auto w = glm::normalize(lookfrom - lookat);
  453.         auto u = glm::normalize(glm::cross(up, w));
  454.         auto v = glm::cross(w, u);
  455.  
  456.         m_Origin = lookfrom;
  457.         m_Horizontal = m_ViewportWidth * u;
  458.         m_Vertical = m_ViewportHeight * v;
  459.         m_BottomLeft = m_Origin - (m_Horizontal / 2.0f) - (m_Vertical / 2.0f) - w;
  460.  
  461.     }
  462.  
  463.     inline Ray GetRay(float u, float v) const
  464.     {
  465.         Ray ray(m_Origin, m_BottomLeft + (m_Horizontal * u) + (v * m_Vertical) - m_Origin);
  466.         return ray;
  467.     }
  468.  
  469. private:
  470.     glm::vec3 m_Origin = glm::vec3(0.0f);
  471.     const float m_AspectRatio = 16.0f / 9.0f; // Window aspect ratio. Easier to keep it as 16:9
  472.     const float m_FocalLength = 1.0f;
  473.  
  474.     // Viewport stuff
  475.     float m_ViewportHeight;
  476.     float m_ViewportWidth;
  477.     glm::vec3 m_Horizontal;
  478.     glm::vec3 m_Vertical;
  479.     glm::vec3 m_BottomLeft;
  480.  
  481.     float m_FOV;
  482. };
  483.  
  484. inline RGB GetGradientColorAtRay(const Ray& ray)
  485. {
  486.     const glm::vec3 ray_direction = ray.GetDirection();
  487.     glm::vec3 v = Lerp(glm::vec3(255.0f, 255.0f, 255.0f), glm::vec3(128.0f, 178.0f, 255.0f), ray_direction.y * 1.8f);
  488.  
  489.     return ToRGB(glm::ivec3(v));
  490. }
  491.  
  492. inline bool RaySphereIntersectionTest(const Sphere& sphere, const Ray& ray, float tmin, float tmax, RayHitRecord& hit_record)
  493. {
  494.     // p(t) = t²b⋅b+2tb⋅(A−C)+(A−C)⋅(A−C)−r² = 0
  495.     // The discriminant of this equation tells us the number of possible solutions
  496.     // we calculate that discriminant of the equation
  497.  
  498.     glm::vec3 oc = ray.GetOrigin() - sphere.Center;
  499.     float A = glm::dot(ray.GetDirection(), ray.GetDirection());
  500.     float B = 2.0 * glm::dot(oc, ray.GetDirection());
  501.     float C = dot(oc, oc) - sphere.Radius * sphere.Radius;
  502.     float Discriminant = B * B - 4 * A * C;
  503.  
  504.     if (Discriminant < 0)
  505.     {
  506.         return false;
  507.     }
  508.  
  509.     else
  510.     {
  511.         // Solve the quadratic equation and
  512.         // find t (T is the distance from the ray origin to the center of the sphere)
  513.         float root = (-B - glm::sqrt(Discriminant)) / (2.0f * A); // T
  514.  
  515.         if (root < tmin || root > tmax)
  516.         {
  517.             root = (-B + glm::sqrt(Discriminant)) / (2.0f * A);
  518.  
  519.             if (root < tmin || root > tmax)
  520.             {
  521.                 return false;
  522.             }
  523.         }
  524.  
  525.         // The root was found successfully
  526.         hit_record.T = root;
  527.         hit_record.Point = ray.GetAt(root);
  528.  
  529.         // TODO ! : CHECK THIS!
  530.         // SHOULD THE RADIUS BE MULTIPLIED HERE?
  531.         hit_record.Normal = (hit_record.Point - sphere.Center) / sphere.Radius;
  532.  
  533.         if (glm::dot(ray.GetDirection(), hit_record.Normal) > 0.0f)
  534.         {
  535.             hit_record.Normal = -hit_record.Normal;
  536.             hit_record.Inside = true;
  537.         }
  538.  
  539.         return true;
  540.     }
  541. }
  542.  
  543. std::vector<Sphere> Spheres =
  544. {
  545.     Sphere(glm::vec3(-1.0, 0.0, -1.0), glm::vec3(255, 0, 0), 0.5f, Material::Diffuse, 0.65f),
  546.     Sphere(glm::vec3(0.0, 0.0, -1.0), glm::vec3(0, 255, 0), 0.5f, Material::Diffuse),
  547.     Sphere(glm::vec3(1.0, 0.0, -1.0), glm::vec3(0, 0, 255), 0.5f, Material::Diffuse, 0.0f),
  548.     Sphere(glm::vec3(0.0f, -100.5f, -1.0f), glm::vec3(255, 0, 0), 100.0f, Material::Diffuse)
  549. };
  550.  
  551. bool IntersectSceneSpheres(const Ray& ray, float tmin, float tmax, RayHitRecord& closest_hit_rec, Sphere& sphere)
  552. {
  553.     RayHitRecord TempRecord;
  554.     bool HitAnything = false;
  555.     float ClosestDistance = tmax;
  556.  
  557.     for (auto& e : Spheres)
  558.     {
  559.         // T is the distance of ray origin to the sphere's center
  560.         // RaySphereIntersectionTest(e, ray, 0.0f, _INFINITY);
  561.  
  562.         if (RaySphereIntersectionTest(e, ray, tmin, ClosestDistance, TempRecord))
  563.         {
  564.             HitAnything = true;
  565.             ClosestDistance = TempRecord.T;
  566.             closest_hit_rec = TempRecord;
  567.             sphere = e;
  568.         }
  569.     }
  570.  
  571.     return HitAnything;
  572. }
  573.  
  574. const int SPP = 20;
  575. const int RAY_DEPTH = 5;
  576.  
  577. /* Non recursive and custom ray tracing model */
  578.  
  579. RGB GetRayColor(const Ray& ray)
  580. {
  581.     int hit_times = -1;
  582.  
  583.     Ray new_ray = ray;
  584.     Sphere hit_sphere;
  585.  
  586.     RayHitRecord ClosestSphere;
  587.     glm::vec3 FinalColor = glm::vec3(1.0f);
  588.     bool IntersectionFound = false;
  589.  
  590.     for (int i = 0; i < RAY_DEPTH; i++)
  591.     {
  592.         hit_times++;
  593.  
  594.         if (IntersectSceneSpheres(new_ray, 0.001f, _INFINITY, ClosestSphere, hit_sphere))
  595.         {
  596.             // Get the final ray direction
  597.  
  598.             glm::vec3 S = ClosestSphere.Normal + GeneratePointInUnitSphere();
  599.             new_ray.SetOrigin(ClosestSphere.Point);
  600.             new_ray.SetDirection(S);
  601.  
  602.             IntersectionFound = true;
  603.         }
  604.  
  605.         else
  606.         {
  607.             break;
  608.         }
  609.     }
  610.  
  611.     FinalColor = glm::vec3(0.0f, 0.0f, 255.0f);
  612.  
  613.     if (IntersectionFound)
  614.     {
  615.         //FinalColor /= 2.0f; // Lambertian diffuse only absorbs half the light
  616.         FinalColor = FinalColor / (float)hit_times;
  617.  
  618.         return ToRGB(FinalColor);
  619.     }
  620.  
  621.     return GetGradientColorAtRay(new_ray);
  622. }
  623.  
  624. /*Camera g_SceneCamera(glm::vec3(-2.0f, 2.0f, 1.0f),
  625.     glm::vec3(0.0f, 0.0f, -1.0f),
  626.     glm::vec3(0.0f, 1.0f, 0.0f),
  627.     90.0f);*/
  628.  
  629. Camera g_SceneCamera(glm::vec3(0.0f),
  630.     glm::vec3(0.0f, 0.0f, -1.0f),
  631.     glm::vec3(0.0f, 1.0f, 0.0f),
  632.     90.0f);
  633.  
  634. void TraceThreadFunction(int xstart, int ystart, int xsize, int ysize)
  635. {
  636.     for (int i = xstart; i < xstart + xsize; i++)
  637.     {
  638.         //std::this_thread::sleep_for(std::chrono::microseconds(8));
  639.  
  640.         for (int j = ystart; j < ystart + ysize; j++)
  641.         {
  642.             glm::vec3 FinalColor;
  643.  
  644.             for (int s = 0; s < SPP; s++)
  645.             {
  646.                 // Calculate the UV Coordinates
  647.  
  648.                 float u = ((float)i + RandomFloat()) / (float)g_Width;
  649.                 float v = ((float)j + RandomFloat()) / (float)g_Height;
  650.  
  651.                 Ray ray = g_SceneCamera.GetRay(u, v);
  652.                 RGB ray_color = GetRayColor(ray);
  653.  
  654.                 FinalColor.r += ray_color.r;
  655.                 FinalColor.g += ray_color.g;
  656.                 FinalColor.b += ray_color.b;
  657.             }
  658.  
  659.             FinalColor.r = (FinalColor.r / SPP);
  660.             FinalColor.g = (FinalColor.g / SPP);
  661.             FinalColor.b = (FinalColor.b / SPP);
  662.  
  663.             PutPixel(glm::ivec2(i, j), ToRGB(FinalColor));
  664.         }
  665.     }
  666. }
  667.  
  668. void TraceScene()
  669. {
  670.     const int sizex = g_Width / THREAD_SPAWN_COUNT;
  671.     const int sizey = g_Height;
  672.  
  673.     for (int t = 0; t < THREAD_SPAWN_COUNT; t++)
  674.     {
  675.         std::thread thread(TraceThreadFunction, sizex * t, 0, sizex, sizey);
  676.         thread.detach();
  677.  
  678.         std::this_thread::sleep_for(std::chrono::milliseconds(5));
  679.     }
  680. }
  681.  
  682. void WritePixelData()
  683. {
  684.     std::cout << std::endl << "Writing Pixel Data.." << std::endl;
  685.     std::cout << "Ray Tracing.." << std::endl;
  686.     TraceScene();
  687. }
  688.  
  689. int main()
  690. {
  691.     g_App.Initialize();
  692.     InitializeForRender();
  693.  
  694.     CreateRenderTexture();
  695.     WritePixelData();
  696.  
  697.     DoRenderLoop();
  698.  
  699.     return 0;
  700. }
Advertisement
Add Comment
Please, Sign In to add comment