postprocessing.frag.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /**
  2. * Copyright (c) 2019-2022 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 postprocessing_frag = `
  8. precision highp float;
  9. precision highp int;
  10. precision highp sampler2D;
  11. uniform sampler2D tSsaoDepth;
  12. uniform sampler2D tColor;
  13. uniform sampler2D tDepthOpaque;
  14. uniform sampler2D tDepthTransparent;
  15. uniform sampler2D tShadows;
  16. uniform sampler2D tOutlines;
  17. uniform vec2 uTexSize;
  18. uniform float uNear;
  19. uniform float uFar;
  20. uniform float uFogNear;
  21. uniform float uFogFar;
  22. uniform vec3 uFogColor;
  23. uniform vec3 uOutlineColor;
  24. uniform bool uTransparentBackground;
  25. uniform vec2 uOcclusionOffset;
  26. uniform float uMaxPossibleViewZDiff;
  27. const vec3 occlusionColor = vec3(0.0);
  28. #include common
  29. float getViewZ(const in float depth) {
  30. #if dOrthographic == 1
  31. return orthographicDepthToViewZ(depth, uNear, uFar);
  32. #else
  33. return perspectiveDepthToViewZ(depth, uNear, uFar);
  34. #endif
  35. }
  36. float getDepthOpaque(const in vec2 coords) {
  37. #ifdef depthTextureSupport
  38. return texture2D(tDepthOpaque, coords).r;
  39. #else
  40. return unpackRGBAToDepth(texture2D(tDepthOpaque, coords));
  41. #endif
  42. }
  43. float getDepthTransparent(const in vec2 coords) {
  44. return unpackRGBAToDepth(texture2D(tDepthTransparent, coords));
  45. }
  46. bool isBackground(const in float depth) {
  47. return depth == 1.0;
  48. }
  49. float getOutline(const in vec2 coords, const in float opaqueDepth, out float closestTexel) {
  50. float backgroundViewZ = uFar + 3.0 * uMaxPossibleViewZDiff;
  51. vec2 invTexSize = 1.0 / uTexSize;
  52. float selfDepth = min(opaqueDepth, getDepthTransparent(coords));
  53. float selfViewZ = isBackground(selfDepth) ? backgroundViewZ : getViewZ(selfDepth);
  54. float outline = 1.0;
  55. closestTexel = 1.0;
  56. for (int y = -dOutlineScale; y <= dOutlineScale; y++) {
  57. for (int x = -dOutlineScale; x <= dOutlineScale; x++) {
  58. if (x * x + y * y > dOutlineScale * dOutlineScale) {
  59. continue;
  60. }
  61. vec2 sampleCoords = coords + vec2(float(x), float(y)) * invTexSize;
  62. vec4 sampleOutlineCombined = texture2D(tOutlines, sampleCoords);
  63. float sampleOutline = sampleOutlineCombined.r;
  64. float sampleOutlineDepth = unpackRGToUnitInterval(sampleOutlineCombined.gb);
  65. float sampleOutlineViewZ = isBackground(sampleOutlineDepth) ? backgroundViewZ : getViewZ(sampleOutlineDepth);
  66. if (sampleOutline == 0.0 && sampleOutlineDepth < closestTexel && abs(selfViewZ - sampleOutlineViewZ) > uMaxPossibleViewZDiff) {
  67. outline = 0.0;
  68. closestTexel = sampleOutlineDepth;
  69. }
  70. }
  71. }
  72. return closestTexel < opaqueDepth ? outline : 1.0;
  73. }
  74. float getSsao(vec2 coords) {
  75. float rawSsao = unpackRGToUnitInterval(texture2D(tSsaoDepth, coords).xy);
  76. if (rawSsao > 0.999) {
  77. return 1.0;
  78. } else if (rawSsao > 0.001) {
  79. return rawSsao;
  80. }
  81. // treat values close to 0.0 as errors and return no occlusion
  82. return 1.0;
  83. }
  84. void main(void) {
  85. vec2 coords = gl_FragCoord.xy / uTexSize;
  86. vec4 color = texture2D(tColor, coords);
  87. float viewDist;
  88. float fogFactor;
  89. float opaqueDepth = getDepthOpaque(coords);
  90. #ifdef dOcclusionEnable
  91. if (!isBackground(opaqueDepth)) {
  92. viewDist = abs(getViewZ(opaqueDepth));
  93. fogFactor = smoothstep(uFogNear, uFogFar, viewDist);
  94. float occlusionFactor = getSsao(coords + uOcclusionOffset);
  95. if (!uTransparentBackground) {
  96. color.rgb = mix(mix(occlusionColor, uFogColor, fogFactor), color.rgb, occlusionFactor);
  97. } else {
  98. color.rgb = mix(occlusionColor * (1.0 - fogFactor), color.rgb, occlusionFactor);
  99. }
  100. }
  101. #endif
  102. #ifdef dShadowEnable
  103. if (!isBackground(opaqueDepth)) {
  104. viewDist = abs(getViewZ(opaqueDepth));
  105. fogFactor = smoothstep(uFogNear, uFogFar, viewDist);
  106. vec4 shadow = texture2D(tShadows, coords);
  107. if (!uTransparentBackground) {
  108. color.rgb = mix(mix(vec3(0), uFogColor, fogFactor), color.rgb, shadow.a);
  109. } else {
  110. color.rgb = mix(vec3(0) * (1.0 - fogFactor), color.rgb, shadow.a);
  111. }
  112. }
  113. #endif
  114. // outline needs to be handled after occlusion and shadow to keep them clean
  115. #ifdef dOutlineEnable
  116. float closestTexel;
  117. float outline = getOutline(coords, opaqueDepth, closestTexel);
  118. if (outline == 0.0) {
  119. viewDist = abs(getViewZ(closestTexel));
  120. fogFactor = smoothstep(uFogNear, uFogFar, viewDist);
  121. if (!uTransparentBackground) {
  122. color.rgb = mix(uOutlineColor, uFogColor, fogFactor);
  123. } else {
  124. color.a = 1.0 - fogFactor;
  125. color.rgb = mix(uOutlineColor, color.rgb, fogFactor);
  126. }
  127. }
  128. #endif
  129. gl_FragColor = color;
  130. }
  131. `;