ParallaxShader.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. console.warn( "THREE.ParallaxShader: As part of the transition to ES6 Modules, the files in 'examples/js' were deprecated in May 2020 (r117) and will be deleted in December 2020 (r124). You can find more information about developing using ES6 Modules in https://threejs.org/docs/#manual/en/introduction/Installation." );
  2. // Parallax Occlusion shaders from
  3. // http://sunandblackcat.com/tipFullView.php?topicid=28
  4. // No tangent-space transforms logic based on
  5. // http://mmikkelsen3d.blogspot.sk/2012/02/parallaxpoc-mapping-and-no-tangent.html
  6. THREE.ParallaxShader = {
  7. // Ordered from fastest to best quality.
  8. modes: {
  9. none: "NO_PARALLAX",
  10. basic: "USE_BASIC_PARALLAX",
  11. steep: "USE_STEEP_PARALLAX",
  12. occlusion: "USE_OCLUSION_PARALLAX", // a.k.a. POM
  13. relief: "USE_RELIEF_PARALLAX"
  14. },
  15. uniforms: {
  16. "bumpMap": { value: null },
  17. "map": { value: null },
  18. "parallaxScale": { value: null },
  19. "parallaxMinLayers": { value: null },
  20. "parallaxMaxLayers": { value: null }
  21. },
  22. vertexShader: [
  23. "varying vec2 vUv;",
  24. "varying vec3 vViewPosition;",
  25. "varying vec3 vNormal;",
  26. "void main() {",
  27. " vUv = uv;",
  28. " vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
  29. " vViewPosition = -mvPosition.xyz;",
  30. " vNormal = normalize( normalMatrix * normal );",
  31. " gl_Position = projectionMatrix * mvPosition;",
  32. "}"
  33. ].join( "\n" ),
  34. fragmentShader: [
  35. "uniform sampler2D bumpMap;",
  36. "uniform sampler2D map;",
  37. "uniform float parallaxScale;",
  38. "uniform float parallaxMinLayers;",
  39. "uniform float parallaxMaxLayers;",
  40. "varying vec2 vUv;",
  41. "varying vec3 vViewPosition;",
  42. "varying vec3 vNormal;",
  43. "#ifdef USE_BASIC_PARALLAX",
  44. " vec2 parallaxMap( in vec3 V ) {",
  45. " float initialHeight = texture2D( bumpMap, vUv ).r;",
  46. // No Offset Limitting: messy, floating output at grazing angles.
  47. //"vec2 texCoordOffset = parallaxScale * V.xy / V.z * initialHeight;",
  48. // Offset Limiting
  49. " vec2 texCoordOffset = parallaxScale * V.xy * initialHeight;",
  50. " return vUv - texCoordOffset;",
  51. " }",
  52. "#else",
  53. " vec2 parallaxMap( in vec3 V ) {",
  54. // Determine number of layers from angle between V and N
  55. " float numLayers = mix( parallaxMaxLayers, parallaxMinLayers, abs( dot( vec3( 0.0, 0.0, 1.0 ), V ) ) );",
  56. " float layerHeight = 1.0 / numLayers;",
  57. " float currentLayerHeight = 0.0;",
  58. // Shift of texture coordinates for each iteration
  59. " vec2 dtex = parallaxScale * V.xy / V.z / numLayers;",
  60. " vec2 currentTextureCoords = vUv;",
  61. " float heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r;",
  62. // while ( heightFromTexture > currentLayerHeight )
  63. // Infinite loops are not well supported. Do a "large" finite
  64. // loop, but not too large, as it slows down some compilers.
  65. " for ( int i = 0; i < 30; i += 1 ) {",
  66. " if ( heightFromTexture <= currentLayerHeight ) {",
  67. " break;",
  68. " }",
  69. " currentLayerHeight += layerHeight;",
  70. // Shift texture coordinates along vector V
  71. " currentTextureCoords -= dtex;",
  72. " heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r;",
  73. " }",
  74. " #ifdef USE_STEEP_PARALLAX",
  75. " return currentTextureCoords;",
  76. " #elif defined( USE_RELIEF_PARALLAX )",
  77. " vec2 deltaTexCoord = dtex / 2.0;",
  78. " float deltaHeight = layerHeight / 2.0;",
  79. // Return to the mid point of previous layer
  80. " currentTextureCoords += deltaTexCoord;",
  81. " currentLayerHeight -= deltaHeight;",
  82. // Binary search to increase precision of Steep Parallax Mapping
  83. " const int numSearches = 5;",
  84. " for ( int i = 0; i < numSearches; i += 1 ) {",
  85. " deltaTexCoord /= 2.0;",
  86. " deltaHeight /= 2.0;",
  87. " heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r;",
  88. // Shift along or against vector V
  89. " if( heightFromTexture > currentLayerHeight ) {", // Below the surface
  90. " currentTextureCoords -= deltaTexCoord;",
  91. " currentLayerHeight += deltaHeight;",
  92. " } else {", // above the surface
  93. " currentTextureCoords += deltaTexCoord;",
  94. " currentLayerHeight -= deltaHeight;",
  95. " }",
  96. " }",
  97. " return currentTextureCoords;",
  98. " #elif defined( USE_OCLUSION_PARALLAX )",
  99. " vec2 prevTCoords = currentTextureCoords + dtex;",
  100. // Heights for linear interpolation
  101. " float nextH = heightFromTexture - currentLayerHeight;",
  102. " float prevH = texture2D( bumpMap, prevTCoords ).r - currentLayerHeight + layerHeight;",
  103. // Proportions for linear interpolation
  104. " float weight = nextH / ( nextH - prevH );",
  105. // Interpolation of texture coordinates
  106. " return prevTCoords * weight + currentTextureCoords * ( 1.0 - weight );",
  107. " #else", // NO_PARALLAX
  108. " return vUv;",
  109. " #endif",
  110. " }",
  111. "#endif",
  112. "vec2 perturbUv( vec3 surfPosition, vec3 surfNormal, vec3 viewPosition ) {",
  113. " vec2 texDx = dFdx( vUv );",
  114. " vec2 texDy = dFdy( vUv );",
  115. " vec3 vSigmaX = dFdx( surfPosition );",
  116. " vec3 vSigmaY = dFdy( surfPosition );",
  117. " vec3 vR1 = cross( vSigmaY, surfNormal );",
  118. " vec3 vR2 = cross( surfNormal, vSigmaX );",
  119. " float fDet = dot( vSigmaX, vR1 );",
  120. " vec2 vProjVscr = ( 1.0 / fDet ) * vec2( dot( vR1, viewPosition ), dot( vR2, viewPosition ) );",
  121. " vec3 vProjVtex;",
  122. " vProjVtex.xy = texDx * vProjVscr.x + texDy * vProjVscr.y;",
  123. " vProjVtex.z = dot( surfNormal, viewPosition );",
  124. " return parallaxMap( vProjVtex );",
  125. "}",
  126. "void main() {",
  127. " vec2 mapUv = perturbUv( -vViewPosition, normalize( vNormal ), normalize( vViewPosition ) );",
  128. " gl_FragColor = texture2D( map, mapUv );",
  129. "}"
  130. ].join( "\n" )
  131. };