DepthLimitedBlurShader.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import {
  2. Vector2
  3. } from '../../../build/three.module.js';
  4. /**
  5. * TODO
  6. */
  7. var DepthLimitedBlurShader = {
  8. defines: {
  9. 'KERNEL_RADIUS': 4,
  10. 'DEPTH_PACKING': 1,
  11. 'PERSPECTIVE_CAMERA': 1
  12. },
  13. uniforms: {
  14. 'tDiffuse': { value: null },
  15. 'size': { value: new Vector2( 512, 512 ) },
  16. 'sampleUvOffsets': { value: [ new Vector2( 0, 0 ) ] },
  17. 'sampleWeights': { value: [ 1.0 ] },
  18. 'tDepth': { value: null },
  19. 'cameraNear': { value: 10 },
  20. 'cameraFar': { value: 1000 },
  21. 'depthCutoff': { value: 10 },
  22. },
  23. vertexShader: [
  24. '#include <common>',
  25. 'uniform vec2 size;',
  26. 'varying vec2 vUv;',
  27. 'varying vec2 vInvSize;',
  28. 'void main() {',
  29. ' vUv = uv;',
  30. ' vInvSize = 1.0 / size;',
  31. ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
  32. '}'
  33. ].join( '\n' ),
  34. fragmentShader: [
  35. '#include <common>',
  36. '#include <packing>',
  37. 'uniform sampler2D tDiffuse;',
  38. 'uniform sampler2D tDepth;',
  39. 'uniform float cameraNear;',
  40. 'uniform float cameraFar;',
  41. 'uniform float depthCutoff;',
  42. 'uniform vec2 sampleUvOffsets[ KERNEL_RADIUS + 1 ];',
  43. 'uniform float sampleWeights[ KERNEL_RADIUS + 1 ];',
  44. 'varying vec2 vUv;',
  45. 'varying vec2 vInvSize;',
  46. 'float getDepth( const in vec2 screenPosition ) {',
  47. ' #if DEPTH_PACKING == 1',
  48. ' return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) );',
  49. ' #else',
  50. ' return texture2D( tDepth, screenPosition ).x;',
  51. ' #endif',
  52. '}',
  53. 'float getViewZ( const in float depth ) {',
  54. ' #if PERSPECTIVE_CAMERA == 1',
  55. ' return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );',
  56. ' #else',
  57. ' return orthographicDepthToViewZ( depth, cameraNear, cameraFar );',
  58. ' #endif',
  59. '}',
  60. 'void main() {',
  61. ' float depth = getDepth( vUv );',
  62. ' if( depth >= ( 1.0 - EPSILON ) ) {',
  63. ' discard;',
  64. ' }',
  65. ' float centerViewZ = -getViewZ( depth );',
  66. ' bool rBreak = false, lBreak = false;',
  67. ' float weightSum = sampleWeights[0];',
  68. ' vec4 diffuseSum = texture2D( tDiffuse, vUv ) * weightSum;',
  69. ' for( int i = 1; i <= KERNEL_RADIUS; i ++ ) {',
  70. ' float sampleWeight = sampleWeights[i];',
  71. ' vec2 sampleUvOffset = sampleUvOffsets[i] * vInvSize;',
  72. ' vec2 sampleUv = vUv + sampleUvOffset;',
  73. ' float viewZ = -getViewZ( getDepth( sampleUv ) );',
  74. ' if( abs( viewZ - centerViewZ ) > depthCutoff ) rBreak = true;',
  75. ' if( ! rBreak ) {',
  76. ' diffuseSum += texture2D( tDiffuse, sampleUv ) * sampleWeight;',
  77. ' weightSum += sampleWeight;',
  78. ' }',
  79. ' sampleUv = vUv - sampleUvOffset;',
  80. ' viewZ = -getViewZ( getDepth( sampleUv ) );',
  81. ' if( abs( viewZ - centerViewZ ) > depthCutoff ) lBreak = true;',
  82. ' if( ! lBreak ) {',
  83. ' diffuseSum += texture2D( tDiffuse, sampleUv ) * sampleWeight;',
  84. ' weightSum += sampleWeight;',
  85. ' }',
  86. ' }',
  87. ' gl_FragColor = diffuseSum / weightSum;',
  88. '}'
  89. ].join( '\n' )
  90. };
  91. var BlurShaderUtils = {
  92. createSampleWeights: function ( kernelRadius, stdDev ) {
  93. var gaussian = function ( x, stdDev ) {
  94. return Math.exp( - ( x * x ) / ( 2.0 * ( stdDev * stdDev ) ) ) / ( Math.sqrt( 2.0 * Math.PI ) * stdDev );
  95. };
  96. var weights = [];
  97. for ( var i = 0; i <= kernelRadius; i ++ ) {
  98. weights.push( gaussian( i, stdDev ) );
  99. }
  100. return weights;
  101. },
  102. createSampleOffsets: function ( kernelRadius, uvIncrement ) {
  103. var offsets = [];
  104. for ( var i = 0; i <= kernelRadius; i ++ ) {
  105. offsets.push( uvIncrement.clone().multiplyScalar( i ) );
  106. }
  107. return offsets;
  108. },
  109. configure: function ( material, kernelRadius, stdDev, uvIncrement ) {
  110. material.defines[ 'KERNEL_RADIUS' ] = kernelRadius;
  111. material.uniforms[ 'sampleUvOffsets' ].value = BlurShaderUtils.createSampleOffsets( kernelRadius, uvIncrement );
  112. material.uniforms[ 'sampleWeights' ].value = BlurShaderUtils.createSampleWeights( kernelRadius, stdDev );
  113. material.needsUpdate = true;
  114. }
  115. };
  116. export { DepthLimitedBlurShader, BlurShaderUtils };