ssao.frag.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /**
  2. * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. * @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz>
  6. */
  7. export const ssao_frag = `
  8. precision highp float;
  9. precision highp int;
  10. precision highp sampler2D;
  11. #include common
  12. uniform sampler2D tDepth;
  13. uniform vec3 uSamples[dNSamples];
  14. uniform mat4 uProjection;
  15. uniform mat4 uInvProjection;
  16. uniform vec2 uTexSize;
  17. uniform float uRadius;
  18. uniform float uBias;
  19. float smootherstep(float edge0, float edge1, float x) {
  20. x = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
  21. return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
  22. }
  23. float noise(const in vec2 coords) {
  24. float a = 12.9898;
  25. float b = 78.233;
  26. float c = 43758.5453;
  27. float dt = dot(coords, vec2(a,b));
  28. float sn = mod(dt, PI);
  29. return abs(fract(sin(sn) * c)); // is abs necessary?
  30. }
  31. vec2 getNoiseVec2(const in vec2 coords) {
  32. return vec2(noise(coords), noise(coords + vec2(PI, 2.71828)));
  33. }
  34. bool isBackground(const in float depth) {
  35. return depth == 1.0;
  36. }
  37. float getDepth(const in vec2 coords) {
  38. return unpackRGBAToDepth(texture2D(tDepth, coords));
  39. }
  40. vec3 normalFromDepth(const in float depth, const in float depth1, const in float depth2, vec2 offset1, vec2 offset2) {
  41. vec3 p1 = vec3(offset1, depth1 - depth);
  42. vec3 p2 = vec3(offset2, depth2 - depth);
  43. vec3 normal = cross(p1, p2);
  44. normal.z = -normal.z;
  45. return normalize(normal);
  46. }
  47. // StarCraft II Ambient Occlusion by [Filion and McNaughton 2008]
  48. void main(void) {
  49. vec2 invTexSize = 1.0 / uTexSize;
  50. vec2 selfCoords = gl_FragCoord.xy * invTexSize;
  51. float selfDepth = getDepth(selfCoords);
  52. vec2 selfPackedDepth = packUnitIntervalToRG(selfDepth);
  53. if (isBackground(selfDepth)) {
  54. gl_FragColor = vec4(packUnitIntervalToRG(0.0), selfPackedDepth);
  55. return;
  56. }
  57. vec2 offset1 = vec2(0.0, invTexSize.y);
  58. vec2 offset2 = vec2(invTexSize.x, 0.0);
  59. float selfDepth1 = getDepth(selfCoords + offset1);
  60. float selfDepth2 = getDepth(selfCoords + offset2);
  61. vec3 selfViewNormal = normalFromDepth(selfDepth, selfDepth1, selfDepth2, offset1, offset2);
  62. vec3 selfViewPos = screenSpaceToViewSpace(vec3(selfCoords, selfDepth), uInvProjection);
  63. vec3 randomVec = normalize(vec3(getNoiseVec2(selfCoords) * 2.0 - 1.0, 0.0));
  64. vec3 tangent = normalize(randomVec - selfViewNormal * dot(randomVec, selfViewNormal));
  65. vec3 bitangent = cross(selfViewNormal, tangent);
  66. mat3 TBN = mat3(tangent, bitangent, selfViewNormal);
  67. float occlusion = 0.0;
  68. for(int i = 0; i < dNSamples; i++){
  69. vec3 sampleViewPos = TBN * uSamples[i];
  70. sampleViewPos = selfViewPos + sampleViewPos * uRadius;
  71. vec4 offset = vec4(sampleViewPos, 1.0);
  72. offset = uProjection * offset;
  73. offset.xyz = (offset.xyz / offset.w) * 0.5 + 0.5;
  74. float sampleViewZ = screenSpaceToViewSpace(vec3(offset.xy, getDepth(offset.xy)), uInvProjection).z;
  75. occlusion += step(sampleViewPos.z + 0.025, sampleViewZ) * smootherstep(0.0, 1.0, uRadius / abs(selfViewPos.z - sampleViewZ));
  76. }
  77. occlusion = 1.0 - (uBias * occlusion / float(dNSamples));
  78. vec2 packedOcclusion = packUnitIntervalToRG(occlusion);
  79. gl_FragColor = vec4(packedOcclusion, selfPackedDepth);
  80. }
  81. `;