Guest User

Ray Tracing Fragment Shader

a guest
Jan 6th, 2021
283
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #version 330 core
  2.  
  3. #define MAX_RAY_HIT_DISTANCE 100000.0f
  4. #define PI 3.14159265354f
  5. #define RAY_BOUNCE_LIMIT 5
  6. #define SAMPLES_PER_PIXEL 100
  7. #define MAX_SPHERES 5
  8.  
  9. out vec3 o_Color;
  10.  
  11. in vec2 v_TexCoords;
  12.  
  13. // Structures
  14.  
  15. // Ray
  16. struct Ray
  17. {
  18.     vec3 Origin;
  19.     vec3 Direction;
  20. };
  21.  
  22. vec3 Ray_GetAt(Ray ray, float scale)
  23. {
  24.     return ray.Origin + (ray.Direction * vec3(scale));
  25. }
  26.  
  27. // "Enums"
  28. const uint MATERIAL_METAL = 0x00000001u;
  29. const uint MATERIAL_DIFFUSE = 0x00000002u;
  30. const uint MATERIAL_INVALID = 0x00000004u;
  31.  
  32. // Sphere
  33. struct Sphere
  34. {
  35.     vec3 Center;
  36.     vec3 Color;
  37.     float Radius;
  38.     uint Material;
  39.     float FuzzLevel;
  40. };
  41.  
  42. // Ray hit record
  43. struct RayHitRecord
  44. {
  45.     vec3 Point;
  46.     vec3 Normal;
  47.     float T;
  48.     bool Inside;
  49.     bool Hit;
  50.     Sphere sphere;
  51. };
  52.  
  53. // Uniforms
  54. uniform vec2 u_ViewportDimensions;
  55. uniform float u_Time;
  56.  
  57. // Camera related uniforms
  58. uniform vec3 u_CameraBottomLeft;
  59. uniform vec3 u_CameraHorizontal;
  60. uniform vec3 u_CameraVertical;
  61. uniform vec3 u_CameraOrigin;
  62.  
  63. // Spheres
  64. uniform Sphere u_SceneSpheres[MAX_SPHERES];
  65. uniform int u_SceneSphereCount;
  66.  
  67. // Functions
  68.  
  69. vec3 lerp(vec3 v1, vec3 v2, float t);
  70. vec3 GetGradientColorAtRay(Ray ray);
  71.  
  72. // Utility
  73.  
  74. int RNG_SEED = 0;
  75.  
  76. vec3 lerp(vec3 v1, vec3 v2, float t)
  77. {
  78.     return (1.0f - t) * v1 + t * v2;
  79. }
  80.  
  81. int MIN = -2147483648;
  82. int MAX = 2147483647;
  83.  
  84. int xorshift(in int value)
  85. {
  86.     // Xorshift*32
  87.     // Based on George Marsaglia's work: http://www.jstatsoft.org/v08/i14/paper
  88.     value ^= value << 13;
  89.     value ^= value >> 17;
  90.     value ^= value << 5;
  91.     return value;
  92. }
  93.  
  94. int nextInt(inout int seed)
  95. {
  96.     seed = xorshift(seed);
  97.     return seed;
  98. }
  99.  
  100. float nextFloat(inout int seed)
  101. {
  102.     seed = xorshift(seed);
  103.     // FIXME: This should have been a seed mapped from MIN..MAX to 0..1 instead
  104.     return abs(fract(float(seed) / 3141.592653));
  105. }
  106.  
  107. float nextFloat(inout int seed, in float max)
  108. {
  109.     return nextFloat(seed) * max;
  110. }
  111.  
  112. float nextFloat(inout int seed, in float min, in float max)
  113. {
  114.     return min + (max - min) * nextFloat(seed);
  115. }
  116.  
  117. // ----
  118.  
  119. vec3 GetGradientColorAtRay(Ray ray)
  120. {
  121.     vec3 v = lerp(vec3(255.0f / 255.0f, 255.0f / 255.0f, 255.0f / 255.0f),
  122.             vec3(128.0f / 255.0f, 178.0f / 255.0f, 255.0f / 255.0f), ray.Direction.y * 1.25f);
  123.     return v;
  124. }
  125.  
  126. RayHitRecord RaySphereIntersectionTest(const Sphere sphere, Ray ray, float tmin, float tmax)
  127. {
  128.     RayHitRecord hit_record;
  129.  
  130.     vec3 oc = ray.Origin - sphere.Center;
  131.     float A = dot(ray.Direction, ray.Direction);
  132.     float B = 2.0 * dot(oc, ray.Direction);
  133.     float C = dot(oc, oc) - sphere.Radius * sphere.Radius;
  134.     float Discriminant = B * B - 4 * A * C;
  135.  
  136.     if (Discriminant < 0)
  137.     {
  138.         hit_record.Hit = false;
  139.         return hit_record;
  140.     }
  141.  
  142.     else
  143.     {
  144.         float root = (-B - sqrt(Discriminant)) / (2.0f * A); // T
  145.  
  146.         if (root < tmin || root > tmax)
  147.         {
  148.             root = (-B + sqrt(Discriminant)) / (2.0f * A);
  149.  
  150.             if (root < tmin || root > tmax)
  151.             {
  152.                 hit_record.Hit = false;
  153.                 return hit_record;
  154.             }
  155.         }
  156.  
  157.         hit_record.Hit = true;
  158.  
  159.         // The root was found successfully
  160.         hit_record.T = root;
  161.         hit_record.Point = Ray_GetAt(ray, root);
  162.  
  163.         hit_record.Normal = (hit_record.Point - sphere.Center) / sphere.Radius;
  164.  
  165.         if (dot(ray.Direction, hit_record.Normal) > 0.0f)
  166.         {
  167.             hit_record.Normal = -hit_record.Normal;
  168.             hit_record.Inside = true;
  169.         }
  170.  
  171.         return hit_record;
  172.     }
  173. }
  174.  
  175. RayHitRecord IntersectSceneSpheres(Ray ray, float tmin, float tmax)
  176. {
  177.     RayHitRecord TempRecord;
  178.     RayHitRecord ClosestRecord;
  179.     bool HitAnything = false;
  180.     float ClosestDistance = tmax;
  181.  
  182.     for (int i = 0 ; i < u_SceneSphereCount ; i++)
  183.     {
  184.         TempRecord = RaySphereIntersectionTest(u_SceneSpheres[i], ray, tmin, ClosestDistance);
  185.  
  186.         if (TempRecord.Hit)
  187.         {
  188.             HitAnything = true;
  189.             ClosestDistance = TempRecord.T;
  190.             ClosestRecord = TempRecord;
  191.             ClosestRecord.sphere = u_SceneSpheres[i];
  192.         }
  193.     }
  194.  
  195.     return ClosestRecord;
  196. }
  197.  
  198. float ConvertValueRange(float v, vec2 r1, vec2 r2)
  199. {
  200.     float ret = (((v - r1.x) * (r2.y - r2.x)) / (r1.y - r1.x)) + r2.x;
  201.     return ret;
  202. }
  203.  
  204. Ray GetRay(vec2 uv)
  205. {
  206.     Ray ray;
  207.     ray.Origin = u_CameraOrigin;
  208.     ray.Direction = u_CameraBottomLeft + (u_CameraHorizontal * uv.x) + (u_CameraVertical * uv.y) - u_CameraOrigin;
  209.    
  210.     return ray;
  211. }
  212.  
  213. vec3 GetRayColor(Ray ray)
  214. {
  215.     Ray new_ray = ray;
  216.     vec3 FinalColor = vec3(1.0f);
  217.  
  218.     bool IntersectionFound = false;
  219.     int hit_times = 0;
  220.  
  221.     for (int i = 0; i < RAY_BOUNCE_LIMIT; i++)
  222.     {
  223.         RayHitRecord ClosestSphere = IntersectSceneSpheres(new_ray, 0.001f, MAX_RAY_HIT_DISTANCE);
  224.  
  225.         if (ClosestSphere.Hit == true)
  226.         {
  227.             // Get the final ray direction
  228.  
  229.             vec3 R;
  230.             R.x = nextFloat(RNG_SEED, -1.0f, 1.0f);
  231.             R.y = nextFloat(RNG_SEED, -1.0f, 1.0f);
  232.             R.z = nextFloat(RNG_SEED, -1.0f, 1.0f);
  233.  
  234.             vec3 S = ClosestSphere.Normal + R;
  235.            
  236.             new_ray.Origin = ClosestSphere.Point;
  237.             new_ray.Direction = S;
  238.  
  239.             IntersectionFound = true;
  240.             hit_times += 1;
  241.         }
  242.  
  243.         else
  244.         {
  245.             break;
  246.         }
  247.     }
  248.  
  249.     FinalColor = vec3(0.0f, 0.0f, 1.0f);
  250.  
  251.     if (IntersectionFound)
  252.     {
  253.         //FinalColor /= 2.0f; // Lambertian diffuse only absorbs half the light
  254.         //FinalColor = FinalColor / hit_times;
  255.         //
  256.         //return FinalColor;
  257.  
  258.         float v = hit_times / float(RAY_BOUNCE_LIMIT);
  259.         return vec3(v);
  260.     }
  261.  
  262.     return GetGradientColorAtRay(ray);
  263. }
  264.  
  265. void main()
  266. {
  267.     const int SPP = 20;
  268.     RNG_SEED = int(gl_FragCoord.x) + int(gl_FragCoord.y) * int(u_ViewportDimensions.x);
  269.  
  270.     vec3 FinalColor = vec3(0.0f);
  271.     vec2 Pixel;
  272.  
  273.     Pixel.x = v_TexCoords.x * u_ViewportDimensions.x;
  274.     Pixel.y = v_TexCoords.y * u_ViewportDimensions.y;
  275.  
  276.     for (int s = 0 ; s < SPP ; s++)
  277.     {
  278.         float u = (Pixel.x + nextFloat(RNG_SEED)) / u_ViewportDimensions.x;
  279.         float v = (Pixel.y + nextFloat(RNG_SEED)) / u_ViewportDimensions.y;
  280.  
  281.         FinalColor += GetRayColor(GetRay(vec2(u, v)));
  282.     }
  283.  
  284.     FinalColor = FinalColor / float(SPP);
  285.  
  286.     o_Color = FinalColor;
  287. }
Advertisement
Add Comment
Please, Sign In to add comment