title: OpenGL ES 2 Vertex Shader issue on Samsung Galaxy Tab 2
body: <p>I am developing for Android with OpenGL ES 2 and two devices: Google Nexus 3 and Archos 80 G9 (8" tablet). On these devices my shaders works fine.</p>
  
  <p>Now, i have bought a Samsung Galaxy Tab 2, and a single vertex shader does not work on this device. This shader (from OSGEarth) remove the problem of z-fighting for tracks on a 3D terrain, modulating the z value of the vertex. On Samsung Galaxy Tab 2 this modulation does not work (!)</p>
  
  <p>This is the shader</p>
  
  <pre><code>std::string vertexShaderSource =
  "#version 100\n\n"
  
  "float remap( float val, float vmin, float vmax, float r0, float r1 ) \n"
  "{ \n"
  "   float vr = (clamp(val, vmin, vmax)-vmin)/(vmax-vmin); \n"
  "   return r0 + vr * (r1-r0); \n"
  "} \n\n"
  
  "mat3 castMat4ToMat3Function(in mat4 m) \n"
  "{ \n"
  "   return mat3( m[0].xyz, m[1].xyz, m[2].xyz ); \n"
  "} \n\n"
  
  "uniform mat4 osg_ViewMatrix; \n"
  "uniform mat4 osg_ViewMatrixInverse; \n"
  "uniform mat4 osg_ModelViewMatrix; \n"
  "uniform mat4 osg_ProjectionMatrix; \n"
  "uniform mat4 osg_ModelViewProjectionMatrix; \n"
  "uniform float osgearth_depthoffset_minoffset; \n"
  "attribute vec4 osg_Vertex;\n"
  "attribute vec4 osg_Color;\n"
  "varying vec4 v_color; \n\n"
  "varying vec4 adjV; \n"
  "varying float simRange; \n\n"
  
  "void main(void) \n"
  "{ \n"
  
      // transform the vertex into eye space:
  "   vec4 vertEye  = osg_ModelViewMatrix * osg_Vertex; \n"
  "   vec3 vertEye3 = vertEye.xyz/vertEye.w; \n"
  "   float range = length(vertEye3); \n"
  
      // vec3 adjVecEye3 = normalize(vertEye3); \n"
      // calculate the "up" vector, that will be our adjustment vector:
  "   vec4 vertWorld = osg_ViewMatrixInverse * vertEye; \n"
  "   vec3 adjVecWorld3 = -normalize(vertWorld.xyz/vertWorld.w); \n"
  "   vec3 adjVecEye3 = castMat4ToMat3Function(osg_ViewMatrix) * adjVecWorld3; \n"
  
      // remap depth offset based on camera distance to vertex. The farther you are away,
      // the more of an offset you need.
  "   float offset = remap( range, 1000.0, 10000000.0, osgearth_depthoffset_minoffset, 10000.0); \n"
  
      // adjust the Z (distance from the eye) by our offset value:
  "   vertEye3 -= adjVecEye3 * offset; \n"
  "   vertEye.xyz = vertEye3 * vertEye.w; \n"
  
      // Transform the new adjusted vertex into clip space and pass it to the fragment shader.
  "   adjV = osg_ProjectionMatrix * vertEye; \n"
  
      // Also pass along the simulated range (eye=&gt;vertex distance). We will need this
     // to detect when the depth offset has pushed the Z value "behind" the camera.
  "   simRange = range - offset; \n"
  
  "   gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex; \n"
  "   v_color = osg_Color; \n"
  
      // transform clipspace depth into [0..1] for FragDepth:
  "   gl_Position.z = max(0.0, (adjV.z/adjV.w)*gl_Position.w ); \n"
  
      // if the offset pushed the Z behind the eye, the projection mapping will
      // result in a z&gt;1. We need to bring these values back down to the
      // near clip plan (z=0). We need to check simRange too before doing this
      // so we don't draw fragments that are legitimently beyond the far clip plane.
  "   float z = 0.5 * (1.0+(adjV.z/adjV.w)); \n"
  "   if ( z &gt; 1.0 &amp;&amp; simRange &lt; 0.0 ) { gl_Position.z = 0.0; } \n"
  
  "} \n" ;
  </code></pre>
  
  <p>With this code the track on the terrain is not displayed at all on SGT2. 
  If a comment the instruction<br>
  <strong>gl_Position.z = max(0.0, (adjV.z/adjV.w)*gl_Position.w );</strong><br>
  the shader works, and the track is displayed, but of course the z-figthing is not removed.</p>
  
  <p>My Google Nexus and Samsung Galaxy Tab 2 both use PowerVR SGX 540, so maybe the problem is in the Floating Point Math precision of the different CPU's? (Or some bug?) </p>
  
  <p>Any ideas?</p>
  
  <p>Thanks</p>
  
  <p>[SOLVED]
  I removed from the vertex shader</p>
  
  <pre><code>"varying vec4 adjV; \n"
  "varying float simRange; \n\n"
  </code></pre>
  
  <p>and declared them ad vec4/float.
  I think they where assigned mediump precision as varyings.</p>