DepthLimitedBlurShader.js 3.8 KB

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