SSAO.glsl.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. See https://js.arcgis.com/4.24/esri/copyright.txt for details.
  4. */
  5. import{ScreenSpacePass as e}from"../views/3d/webgl-engine/core/shaderLibrary/ScreenSpacePass.js";import{ReadLinearDepth as r}from"../views/3d/webgl-engine/core/shaderLibrary/output/ReadLinearDepth.glsl.js";import{CameraSpace as o,getZScale as t}from"../views/3d/webgl-engine/core/shaderLibrary/util/CameraSpace.glsl.js";import{Float2PassUniform as a}from"../views/3d/webgl-engine/core/shaderModules/Float2PassUniform.js";import{Float2Uniform as n}from"../views/3d/webgl-engine/core/shaderModules/Float2Uniform.js";import{FloatUniform as i}from"../views/3d/webgl-engine/core/shaderModules/FloatUniform.js";import{glsl as s}from"../views/3d/webgl-engine/core/shaderModules/interfaces.js";import{ShaderBuilder as l}from"../views/3d/webgl-engine/core/shaderModules/ShaderBuilder.js";import{Texture2DUniform as c}from"../views/3d/webgl-engine/core/shaderModules/Texture2DUniform.js";import{SSAOOutput as d}from"../views/3d/webgl-engine/lib/SSAOTechniqueConfiguration.js";const f={samples:16,filterRadius:4};function u(u){const p=new l,m=p.fragment;if(p.include(e),u.output===d.Blur){const e=(f.filterRadius+1)/2,o=1/(2*e*e);m.include(r),m.uniforms.add([new c("normalMap"),new c("depthMap"),new c("tex"),new n("blurSize"),new i("projScale"),new a("nearFar",((e,r)=>r.camera.nearFar))]),m.code.add(s`
  6. void blurFunction(vec2 uv, float r, float center_d, float sharpness, inout float wTotal, inout float bTotal) {
  7. float c = texture2D(tex, uv).r;
  8. float d = linearDepthFromTexture(depthMap, uv, nearFar);
  9. float ddiff = d - center_d;
  10. float w = exp(-r * r * ${s.float(o)} - ddiff * ddiff * sharpness);
  11. wTotal += w;
  12. bTotal += w * c;
  13. }
  14. `),m.code.add(s`
  15. void main(void) {
  16. float b = 0.0;
  17. float w_total = 0.0;
  18. float center_d = linearDepthFromTexture(depthMap, uv, nearFar);
  19. float sharpness = -0.05 * projScale/center_d;
  20. for (int r = -${s.int(f.filterRadius)}; r <= ${s.int(f.filterRadius)}; ++r) {
  21. float rf = float(r);
  22. vec2 uvOffset = uv + rf * blurSize;
  23. blurFunction(uvOffset, rf, center_d, sharpness, w_total, b);
  24. }
  25. gl_FragColor = vec4(b / w_total);
  26. }
  27. `)}return u.output===d.SSAO&&(m.include(r),p.include(o),m.uniforms.add(new c("normalMap")),m.uniforms.add(new c("depthMap")),m.uniforms.add(new c("rnm")),m.uniforms.add(new i("intensity")),m.uniforms.add(new i("projScale")),m.uniforms.add(new i("radius")),m.uniforms.add(new a("nearFar",((e,r)=>r.camera.nearFar))),m.uniforms.add(new n("screenSize")),m.uniforms.add(new n("rnmScale")),m.code.add(s`vec3 sphere[16];
  28. void fillSphere() {
  29. sphere[0] = vec3(0.186937, 0.0, 0.0);
  30. sphere[1] = vec3(0.700542, 0.0, 0.0);
  31. sphere[2] = vec3(-0.864858, -0.481795, -0.111713);
  32. sphere[3] = vec3(-0.624773, 0.102853, -0.730153);
  33. sphere[4] = vec3(-0.387172, 0.260319, 0.007229);
  34. sphere[5] = vec3(-0.222367, -0.642631, -0.707697);
  35. sphere[6] = vec3(-0.01336, -0.014956, 0.169662);
  36. sphere[7] = vec3(0.122575, 0.1544, -0.456944);
  37. sphere[8] = vec3(-0.177141, 0.85997, -0.42346);
  38. sphere[9] = vec3(-0.131631, 0.814545, 0.524355);
  39. sphere[10] = vec3(-0.779469, 0.007991, 0.624833);
  40. sphere[11] = vec3(0.308092, 0.209288,0.35969);
  41. sphere[12] = vec3(0.359331, -0.184533, -0.377458);
  42. sphere[13] = vec3(0.192633, -0.482999, -0.065284);
  43. sphere[14] = vec3(0.233538, 0.293706, -0.055139);
  44. sphere[15] = vec3(0.417709, -0.386701, 0.442449);
  45. }
  46. float fallOffFunction(float vv, float vn, float bias) {
  47. float f = max(radius * radius - vv, 0.0);
  48. return f * f * f * max(vn-bias, 0.0);
  49. }`),m.code.add(s`float aoValueFromPositionsAndNormal(vec3 C, vec3 n_C, vec3 Q) {
  50. vec3 v = Q - C;
  51. float vv = dot(v, v);
  52. float vn = dot(normalize(v), n_C);
  53. return fallOffFunction(vv, vn, 0.1);
  54. }`),p.fragment.uniforms.add(new a("zScale",((e,r)=>t(r)))),m.code.add(s`
  55. void main(void) {
  56. fillSphere();
  57. vec3 fres = normalize((texture2D(rnm, uv * rnmScale).xyz * 2.0) - vec3(1.0));
  58. float currentPixelDepth = linearDepthFromTexture(depthMap, uv, nearFar);
  59. if (-currentPixelDepth>nearFar.y || -currentPixelDepth<nearFar.x) {
  60. gl_FragColor = vec4(0.0);
  61. return;
  62. }
  63. vec3 currentPixelPos = reconstructPosition(gl_FragCoord.xy,currentPixelDepth);
  64. // get the normal of current fragment
  65. vec4 norm4 = texture2D(normalMap, uv);
  66. vec3 norm = vec3(-1.0) + 2.0 * norm4.xyz;
  67. bool isTerrain = norm4.w<0.5;
  68. float sum = .0;
  69. vec3 tapPixelPos;
  70. // note: the factor 2.0 should not be necessary, but makes ssao much nicer.
  71. // bug or deviation from CE somewhere else?
  72. float ps = projScale/(2.0 * currentPixelPos.z * zScale.x + zScale.y);
  73. for(int i = 0; i < ${s.int(f.samples)}; ++i) {
  74. vec2 unitOffset = reflect(sphere[i], fres).xy;
  75. vec2 offset = vec2(-unitOffset * radius * ps);
  76. //don't use current or very nearby samples
  77. if ( abs(offset.x)<2.0 || abs(offset.y)<2.0) continue;
  78. vec2 tc = vec2(gl_FragCoord.xy + offset);
  79. if (tc.x < 0.0 || tc.y < 0.0 || tc.x > screenSize.x || tc.y > screenSize.y) continue;
  80. vec2 tcTap = tc / screenSize;
  81. float occluderFragmentDepth = linearDepthFromTexture(depthMap, tcTap, nearFar);
  82. if (isTerrain) {
  83. bool isTerrainTap = texture2D(normalMap, tcTap).w<0.5;
  84. if (isTerrainTap) {
  85. continue;
  86. }
  87. }
  88. tapPixelPos = reconstructPosition(tc, occluderFragmentDepth);
  89. sum+= aoValueFromPositionsAndNormal(currentPixelPos, norm, tapPixelPos);
  90. }
  91. // output the result
  92. float A = max(1.0-sum*intensity/float(${s.int(f.samples)}),0.0);
  93. // Anti-tone map to reduce contrast and drag dark region farther: (x^0.2 + 1.2 * x^4)/2.2
  94. A = (pow(A, 0.2) + 1.2 * A*A*A*A) / 2.2;
  95. gl_FragColor = vec4(A);
  96. }
  97. `)),p}const p=Object.freeze(Object.defineProperty({__proto__:null,build:u},Symbol.toStringTag,{value:"Module"}));export{p as S,u as b};