123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- // Parallax Occlusion shaders from
- // http://sunandblackcat.com/tipFullView.php?topicid=28
- // No tangent-space transforms logic based on
- // http://mmikkelsen3d.blogspot.sk/2012/02/parallaxpoc-mapping-and-no-tangent.html
- THREE.ParallaxShader = {
- // Ordered from fastest to best quality.
- modes: {
- none: 'NO_PARALLAX',
- basic: 'USE_BASIC_PARALLAX',
- steep: 'USE_STEEP_PARALLAX',
- occlusion: 'USE_OCLUSION_PARALLAX', // a.k.a. POM
- relief: 'USE_RELIEF_PARALLAX'
- },
- uniforms: {
- "bumpMap": { value: null },
- "map": { value: null },
- "parallaxScale": { value: null },
- "parallaxMinLayers": { value: null },
- "parallaxMaxLayers": { value: null }
- },
- vertexShader: [
- "varying vec2 vUv;",
- "varying vec3 vViewPosition;",
- "varying vec3 vNormal;",
- "void main() {",
- " vUv = uv;",
- " vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
- " vViewPosition = -mvPosition.xyz;",
- " vNormal = normalize( normalMatrix * normal );",
- " gl_Position = projectionMatrix * mvPosition;",
- "}"
- ].join( "\n" ),
- fragmentShader: [
- "uniform sampler2D bumpMap;",
- "uniform sampler2D map;",
- "uniform float parallaxScale;",
- "uniform float parallaxMinLayers;",
- "uniform float parallaxMaxLayers;",
- "varying vec2 vUv;",
- "varying vec3 vViewPosition;",
- "varying vec3 vNormal;",
- "#ifdef USE_BASIC_PARALLAX",
- " vec2 parallaxMap( in vec3 V ) {",
- " float initialHeight = texture2D( bumpMap, vUv ).r;",
- // No Offset Limitting: messy, floating output at grazing angles.
- //"vec2 texCoordOffset = parallaxScale * V.xy / V.z * initialHeight;",
- // Offset Limiting
- " vec2 texCoordOffset = parallaxScale * V.xy * initialHeight;",
- " return vUv - texCoordOffset;",
- " }",
- "#else",
- " vec2 parallaxMap( in vec3 V ) {",
- // Determine number of layers from angle between V and N
- " float numLayers = mix( parallaxMaxLayers, parallaxMinLayers, abs( dot( vec3( 0.0, 0.0, 1.0 ), V ) ) );",
- " float layerHeight = 1.0 / numLayers;",
- " float currentLayerHeight = 0.0;",
- // Shift of texture coordinates for each iteration
- " vec2 dtex = parallaxScale * V.xy / V.z / numLayers;",
- " vec2 currentTextureCoords = vUv;",
- " float heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r;",
- // while ( heightFromTexture > currentLayerHeight )
- // Infinite loops are not well supported. Do a "large" finite
- // loop, but not too large, as it slows down some compilers.
- " for ( int i = 0; i < 30; i += 1 ) {",
- " if ( heightFromTexture <= currentLayerHeight ) {",
- " break;",
- " }",
- " currentLayerHeight += layerHeight;",
- // Shift texture coordinates along vector V
- " currentTextureCoords -= dtex;",
- " heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r;",
- " }",
- " #ifdef USE_STEEP_PARALLAX",
- " return currentTextureCoords;",
- " #elif defined( USE_RELIEF_PARALLAX )",
- " vec2 deltaTexCoord = dtex / 2.0;",
- " float deltaHeight = layerHeight / 2.0;",
- // Return to the mid point of previous layer
- " currentTextureCoords += deltaTexCoord;",
- " currentLayerHeight -= deltaHeight;",
- // Binary search to increase precision of Steep Parallax Mapping
- " const int numSearches = 5;",
- " for ( int i = 0; i < numSearches; i += 1 ) {",
- " deltaTexCoord /= 2.0;",
- " deltaHeight /= 2.0;",
- " heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r;",
- // Shift along or against vector V
- " if( heightFromTexture > currentLayerHeight ) {", // Below the surface
- " currentTextureCoords -= deltaTexCoord;",
- " currentLayerHeight += deltaHeight;",
- " } else {", // above the surface
- " currentTextureCoords += deltaTexCoord;",
- " currentLayerHeight -= deltaHeight;",
- " }",
- " }",
- " return currentTextureCoords;",
- " #elif defined( USE_OCLUSION_PARALLAX )",
- " vec2 prevTCoords = currentTextureCoords + dtex;",
- // Heights for linear interpolation
- " float nextH = heightFromTexture - currentLayerHeight;",
- " float prevH = texture2D( bumpMap, prevTCoords ).r - currentLayerHeight + layerHeight;",
- // Proportions for linear interpolation
- " float weight = nextH / ( nextH - prevH );",
- // Interpolation of texture coordinates
- " return prevTCoords * weight + currentTextureCoords * ( 1.0 - weight );",
- " #else", // NO_PARALLAX
- " return vUv;",
- " #endif",
- " }",
- "#endif",
- "vec2 perturbUv( vec3 surfPosition, vec3 surfNormal, vec3 viewPosition ) {",
- " vec2 texDx = dFdx( vUv );",
- " vec2 texDy = dFdy( vUv );",
- " vec3 vSigmaX = dFdx( surfPosition );",
- " vec3 vSigmaY = dFdy( surfPosition );",
- " vec3 vR1 = cross( vSigmaY, surfNormal );",
- " vec3 vR2 = cross( surfNormal, vSigmaX );",
- " float fDet = dot( vSigmaX, vR1 );",
- " vec2 vProjVscr = ( 1.0 / fDet ) * vec2( dot( vR1, viewPosition ), dot( vR2, viewPosition ) );",
- " vec3 vProjVtex;",
- " vProjVtex.xy = texDx * vProjVscr.x + texDy * vProjVscr.y;",
- " vProjVtex.z = dot( surfNormal, viewPosition );",
- " return parallaxMap( vProjVtex );",
- "}",
- "void main() {",
- " vec2 mapUv = perturbUv( -vViewPosition, normalize( vNormal ), normalize( vViewPosition ) );",
- " gl_FragColor = texture2D( map, mapUv );",
- "}"
- ].join( "\n" )
- };
|