pointlight.vert 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. in vec3 Position;
  2. in float Energy;
  3. in vec3 Color;
  4. in float Radius;
  5. flat out vec3 center;
  6. flat out float energy;
  7. flat out vec3 col;
  8. flat out float radius;
  9. const float zNear = 1.;
  10. // Code borrowed from https://software.intel.com/en-us/articles/deferred-rendering-for-current-and-future-rendering-pipelines
  11. // Maths explanations are found here http://www.gamasutra.com/view/feature/131351/the_mechanics_of_robust_stencil_.php?page=6
  12. vec2 UpdateClipRegionRoot(float nc, /* Tangent plane x/y normal coordinate (view space) */
  13. float lc, /* Light x/y coordinate (view space) */
  14. float lz, /* Light z coordinate (view space) */
  15. float lightRadius,
  16. float cameraScale /* Project scale for coordinate (_11 or _22 for x/y respectively) */)
  17. {
  18. float nz = (lightRadius - nc * lc) / lz;
  19. float pz = (lc * lc + lz * lz - lightRadius * lightRadius) /
  20. (lz - (nz / nc) * lc);
  21. if (pz > 0.) {
  22. float c = -nz * cameraScale / nc;
  23. if (nc > 0.) // Left side boundary
  24. return vec2(c, 1.);
  25. else // Right side boundary
  26. return vec2(-1., c);
  27. }
  28. return vec2(-1., 1.);
  29. }
  30. vec2 UpdateClipRegion(float lc, /* Light x/y coordinate (view space) */
  31. float lz, /* Light z coordinate (view space) */
  32. float lightRadius,
  33. float cameraScale /* Project scale for coordinate (_11 or _22 for x/y respectively) */)
  34. {
  35. float rSq = lightRadius * lightRadius;
  36. float lcSqPluslzSq = lc * lc + lz * lz;
  37. float d = rSq * lc * lc - lcSqPluslzSq * (rSq - lz * lz);
  38. // The camera is inside lignt bounding sphere, quad fits whole screen
  39. if (d <= 0.)
  40. return vec2(-1., 1.);
  41. float a = lightRadius * lc;
  42. float b = sqrt(d);
  43. float nx0 = (a + b) / lcSqPluslzSq;
  44. float nx1 = (a - b) / lcSqPluslzSq;
  45. vec2 clip0 = UpdateClipRegionRoot(nx0, lc, lz, lightRadius, cameraScale);
  46. vec2 clip1 = UpdateClipRegionRoot(nx1, lc, lz, lightRadius, cameraScale);
  47. return vec2(max(clip0.x, clip1.x), min(clip0.y, clip1.y));
  48. }
  49. // Returns bounding box [min.x, max.x, min.y, max.y] in clip [-1, 1] space.
  50. vec4 ComputeClipRegion(vec3 lightPosView, float lightRadius)
  51. {
  52. if (lightPosView.z + lightRadius >= zNear) {
  53. vec2 clipX = UpdateClipRegion(lightPosView.x, lightPosView.z, lightRadius, ProjectionMatrix[0][0]);
  54. vec2 clipY = UpdateClipRegion(lightPosView.y, lightPosView.z, lightRadius, ProjectionMatrix[1][1]);
  55. return vec4(clipX, clipY);
  56. }
  57. return vec4(0.);
  58. }
  59. void main(void)
  60. {
  61. vec4 Center = ViewMatrix * vec4(Position, 1.);
  62. Center /= Center.w;
  63. vec2 ProjectedCornerPosition;
  64. vec4 clip = ComputeClipRegion(Center.xyz, Radius);
  65. switch (gl_VertexID)
  66. {
  67. case 0:
  68. ProjectedCornerPosition = clip.xz;
  69. break;
  70. case 1:
  71. ProjectedCornerPosition = clip.xw;
  72. break;
  73. case 2:
  74. ProjectedCornerPosition = clip.yz;
  75. break;
  76. case 3:
  77. ProjectedCornerPosition = clip.yw;
  78. break;
  79. }
  80. // Work out nearest depth for quad Z
  81. // Clamp to near plane in case this light intersects the near plane... don't want our quad to be clipped
  82. float quadDepth = max(zNear, Center.z - Radius);
  83. // Project quad depth into clip space
  84. vec4 quadClip = ProjectionMatrix * vec4(0., 0., quadDepth, 1.0f);
  85. gl_Position = vec4(ProjectedCornerPosition, quadClip.z / quadClip.w, 1.);
  86. col = Color;
  87. center = Position;
  88. energy = Energy;
  89. radius = Radius;
  90. }