1#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING)
2    vec2 steepParallaxOffset(sampler2D parallaxMap, vec3 vViewDir,vec2 texCoord,float parallaxScale){
3        vec2 vParallaxDirection = normalize(  vViewDir.xy );
4
5        // The length of this vector determines the furthest amount of displacement: (Ati's comment)
6        float fLength         = length( vViewDir );
7        float fParallaxLength = sqrt( fLength * fLength - vViewDir.z * vViewDir.z ) / vViewDir.z;
8
9        // Compute the actual reverse parallax displacement vector: (Ati's comment)
10        vec2 vParallaxOffsetTS = vParallaxDirection * fParallaxLength;
11
12        // Need to scale the amount of displacement to account for different height ranges
13        // in height maps. This is controlled by an artist-editable parameter: (Ati's comment)
14        parallaxScale *=0.3;
15        vParallaxOffsetTS *= parallaxScale;
16
17       vec3 eyeDir = normalize(vViewDir).xyz;
18
19        float nMinSamples = 6.0;
20        float nMaxSamples = 1000.0 * parallaxScale;
21        float nNumSamples = mix( nMinSamples, nMaxSamples, 1.0 - eyeDir.z );   //In reference shader: int nNumSamples = (int)(lerp( nMinSamples, nMaxSamples, dot( eyeDirWS, N ) ));
22        float fStepSize = 1.0 / nNumSamples;
23        float fCurrHeight = 0.0;
24        float fPrevHeight = 1.0;
25        float fNextHeight = 0.0;
26        float nStepIndex = 0.0;
27        vec2 vTexOffsetPerStep = fStepSize * vParallaxOffsetTS;
28        vec2 vTexCurrentOffset = texCoord;
29        float  fCurrentBound     = 1.0;
30        float  fParallaxAmount   = 0.0;
31
32        while ( nStepIndex < nNumSamples && fCurrHeight <= fCurrentBound ) {
33            vTexCurrentOffset -= vTexOffsetPerStep;
34            fPrevHeight = fCurrHeight;
35
36
37           #ifdef NORMALMAP_PARALLAX
38               //parallax map is stored in the alpha channel of the normal map
39               fCurrHeight = texture2DLod( parallaxMap, vTexCurrentOffset,1.0).a;
40           #else
41               //parallax map is a texture
42               fCurrHeight = texture2DLod( parallaxMap, vTexCurrentOffset,1.0).r;
43           #endif
44
45            fCurrentBound -= fStepSize;
46            nStepIndex+=1.0;
47        }
48        vec2 pt1 = vec2( fCurrentBound, fCurrHeight );
49        vec2 pt2 = vec2( fCurrentBound + fStepSize, fPrevHeight );
50
51        float fDelta2 = pt2.x - pt2.y;
52        float fDelta1 = pt1.x - pt1.y;
53
54        float fDenominator = fDelta2 - fDelta1;
55
56        fParallaxAmount = (pt1.x * fDelta2 - pt2.x * fDelta1 ) / fDenominator;
57
58        vec2 vParallaxOffset = vParallaxOffsetTS * (1.0 - fParallaxAmount );
59       return texCoord - vParallaxOffset;
60    }
61
62    vec2 classicParallaxOffset(sampler2D parallaxMap, vec3 vViewDir,vec2 texCoord,float parallaxScale){
63       float h;
64       h = texture2D(parallaxMap, texCoord).a;
65       #ifdef NORMALMAP_PARALLAX
66               //parallax map is stored in the alpha channel of the normal map
67               h = texture2D(parallaxMap, texCoord).a;
68       #else
69               //parallax map is a texture
70               h = texture2D(parallaxMap, texCoord).r;
71       #endif
72       float heightScale = parallaxScale;
73       float heightBias = heightScale* -0.6;
74       vec3 normView = normalize(vViewDir);
75       h = (h * heightScale + heightBias) * normView.z;
76       return texCoord + (h * normView.xy);
77    }
78#endif