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.
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 (!)
This is the shader (modified from original, to work on GLES2)
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=>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>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 > 1.0 && simRange < 0.0 ) { gl_Position.z = 0.0; } \n"
"} \n" ;
With this code the track on the terrain is not displayed at all on SGT2.
If a comment the instruction
gl_Position.z = max(0.0, (adjV.z/adjV.w)*gl_Position.w );
the shader works, and the track is displayed, but of course the z-figthing is
not removed.
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? (Nexus
should use OMAP4460, and Samsung OMAP4430)
Any ideas?
Thanks
Massimo[/code]
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=56041#56041
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org