#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING) | |
vec2 steepParallaxOffset(sampler2D parallaxMap, vec3 vViewDir,vec2 texCoord,float parallaxScale){ | |
vec2 vParallaxDirection = normalize( vViewDir.xy ); | |
// The length of this vector determines the furthest amount of displacement: (Ati's comment) | |
float fLength = length( vViewDir ); | |
float fParallaxLength = sqrt( fLength * fLength - vViewDir.z * vViewDir.z ) / vViewDir.z; | |
// Compute the actual reverse parallax displacement vector: (Ati's comment) | |
vec2 vParallaxOffsetTS = vParallaxDirection * fParallaxLength; | |
// Need to scale the amount of displacement to account for different height ranges | |
// in height maps. This is controlled by an artist-editable parameter: (Ati's comment) | |
parallaxScale *=0.3; | |
vParallaxOffsetTS *= parallaxScale; | |
vec3 eyeDir = normalize(vViewDir).xyz; | |
float nMinSamples = 6.0; | |
float nMaxSamples = 1000.0 * parallaxScale; | |
float nNumSamples = mix( nMinSamples, nMaxSamples, 1.0 - eyeDir.z ); //In reference shader: int nNumSamples = (int)(lerp( nMinSamples, nMaxSamples, dot( eyeDirWS, N ) )); | |
float fStepSize = 1.0 / nNumSamples; | |
float fCurrHeight = 0.0; | |
float fPrevHeight = 1.0; | |
float fNextHeight = 0.0; | |
float nStepIndex = 0.0; | |
vec2 vTexOffsetPerStep = fStepSize * vParallaxOffsetTS; | |
vec2 vTexCurrentOffset = texCoord; | |
float fCurrentBound = 1.0; | |
float fParallaxAmount = 0.0; | |
while ( nStepIndex < nNumSamples && fCurrHeight <= fCurrentBound ) { | |
vTexCurrentOffset -= vTexOffsetPerStep; | |
fPrevHeight = fCurrHeight; | |
#ifdef NORMALMAP_PARALLAX | |
//parallax map is stored in the alpha channel of the normal map | |
fCurrHeight = texture2DLod( parallaxMap, vTexCurrentOffset,1.0).a; | |
#else | |
//parallax map is a texture | |
fCurrHeight = texture2DLod( parallaxMap, vTexCurrentOffset,1.0).r; | |
#endif | |
fCurrentBound -= fStepSize; | |
nStepIndex+=1.0; | |
} | |
vec2 pt1 = vec2( fCurrentBound, fCurrHeight ); | |
vec2 pt2 = vec2( fCurrentBound + fStepSize, fPrevHeight ); | |
float fDelta2 = pt2.x - pt2.y; | |
float fDelta1 = pt1.x - pt1.y; | |
float fDenominator = fDelta2 - fDelta1; | |
fParallaxAmount = (pt1.x * fDelta2 - pt2.x * fDelta1 ) / fDenominator; | |
vec2 vParallaxOffset = vParallaxOffsetTS * (1.0 - fParallaxAmount ); | |
return texCoord - vParallaxOffset; | |
} | |
vec2 classicParallaxOffset(sampler2D parallaxMap, vec3 vViewDir,vec2 texCoord,float parallaxScale){ | |
float h; | |
h = texture2D(parallaxMap, texCoord).a; | |
#ifdef NORMALMAP_PARALLAX | |
//parallax map is stored in the alpha channel of the normal map | |
h = texture2D(parallaxMap, texCoord).a; | |
#else | |
//parallax map is a texture | |
h = texture2D(parallaxMap, texCoord).r; | |
#endif | |
float heightScale = parallaxScale; | |
float heightBias = heightScale* -0.6; | |
vec3 normView = normalize(vViewDir); | |
h = (h * heightScale + heightBias) * normView.z; | |
return texCoord + (h * normView.xy); | |
} | |
#endif |