1

我正在使用 OpenGL ES 2 和两个设备为 Android 开发:Google Nexus 3 和 Archos 80 G9(8" 平板电脑)。在这些设备上,我的着色器工作正常。

现在,我购买了三星 Galaxy Tab 2,但单个顶点着色器无法在此设备上运行。这个着色器(来自 OSGEarth)消除了 3D 地形上轨道的 z-fighting 问题,调制顶点的 z 值。在三星 Galaxy Tab 2 上,此调制不起作用(!)

这是着色器

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" ;

使用此代码,地形上的轨迹根本不会在 SGT2 上显示。如果注释指令
gl_Position.z = max(0.0, (adjV.z/adjV.w)*gl_Position.w );
着色器工作,并显示轨道,但当然 z-figthing 没有被删除。

我的 Google Nexus 和三星 Galaxy Tab 2 都使用 PowerVR SGX 540,所以问题可能出在不同 CPU 的浮点数学精度上?(或者一些错误?)

有任何想法吗?

谢谢

[已解决] 我从顶点着色器中删除

"varying vec4 adjV; \n"
"varying float simRange; \n\n"

并将它们声明为 ad vec4/float。我认为他们将 mediump 精度分配为变量。

4

0 回答 0