OpenGL ES 片元着色器中 int 类型精度不匹配的问题分析
太阳火神的美丽人生 (http://blog.csdn.net/opengl_es)
本文遵循“署名-非商业用途-保持一致”创作公用协议
最终解决方法补充:
------------------------
经过反复分析和测试,最终定位问题并非是 int 类型在片元着色器中不能使用,而是在顶点和片元着色器中同时使用会出现问题,与变量在两着色器中同时声明并无关系。
去掉顶点着色器中的使用,即使保留其声明也是没问题的,因为两个着色器顶部都做了精度声明:
precision highp float;
分析,可能是在运算过程中,导致进行了类型转换,
不过这个说法也是说不太通的,暂时只是解决了问题,还不清楚问题的真正原因,
希望之后的使用中能以这种经验教训为戒,尽量避勉简单类型在两着色器中同时使用,这样可能会导致精度不匹配的问题发生。
------------------------
补充:
--------
问题已解决,涉及 int 变量的计算,从整体计算中拨离出来,放在顶点着色器中去计算,然后把其计算的结果(一般是矩阵或矢量)作为参数传递到片元着色器,再进一步进行计算。
将 int 相关的计算之后的结果,作为一个中间量而独立出来,并且该中间量是非 int 类型的,即可作为参数输出到片元着色器。
总是感觉应该有更好的方式来解决 int 的问题和 int 变量在片元着色器中精度的问题。
在着色器中灯光计算函数中增加相应该 int 值的引用:
vec4 combineLight (vec3 pLightPositionCoordinate, vec3 pAmbientMaterial, vec3 pDiffuseMaterial, vec3 pSpecularMaterial, float pShininessMaterial, mat3 pNormalMatrix, vec3 pNormalCoordinate) { vec3 N = uNormalMatrix * pNormalCoordinate; if (1 == uRevertNormalIf) { N = uNormalMatrix * (-pNormalCoordinate); } vec3 L = normalize(pLightPositionCoordinate); vec3 E = vec3(0, 0, 1); vec3 H = normalize(L + E); float df = max(0.0, dot(N, L)); float sf = max(0.0, dot(N, H)); sf = pow(sf, pShininessMaterial); // 合成环境光、反射光、镜面高光 vec3 combinedLightColor = pAmbientMaterial + df * pDiffuseMaterial + sf * pShininessMaterial; vec4 lighColor = vec4(combinedLightColor+combinedLightColor+combinedLightColor, 1); return lighColor; }以上代码中再改成不使用该 int 变量的情况测试:
vec3 N = uNormalMatrix * pNormalCoordinate; if (1 == 1) { N = uNormalMatrix * (-pNormalCoordinate); }
------------------
如下提示:
2014-01-03 11:48:13.584 Tutorial12[75037:70b] Error compiling shader: ERROR: 0:35: int can't be an out in the vertex shader
这个int型的全局变量,在顶点着色器中可以正常获取到值,但在片元着色器中使用,就会提示精度不匹配。
所以想了一下,从顶点着色器接收到该值后,通过参数变量输出到片元着色器再使用,
可是结果如上所示,并未达成。
ERROR: Uniform precision mismatch 'uRevertNormalIf' 2014-01-03 17:30:17.835 Tutorial12[77675:70b] >> Error: Failed to setup program.
在片元着色器中,通过明确的指定 int 型全局变量与本地函数参数的精度来匹配,高、中、低均偿试过了,仍无法解决,尚不知这个问题的根本原因。
以上作为一个问题留下,暂时先写死跳过,后续解决,再补充。