|
@@ -1,184 +0,0 @@
|
|
|
-// 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
|
|
|
-
|
|
|
-const 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: /* glsl */`
|
|
|
-
|
|
|
- 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;
|
|
|
-
|
|
|
- }`,
|
|
|
-
|
|
|
- fragmentShader: /* glsl */`
|
|
|
-
|
|
|
- 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 );
|
|
|
-
|
|
|
- }`
|
|
|
-
|
|
|
-};
|
|
|
-
|
|
|
-export { ParallaxShader };
|