DepthLimitedBlurShader.js 3.7 KB

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