2
0

SAOShader.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. import {
  2. Matrix4,
  3. Vector2
  4. } from '../../../build/three.module.js';
  5. /**
  6. * TODO
  7. */
  8. var SAOShader = {
  9. defines: {
  10. 'NUM_SAMPLES': 7,
  11. 'NUM_RINGS': 4,
  12. 'NORMAL_TEXTURE': 0,
  13. 'DIFFUSE_TEXTURE': 0,
  14. 'DEPTH_PACKING': 1,
  15. 'PERSPECTIVE_CAMERA': 1
  16. },
  17. uniforms: {
  18. 'tDepth': { value: null },
  19. 'tDiffuse': { value: null },
  20. 'tNormal': { value: null },
  21. 'size': { value: new Vector2( 512, 512 ) },
  22. 'cameraNear': { value: 1 },
  23. 'cameraFar': { value: 100 },
  24. 'cameraProjectionMatrix': { value: new Matrix4() },
  25. 'cameraInverseProjectionMatrix': { value: new Matrix4() },
  26. 'scale': { value: 1.0 },
  27. 'intensity': { value: 0.1 },
  28. 'bias': { value: 0.5 },
  29. 'minResolution': { value: 0.0 },
  30. 'kernelRadius': { value: 100.0 },
  31. 'randomSeed': { value: 0.0 }
  32. },
  33. vertexShader: [
  34. 'varying vec2 vUv;',
  35. 'void main() {',
  36. ' vUv = uv;',
  37. ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
  38. '}'
  39. ].join( '\n' ),
  40. fragmentShader: [
  41. '#include <common>',
  42. 'varying vec2 vUv;',
  43. '#if DIFFUSE_TEXTURE == 1',
  44. 'uniform sampler2D tDiffuse;',
  45. '#endif',
  46. 'uniform sampler2D tDepth;',
  47. '#if NORMAL_TEXTURE == 1',
  48. 'uniform sampler2D tNormal;',
  49. '#endif',
  50. 'uniform float cameraNear;',
  51. 'uniform float cameraFar;',
  52. 'uniform mat4 cameraProjectionMatrix;',
  53. 'uniform mat4 cameraInverseProjectionMatrix;',
  54. 'uniform float scale;',
  55. 'uniform float intensity;',
  56. 'uniform float bias;',
  57. 'uniform float kernelRadius;',
  58. 'uniform float minResolution;',
  59. 'uniform vec2 size;',
  60. 'uniform float randomSeed;',
  61. '// RGBA depth',
  62. '#include <packing>',
  63. 'vec4 getDefaultColor( const in vec2 screenPosition ) {',
  64. ' #if DIFFUSE_TEXTURE == 1',
  65. ' return texture2D( tDiffuse, vUv );',
  66. ' #else',
  67. ' return vec4( 1.0 );',
  68. ' #endif',
  69. '}',
  70. 'float getDepth( const in vec2 screenPosition ) {',
  71. ' #if DEPTH_PACKING == 1',
  72. ' return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) );',
  73. ' #else',
  74. ' return texture2D( tDepth, screenPosition ).x;',
  75. ' #endif',
  76. '}',
  77. 'float getViewZ( const in float depth ) {',
  78. ' #if PERSPECTIVE_CAMERA == 1',
  79. ' return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );',
  80. ' #else',
  81. ' return orthographicDepthToViewZ( depth, cameraNear, cameraFar );',
  82. ' #endif',
  83. '}',
  84. 'vec3 getViewPosition( const in vec2 screenPosition, const in float depth, const in float viewZ ) {',
  85. ' float clipW = cameraProjectionMatrix[2][3] * viewZ + cameraProjectionMatrix[3][3];',
  86. ' vec4 clipPosition = vec4( ( vec3( screenPosition, depth ) - 0.5 ) * 2.0, 1.0 );',
  87. ' clipPosition *= clipW; // unprojection.',
  88. ' return ( cameraInverseProjectionMatrix * clipPosition ).xyz;',
  89. '}',
  90. 'vec3 getViewNormal( const in vec3 viewPosition, const in vec2 screenPosition ) {',
  91. ' #if NORMAL_TEXTURE == 1',
  92. ' return unpackRGBToNormal( texture2D( tNormal, screenPosition ).xyz );',
  93. ' #else',
  94. ' return normalize( cross( dFdx( viewPosition ), dFdy( viewPosition ) ) );',
  95. ' #endif',
  96. '}',
  97. 'float scaleDividedByCameraFar;',
  98. 'float minResolutionMultipliedByCameraFar;',
  99. 'float getOcclusion( const in vec3 centerViewPosition, const in vec3 centerViewNormal, const in vec3 sampleViewPosition ) {',
  100. ' vec3 viewDelta = sampleViewPosition - centerViewPosition;',
  101. ' float viewDistance = length( viewDelta );',
  102. ' float scaledScreenDistance = scaleDividedByCameraFar * viewDistance;',
  103. ' return max(0.0, (dot(centerViewNormal, viewDelta) - minResolutionMultipliedByCameraFar) / scaledScreenDistance - bias) / (1.0 + pow2( scaledScreenDistance ) );',
  104. '}',
  105. '// moving costly divides into consts',
  106. 'const float ANGLE_STEP = PI2 * float( NUM_RINGS ) / float( NUM_SAMPLES );',
  107. 'const float INV_NUM_SAMPLES = 1.0 / float( NUM_SAMPLES );',
  108. 'float getAmbientOcclusion( const in vec3 centerViewPosition ) {',
  109. ' // precompute some variables require in getOcclusion.',
  110. ' scaleDividedByCameraFar = scale / cameraFar;',
  111. ' minResolutionMultipliedByCameraFar = minResolution * cameraFar;',
  112. ' vec3 centerViewNormal = getViewNormal( centerViewPosition, vUv );',
  113. ' // jsfiddle that shows sample pattern: https://jsfiddle.net/a16ff1p7/',
  114. ' float angle = rand( vUv + randomSeed ) * PI2;',
  115. ' vec2 radius = vec2( kernelRadius * INV_NUM_SAMPLES ) / size;',
  116. ' vec2 radiusStep = radius;',
  117. ' float occlusionSum = 0.0;',
  118. ' float weightSum = 0.0;',
  119. ' for( int i = 0; i < NUM_SAMPLES; i ++ ) {',
  120. ' vec2 sampleUv = vUv + vec2( cos( angle ), sin( angle ) ) * radius;',
  121. ' radius += radiusStep;',
  122. ' angle += ANGLE_STEP;',
  123. ' float sampleDepth = getDepth( sampleUv );',
  124. ' if( sampleDepth >= ( 1.0 - EPSILON ) ) {',
  125. ' continue;',
  126. ' }',
  127. ' float sampleViewZ = getViewZ( sampleDepth );',
  128. ' vec3 sampleViewPosition = getViewPosition( sampleUv, sampleDepth, sampleViewZ );',
  129. ' occlusionSum += getOcclusion( centerViewPosition, centerViewNormal, sampleViewPosition );',
  130. ' weightSum += 1.0;',
  131. ' }',
  132. ' if( weightSum == 0.0 ) discard;',
  133. ' return occlusionSum * ( intensity / weightSum );',
  134. '}',
  135. 'void main() {',
  136. ' float centerDepth = getDepth( vUv );',
  137. ' if( centerDepth >= ( 1.0 - EPSILON ) ) {',
  138. ' discard;',
  139. ' }',
  140. ' float centerViewZ = getViewZ( centerDepth );',
  141. ' vec3 viewPosition = getViewPosition( vUv, centerDepth, centerViewZ );',
  142. ' float ambientOcclusion = getAmbientOcclusion( viewPosition );',
  143. ' gl_FragColor = getDefaultColor( vUv );',
  144. ' gl_FragColor.xyz *= 1.0 - ambientOcclusion;',
  145. '}'
  146. ].join( '\n' )
  147. };
  148. export { SAOShader };