Irradiance.ankiprog 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. <!--
  2. Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
  3. All rights reserved.
  4. Code licensed under the BSD License.
  5. http://www.anki3d.org/LICENSE
  6. -->
  7. <shaderProgram>
  8. <shaders>
  9. <shader type="vert">
  10. <source><![CDATA[
  11. #include "shaders/QuadVert.glsl"
  12. ]]></source>
  13. </shader>
  14. <shader type="frag">
  15. <inputs>
  16. <input name="ENV_TEX_TILE_SIZE" type="uint" const="1"/>
  17. <input name="ENV_TEX_MIP" type="float" const="1"/>
  18. </inputs>
  19. <source><![CDATA[
  20. // Compute the irradiance given an environment map
  21. // It's almost the same as http://www.codinglabs.net/article_physically_based_rendering.aspx
  22. // It's more bright though
  23. #include "shaders/Functions.glsl"
  24. layout(location = 0) in vec2 in_uv;
  25. layout(location = 0) out vec3 out_color;
  26. layout(ANKI_TEX_BINDING(0, 0)) uniform samplerCubeArray u_envTex;
  27. layout(ANKI_UBO_BINDING(0, 0)) uniform u0_
  28. {
  29. // x: The face index to render to
  30. // y: The array index to read from the u_envTex
  31. uvec4 u_faceIdxArrayIdxPad2;
  32. };
  33. float areaElement(float x, float y)
  34. {
  35. return atan(x * y, sqrt(x * x + y * y + 1.0));
  36. }
  37. float cubeCoordSolidAngle(vec2 norm)
  38. {
  39. float invSize = 1.0 / float(ENV_TEX_TILE_SIZE);
  40. vec2 v0 = norm - vec2(invSize);
  41. vec2 v1 = norm + vec2(invSize);
  42. return areaElement(v0.x, v0.y) - areaElement(v0.x, v1.y) - areaElement(v1.x, v0.y) + areaElement(v1.x, v1.y);
  43. }
  44. // Integrate the environment map to compute the irradiance for a single fragment
  45. void main()
  46. {
  47. uint face = u_faceIdxArrayIdxPad2.x;
  48. float texArrIdx = float(u_faceIdxArrayIdxPad2.y);
  49. // Get the r coordinate of the current face and fragment
  50. vec3 ri = getCubemapDirection(UV_TO_NDC(in_uv), face);
  51. vec3 outCol = vec3(0.0);
  52. float weight = EPSILON;
  53. // For all the faces and texels of the environment map calculate a color sum
  54. for(uint f = 0u; f < 6u; ++f)
  55. {
  56. for(uint i = 0u; i < ENV_TEX_TILE_SIZE; ++i)
  57. {
  58. for(uint j = 0u; j < ENV_TEX_TILE_SIZE; ++j)
  59. {
  60. vec2 uv = vec2(j, i) / float(ENV_TEX_TILE_SIZE);
  61. vec3 r = getCubemapDirection(UV_TO_NDC(uv), f);
  62. float lambert = dot(r, ri);
  63. if(lambert > 0.0)
  64. {
  65. vec3 col = textureLod(u_envTex, vec4(r, texArrIdx), ENV_TEX_MIP).rgb;
  66. outCol += col * lambert * cubeCoordSolidAngle(UV_TO_NDC(uv));
  67. weight += lambert;
  68. }
  69. }
  70. }
  71. }
  72. //out_color = outCol / weight * PI;
  73. out_color = outCol / PI;
  74. }
  75. ]]></source>
  76. </shader>
  77. </shaders>
  78. </shaderProgram>