   POM HLSL - GLSL
  Hey,I tried to translate the POM algorithm from gamedev to GLSL but the output is a black quad. Does anyone spot the mistake?Original HLSL implementation from this site://-----------------------------------------------------------------------------// parallax.fx////-----------------------------------------------------------------------------//-----------------------------------------------------------------------------// Parameters//-----------------------------------------------------------------------------float4x4 mWVP: WorldViewProjection;float4x4 mW: World;texture texColorHeight: ColorMap0; float4  EyePositionWS: ViewPosition;floatfHeightMapScale= 0.04;floatfTexelsPerSide= sqrt(512.0 * 512.0 * 2);intnMaxSamples= 50;intnMinSamples= 4;//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------// Samplers//-----------------------------------------------------------------------------sampler Sampler = sampler_state{    Texture   = (texColorHeight);    MipFilter = LINEAR;    MinFilter = LINEAR;    MagFilter = LINEAR;    AddressU = Wrap;    AddressV = Wrap;};//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------struct vertex{   float3 position: POSITION;   float2 texcoord: TEXCOORD0;   float3 normal: NORMAL;   float3 tangent: TANGENT;   float3 binormal: BINORMAL;};//-----------------------------------------------------------------------------struct fragment{float4 position: POSITION;float2 texcoord: TEXCOORD0;float3 eye: TEXCOORD1;float3 normal   : TEXCOORD2;};//-----------------------------------------------------------------------------struct pixel{float4 color: COLOR;};//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------// Vertex Shader//-----------------------------------------------------------------------------fragment VS( vertex IN ){    fragment OUT;float4 VertexPositionWS = mul( float4(IN.position, 1), mW );float3 P = VertexPositionWS.xyz;float3 E = EyePositionWS.xyz - P;// The per-vertex tangent, binormal, normal form the tangent to object space// rotation matrix.  Multiply by the world matrix to form tangent to world space// rotation matrix.  Then transpose the matrix to form the inverse tangent to// world space, otherwise called the world to tangent space rotation matrix.float3x3 tangentToWorldSpace;tangentToWorldSpace[0] = mul( IN.tangent, mW );tangentToWorldSpace[1] = mul( IN.binormal, mW );tangentToWorldSpace[2] = mul( IN.normal, mW );float3x3 worldToTangentSpace = transpose(tangentToWorldSpace);OUT.position = mul( float4(IN.position, 1), mWVP );// standard transformation to clip spaceOUT.texcoord = IN.texcoord;// pass through the original texcoordsOUT.eye = mul( E, worldToTangentSpace );// pass through the TANGENT space eye vector (un-normalized)OUT.normal = mul( IN.normal, worldToTangentSpace );// pass through the TANGENT space normal vector (un-normalized)return OUT;}//-----------------------------------------------------------------------------// Pixel Shader//-----------------------------------------------------------------------------pixel PS( fragment IN ){pixel OUT;float fParallaxLimit = length(IN.eye.xy) / IN.eye.z;// calculate the parallax offset vector max lengthfParallaxLimit *= fHeightMapScale;// scale the vector according to height-map scalefloat2 vOffset = normalize( -IN.eye.xy );// calculate the parallax offset vector directionvOffset = vOffset * fParallaxLimit;// calculate the final maximum offset vectorfloat3 E = normalize(IN.eye);float3 N = normalize(IN.normal);//int nNumSamples = (int)lerp( nMaxSamples, nMinSamples, dot( E, N ) );// calculate dynamic number of samples (Tatarchuk's method)int nNumSamples = (int)(fParallaxLimit * fTexelsPerSide);// calculate dynamic number of samples (Zink's method)float fStepSize = 1.0 / (float)nNumSamples;// calculate the texcoord step sizefloat2 dx, dy;dx = ddx( IN.texcoord );// calculate the texcoord partial derivative in x in screen space for tex2Dgraddy = ddy( IN.texcoord );// calculate the texcoord partial derivative in y in screen space for tex2Dgradfloat2 vOffsetStep = fStepSize * vOffset;float2 vCurrOffset = float2( 0, 0 );float2 vLastOffset = float2( 0, 0 );float2 vFinalOffset = float2( 0, 0 );float4 vCurrSample;float4 vLastSample;float stepHeight = 1.0;int nCurrSample = 0;while ( nCurrSample < nNumSamples ){vCurrSample = tex2Dgrad( Sampler, IN.texcoord + vCurrOffset, dx, dy );// sample the current texcoord offsetif ( vCurrSample.a > stepHeight ){// calculate the linear intersection pointfloat Ua = (vLastSample.a - (stepHeight+fStepSize)) / ( fStepSize + (vCurrSample.a - vLastSample.a));vFinalOffset = vLastOffset + Ua * vOffsetStep;vCurrSample = tex2Dgrad( Sampler, IN.texcoord + vFinalOffset, dx, dy );// sample the corrected tex coordsnCurrSample = nNumSamples + 1;// exit the while loop}else{nCurrSample++;// increment to the next samplestepHeight -= fStepSize;// change the required height-map heightvLastOffset = vCurrOffset;// remember this texcoord offset for next timevCurrOffset += vOffsetStep;// increment to the next texcoord offsetvLastSample = vCurrSample;}}OUT.color = vCurrSample;// return the final sampled color valuereturn OUT;}//-----------------------------------------------------------------------------// Techniques//-----------------------------------------------------------------------------technique LitTexturedSpecular{    pass Pass0    {VertexShader = compile vs_3_0 VS();PixelShader  = compile ps_3_0 PS();    }}//-----------------------------------------------------------------------------My GLSL approach:VertexShader: I'm working with parallel projected textures so I don't need to calculate the eye vector per vertex since it's equal for a whole texture. I calculate a tangent space normalized eye vector in the application and pass it over to the frag shader. gl_TexCoord[0] is the original depth map.#version 120void main(void){gl_TexCoord[0] = gl_MultiTexCoord0;gl_Position = ftransform();}FragmentShader:#version 120#extension GL_ARB_shader_texture_lod : requireconst float HEIGHTMAP_SCALE = 0.04f;  // not sure what this is forconst int nMinSamples = 4;const int nMaxSamples = 50;uniform vec3 vEye;uniform sampler2D sampler;void main(void){// determine max parallax offset length// length(vEye) is always 1.0ffloat fParallaxLimit = 1.0f / vEye.z;fParallaxLimit *= HEIGHTMAP_SCALE;// calculate direction of offset vectorvec2 vOffset = vec2(-vEye.x, -vEye.y);vOffset = normalize(vOffset) * fParallaxLimit;// calculate dynamic number of samples// vEye.z = dot(vEye, normal) with normal in tangent space always being (0,0,1)int nNumSamples = mix(nMinSamples, nMaxSamples, vEye.z);float fStepsize = 1.0 / (float)nNumSamples;// calculate texture gradients in screen spacevec2 dx, dy;dx = dFdx(gl_TexCoord[0].st);dy = dFdy(gl_TexCoord[0].st);vec2 vOffsetStep = fStepsize * vOffset;vec2 vCurrOffset = vec2(0, 0);vec2 vLastOffset = vec2(0, 0);vec2 vFinalOffset = vec2(0, 0);vec4 vCurrSample;vec4 vLastSample;float fStepHeight = 1.0;int nCurrSample = 0;while(nCurrSample < nNumSamples ){// sample the current texcoord offsetvCurrSample = texture2DGradARB(sampler, gl_TexCoord[0].st + vCurrOffset, dx, dy);if(vCurrSample.w > fStepHeight){float Ua = (vLastSample.w - (fStepHeight + fStepsize))/ (fStepsize + (vCurrSample.w - vLastSample.w));vFinalOffset = vLastOffset + Ua * vOffsetStep;vCurrSample = texture2Dgrad(sampler, gl_TexCoord[0].st + vFinalOffset, dx, dy);nCurrSample = nNumSamples + 1;}else{nCurrSample++;fStepHeight -= fStepsize;vLastOffset = vCurrOffset;vCurrOffset += vOffsetStep;vLastSample = nCurrSample;}}gl_FragColor = vCurrSample;}
  Ok, put in other words: What can I do to find the mistake? Since there's no debugging for shaders I feel kinda lost because I walked through the code a billion times and just can't find a mistake (it's definitely possible that there still is one because my GLSL skills aren't very good)   ;  You just have to be creative. Try building it in small stages and check that it is working as you go along. First maybe just try to set the output fragcolor as red. Do you see a red quad? If no, then there's something wrong with your vertices or opengl setup. Just pick intermediate variables from your frag shader and output them as colors that you can identify, so you can see if it looks like you expect. Or if you don't see anything from them, maybe you know that there is a problem with those variables.It's very hard to just write a giant shader all at once and hope for the best.   