Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl textureGather()在texel中心坐标处的行为_Opengl_Glsl - Fatal编程技术网

Opengl textureGather()在texel中心坐标处的行为

Opengl textureGather()在texel中心坐标处的行为,opengl,glsl,Opengl,Glsl,假设我有一个100x100纹理,我执行以下操作: vec4 texelQuad = textureGather(sampler, vec2(50.5)/vec2(100.0)); ivec2 lowerBoundTexelCoord = ivec2(floor(textureCoord * textureSize - 0.5)); 我要求的坐标正好在texel(50,50)的中心。那么,我会得到一个以(49,49)和(50,50)为界的四元texel,还是以(50,50)和(51,51)为界

假设我有一个100x100纹理,我执行以下操作:

vec4 texelQuad = textureGather(sampler, vec2(50.5)/vec2(100.0));
ivec2 lowerBoundTexelCoord = ivec2(floor(textureCoord * textureSize - 0.5));
我要求的坐标正好在texel(50,50)的中心。那么,我会得到一个以(49,49)和(50,50)为界的四元texel,还是以(50,50)和(51,51)为界的四元texel。规范在这个问题上含糊其辞。它只说了以下几点:

vec4 texelQuad = textureGather(sampler, vec2(50.5)/vec2(100.0));
ivec2 lowerBoundTexelCoord = ivec2(floor(textureCoord * textureSize - 0.5));
线性缩小滤波器的规则应用于 识别四个选定的纹理

相关章节
8.14.2坐标包装和纹理选择
也不是非常清楚。我最好的假设是:

vec4 texelQuad = textureGather(sampler, vec2(50.5)/vec2(100.0));
ivec2 lowerBoundTexelCoord = ivec2(floor(textureCoord * textureSize - 0.5));
这个假设在实践中成立吗?不,没有。事实上,其他假设也不成立,因为不同的硬件在这种特定情况下会返回不同的结果:

textureSize:           100x100
textureCoord:          vec2(50.5)/vec2(100.0)
Hyphotesis:            (49, 49) to (50, 50)
GeForce 1050 Ti:       (49, 49) to (50, 50)
Intel HD Graphics 630: (50, 50) to (51, 51) 
另一种情况:

textureSize:           100x100
textureCoord:          vec2(49.5)/vec2(100.0)
Hyphotesis:            (48, 48) to (49, 49)
GeForce 1050 Ti:       (49, 49) to (50, 50)
Intel HD Graphics 630: (48, 48) to (49, 49) 
由于texel中心坐标的不可预测行为,这是否会使textureGather()变得无用?一点也不!。虽然在某些特定情况下,您可能无法预测它将返回哪4个texel,但您仍然可以通过给它指定所需的4个texel之间的坐标,强制它返回所需的4个texel。也就是说,如果我想要以(49,49)和(50,50)为边界的texel,我会调用:

textureGather(sampler, vec2(50.0, 50.0)/textureSize);
由于我这次请求的坐标是4个texel相交的点,任何实现都肯定会返回这4个texel

现在,问题是:我的分析正确吗?是否每个使用textureGather()的人都会强迫它返回一个特定的Texel四元组,而不是计算它将自己返回哪些Texel?如果是这样的话,很遗憾没有在任何文档中反映出来

编辑

有人指出,OpenGL不能保证在不同的硬件上分割相同的浮点数得到相同的结果。因此,有必要提到,在我的实际代码中,我使用了
vec2(50.5)/vec2(textureSize(sampler,0))
而不是
vec2(50.5)/vec2(100.0)
。这很重要,因为
textureSize()
的存在会阻止在着色器编译时执行该分割

我还要重新表述一下这个问题:

假设你从一个黑盒子得到了一个标准化的纹理坐标。然后将该坐标传递给textureGather():

任何人都可以生成GLSL代码来返回texelQuad[3]中返回的texel坐标的整数对,这是2x2框的下限角?以下显而易见的解决方案并非在所有情况下都有效:

vec2 textureDims = textureSize(sampler, 0);    
ivec2 lowerBoundTexelCoord = ivec2(floor(textureCoord * textureDims - 0.5));
上述方法可能失败的棘手案例包括:

vec2 textureCoord = vec2(49.5)/vec2(textureSize(sampler, 0)); 
vec2 textureCoord = vec2(50.5)/vec2(textureSize(sampler, 0));

其中
textureSize(sampler,0)
返回
ivec2(100100)
回想一下
GL\u LINEAR
([OpenGL 4.6(核心)§8.14纹理缩小])的纹理位置是通过以下公式选择的:

i0=包裹(⌊u′-1/2⌋)

j0=包裹(⌊v′-1/2⌋)

在这种情况下,(u′,v′)的值等于

(vec2(50.5) / vec2(100)) * vec2(100)
但是,请注意,这不能保证等于
vec2(50.5)
。请参阅:

a/b,1.0/b:2.5 ULP,适用于[2-1262126]范围内的b

因此,u′的值可能略大于50.5,略小于50.5,或者可能正好是50.5。没有承诺!规范承诺不超过2.5 ULP,但这没什么好写的。你可以看到,当你减去0.5并开始发言时,你会得到49或50,这取决于数字是多少迪德

i0=包裹(⌊(50.5 / 100) * 100 - 1/2⌋)

i0=包裹(⌊(.505±误差)*100-1/2⌋)

i0=包裹(⌊50.5±误差-1/2⌋)

i0=包裹(⌊50±误差⌋)

i0=50(如果误差>=0)或49(如果误差<0)

因此,事实上,不可预测的不是
textureGather()
。不可预测的部分是尝试除以100时的舍入误差,这在GLSL规范和经典文章中有解释

或者换句话说,
textureGather()
总是给你相同的结果,但是
50.5/100.0
没有


请注意,如果纹理是二的幂,则可以得到准确的结果,因为可以使用
50.5*0.0078125
计算
50.5/128
,结果将完全正确,因为乘法正确舍入,0.0078125是二的幂。

舍入错误,因为
vec2(50.5)/vec2(100.0)
不准确。请看:@DietrichEpp这真的离题了。你看,我不在乎在模棱两可的情况下返回哪些texel,只要我能预测它们将返回哪些texel。不幸的是,这似乎不可能预测。但
textureGather
没有问题,问题是你正在传递一个在不同的平台上对
textureGather
使用不同的值,并期望在这些不同的平台上得到相同的结果。或者使用两个纹理的幂,或者使用
floor()计算得到的纹理数
。好吧,我不知道OpenGL不能保证在不同的硬件上分割相同的数字会得到相同的结果。但是,这还不是重点。假设你从一个黑盒子中得到了一个标准化的纹理坐标。
vec2(50.5)/vec2(100.0)的分割
就是这样一个黑匣子。事实上,在我的实际代码中,它是
vec2(50.5)/vec2(textureSize(…)
,这突然之间是一个重要的区别。现在,将坐标从黑匣子传递到textureGather()。你能生成一段代码来准确预测将要返回的texel吗?我不能。@Tulon:你能准确预测将要收集的texel,只要你能准确预测传递给
textureGather()
。这与
textureGather()的值无关
@Tulon:你为什么要准确地预测事情呢?如果你的代码依赖于浮点除法,那么你就需要一个exac