Ingen beskrivning

raytracing.comp 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. // Shader is looseley based on the ray tracing coding session by Inigo Quilez (www.iquilezles.org)
  2. #version 450
  3. #extension GL_ARB_separate_shader_objects : enable
  4. #extension GL_ARB_shading_language_420pack : enable
  5. layout (local_size_x = 16, local_size_y = 16) in;
  6. layout (binding = 0, rgba8) uniform writeonly image2D resultImage;
  7. #define EPSILON 0.0001
  8. #define MAXLEN 1000.0
  9. #define SHADOW 0.5
  10. #define RAYBOUNCES 2
  11. #define REFLECTIONS true
  12. #define REFLECTIONSTRENGTH 0.4
  13. #define REFLECTIONFALLOFF 0.5
  14. struct Camera
  15. {
  16. vec3 pos;
  17. vec3 lookat;
  18. float fov;
  19. };
  20. layout (binding = 1) uniform UBO
  21. {
  22. vec3 lightPos;
  23. float aspectRatio;
  24. vec4 fogColor;
  25. Camera camera;
  26. mat4 rotMat;
  27. } ubo;
  28. struct Sphere
  29. {
  30. vec3 pos;
  31. float radius;
  32. vec3 diffuse;
  33. float specular;
  34. int id;
  35. };
  36. struct Plane
  37. {
  38. vec3 normal;
  39. float distance;
  40. vec3 diffuse;
  41. float specular;
  42. int id;
  43. };
  44. layout (std140, binding = 2) buffer Spheres
  45. {
  46. Sphere spheres[ ];
  47. };
  48. layout (std140, binding = 3) buffer Planes
  49. {
  50. Plane planes[ ];
  51. };
  52. void reflectRay(inout vec3 rayD, in vec3 mormal)
  53. {
  54. rayD = rayD + 2.0 * -dot(mormal, rayD) * mormal;
  55. }
  56. // Lighting =========================================================
  57. float lightDiffuse(vec3 normal, vec3 lightDir)
  58. {
  59. return clamp(dot(normal, lightDir), 0.1, 1.0);
  60. }
  61. float lightSpecular(vec3 normal, vec3 lightDir, float specularFactor)
  62. {
  63. vec3 viewVec = normalize(ubo.camera.pos);
  64. vec3 halfVec = normalize(lightDir + viewVec);
  65. return pow(clamp(dot(normal, halfVec), 0.0, 1.0), specularFactor);
  66. }
  67. // Sphere ===========================================================
  68. float sphereIntersect(in vec3 rayO, in vec3 rayD, in Sphere sphere)
  69. {
  70. vec3 oc = rayO - sphere.pos;
  71. float b = 2.0 * dot(oc, rayD);
  72. float c = dot(oc, oc) - sphere.radius*sphere.radius;
  73. float h = b*b - 4.0*c;
  74. if (h < 0.0)
  75. {
  76. return -1.0;
  77. }
  78. float t = (-b - sqrt(h)) / 2.0;
  79. return t;
  80. }
  81. vec3 sphereNormal(in vec3 pos, in Sphere sphere)
  82. {
  83. return (pos - sphere.pos) / sphere.radius;
  84. }
  85. // Plane ===========================================================
  86. float planeIntersect(vec3 rayO, vec3 rayD, Plane plane)
  87. {
  88. float d = dot(rayD, plane.normal);
  89. if (d == 0.0)
  90. return 0.0;
  91. float t = -(plane.distance + dot(rayO, plane.normal)) / d;
  92. if (t < 0.0)
  93. return 0.0;
  94. return t;
  95. }
  96. int intersect(in vec3 rayO, in vec3 rayD, inout float resT)
  97. {
  98. int id = -1;
  99. for (int i = 0; i < spheres.length(); i++)
  100. {
  101. float tSphere = sphereIntersect(rayO, rayD, spheres[i]);
  102. if ((tSphere > EPSILON) && (tSphere < resT))
  103. {
  104. id = spheres[i].id;
  105. resT = tSphere;
  106. }
  107. }
  108. for (int i = 0; i < planes.length(); i++)
  109. {
  110. float tplane = planeIntersect(rayO, rayD, planes[i]);
  111. if ((tplane > EPSILON) && (tplane < resT))
  112. {
  113. id = planes[i].id;
  114. resT = tplane;
  115. }
  116. }
  117. return id;
  118. }
  119. float calcShadow(in vec3 rayO, in vec3 rayD, in int objectId, inout float t)
  120. {
  121. for (int i = 0; i < spheres.length(); i++)
  122. {
  123. if (spheres[i].id == objectId)
  124. continue;
  125. float tSphere = sphereIntersect(rayO, rayD, spheres[i]);
  126. if ((tSphere > EPSILON) && (tSphere < t))
  127. {
  128. t = tSphere;
  129. return SHADOW;
  130. }
  131. }
  132. return 1.0;
  133. }
  134. vec3 fog(in float t, in vec3 color)
  135. {
  136. return mix(color, ubo.fogColor.rgb, clamp(sqrt(t*t)/20.0, 0.0, 1.0));
  137. }
  138. vec3 renderScene(inout vec3 rayO, inout vec3 rayD, inout int id)
  139. {
  140. vec3 color = vec3(0.0);
  141. float t = MAXLEN;
  142. // Get intersected object ID
  143. int objectID = intersect(rayO, rayD, t);
  144. if (objectID == -1)
  145. {
  146. return color;
  147. }
  148. vec3 pos = rayO + t * rayD;
  149. vec3 lightVec = normalize(ubo.lightPos - pos);
  150. vec3 normal;
  151. // Planes
  152. // Spheres
  153. for (int i = 0; i < planes.length(); i++)
  154. {
  155. if (objectID == planes[i].id)
  156. {
  157. normal = planes[i].normal;
  158. float diffuse = lightDiffuse(normal, lightVec);
  159. float specular = lightSpecular(normal, lightVec, planes[i].specular);
  160. color = diffuse * planes[i].diffuse + specular;
  161. }
  162. }
  163. for (int i = 0; i < spheres.length(); i++)
  164. {
  165. if (objectID == spheres[i].id)
  166. {
  167. normal = sphereNormal(pos, spheres[i]);
  168. float diffuse = lightDiffuse(normal, lightVec);
  169. float specular = lightSpecular(normal, lightVec, spheres[i].specular);
  170. color = diffuse * spheres[i].diffuse + specular;
  171. }
  172. }
  173. if (id == -1)
  174. return color;
  175. id = objectID;
  176. // Shadows
  177. t = length(ubo.lightPos - pos);
  178. color *= calcShadow(pos, lightVec, id, t);
  179. // Fog
  180. color = fog(t, color);
  181. // Reflect ray for next render pass
  182. reflectRay(rayD, normal);
  183. rayO = pos;
  184. return color;
  185. }
  186. void main()
  187. {
  188. ivec2 dim = imageSize(resultImage);
  189. vec2 uv = vec2(gl_GlobalInvocationID.xy) / dim;
  190. vec3 rayO = ubo.camera.pos;
  191. vec3 rayD = normalize(vec3((-1.0 + 2.0 * uv) * vec2(ubo.aspectRatio, 1.0), -1.0));
  192. // Basic color path
  193. int id = 0;
  194. vec3 finalColor = renderScene(rayO, rayD, id);
  195. // Reflection
  196. if (REFLECTIONS)
  197. {
  198. float reflectionStrength = REFLECTIONSTRENGTH;
  199. for (int i = 0; i < RAYBOUNCES; i++)
  200. {
  201. vec3 reflectionColor = renderScene(rayO, rayD, id);
  202. finalColor = (1.0 - reflectionStrength) * finalColor + reflectionStrength * mix(reflectionColor, finalColor, 1.0 - reflectionStrength);
  203. reflectionStrength *= REFLECTIONFALLOFF;
  204. }
  205. }
  206. imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), vec4(finalColor, 0.0));
  207. }