Opengl GLSL(330)模返回意外值
我目前正在使用GLSL 330,遇到了mod()函数的一些奇怪行为。 我在windows 8下使用Radeon HD 6470M。我无法在使用windows 7和GeForce GTX 260的桌面PC上重新创建此行为 以下是我的测试代码:Opengl GLSL(330)模返回意外值,opengl,glsl,modulo,opengl-3,Opengl,Glsl,Modulo,Opengl 3,我目前正在使用GLSL 330,遇到了mod()函数的一些奇怪行为。 我在windows 8下使用Radeon HD 6470M。我无法在使用windows 7和GeForce GTX 260的桌面PC上重新创建此行为 以下是我的测试代码: float testvalf = -126; vec2 testval = vec2(-126, -126); float modtest1 = mod(testvalf, 63.0); //returns 63 float modtest2 = mo
float testvalf = -126;
vec2 testval = vec2(-126, -126);
float modtest1 = mod(testvalf, 63.0); //returns 63
float modtest2 = mod(testval.x, 63.0); //returns 63
float modtest3 = mod(-126, 63.0); //returns 0
编辑:
下面是在IceCools建议之后进行的更多测试结果
int y = 63;
int inttestval = -126;
ivec2 intvectest(-126, -126);
float floattestval = -125.9;
float modtest4 = mod(inttestval, 63); //returns 63
float modtest5 = mod(intvectest, 63); //returns vec2(63.0, 63.0)
float modtest6 = mod(intvectest.x, 63); //returns 63
float modtest7 = mod(floor(floattestval), 63); //returns 63
float modtest8 = mod(inttestval, y); //returns 63
float modtest9 = mod(-126, y); //returns 63
我更新了我的驱动程序并再次测试,结果相同。在桌面上再次无法复制。
根据GLSL文档,可能的参数组合有(GenType,float)和(GenType,GenType)(没有双精度,因为我们小于4.0)。此外,返回类型被强制为浮点型,但这对于这个问题来说并不重要。我不知道如果您有意这么做,但是-126是一个int而不是浮点型,并且代码可能没有达到您的预期 顺便说一下,关于模: 请注意,调用了两个不同的函数: 前两行:
float mod(float, float);
最后一行:
int mod(int, float);
如果我是对的,mod的计算如下:
genType mod(genType x, float y){
return x - y*floor(x/y);
}
现在请注意,如果x/y的计算结果为-2.0,它将返回0,但是如果它的计算结果为-2.00000001,那么将返回63.0。int/float和float/float除法之间的差异并非不可能
因此,原因可能是您正在混合使用int和float 我想我已经找到了答案
我有一个错误是,GoType的关键字并不意味着泛型类型,比如C++模板。
GenType是float、vec2、vec3和vec4的缩写(请参见-ctrl+f GenType) 顺便说一句,genType命名类似于:genType - floats
genDType - doubles
genIType - ints
genBType - bools
这意味着genType mod(genType,float)
意味着没有类似int mod(int,float)
的函数
上面所有的代码都调用了float mod(float,float)
(幸亏函数参数有隐式类型转换,所以mod(int,int)
也可以工作,但实际上调用了mod(float,float)
)
作为证明:
int x = mod(-126, 63);
Doesn't compile: error C7011: implicit cast from "float" to "int"
它之所以不工作,是因为它返回float,所以它的工作原理如下:
float x = mod(-126, 63);
因此,调用float mod(float,float)
因此,我们回到了最初的问题:
- 浮点除法不准确
- 浮点转换的int不准确
- 这在大多数GPU上不应该是个问题,因为如果浮点数之间的差值小于10^-5,则浮点数被认为是相等的(这可能因硬件而异,但我的GPU就是这种情况)。所以下限(-2.0000001)是-2。Highp浮动远比这精确李>
- 因此,要么您没有使用highp浮点(
应该修复它),要么您的GPU对浮点相等性有更严格的限制,或者某些函数返回的值不太准确precision highp float;
- 如果所有其他方法都失败,请尝试:
#扩展黑魔法:启用
precision mediump float;
float x = 0.4121551, y = 0.4121552;
x == y; // true
0.4121551 == 0.4121552; // false, as highp they still differ.
因此,mod(-126,63.0)
仍然可以足够精确地返回正确的值,因为它使用高精度浮点运算,但是如果您给定一个变量(与所有其他情况一样),该变量将仅为mediump,则函数将没有足够的精度来计算正确的值,当您查看您的测试时,发生了以下情况:
- 所有至少包含一个变量的函数都不够精确
- 唯一使用2个键入数字的函数调用返回正确的值
!(abs(mod(x,y))>=abs(y))
应始终为真。打破,打破了什么模是图形程序。(奇怪的是!…>=对于NaN值也是如此)。非常好的信息,我回家后会研究gpu的浮点精度。如果有相关信息,甚至可以联系AMD的支持服务。但即使精度是答案,这仍然不能解释为什么得到63 für mod(变量,63.0)和0表示mod(-126,63.0)。