【发布时间】:2016-05-13 19:06:40
【问题描述】:
我正在使用取自this tutorial 的以下代码在 WebGL 的片段着色器中对浮点纹理执行线性过滤:
float fHeight = 512.0;
float fWidth = 1024.0;
float texelSizeX = 1.0/fWidth;
float texelSizeY = 1.0/fHeight;
float tex2DBiLinear( sampler2D textureSampler_i, vec2 texCoord_i )
{
float p0q0 = texture2D(textureSampler_i, texCoord_i)[0];
float p1q0 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX, 0))[0];
float p0q1 = texture2D(textureSampler_i, texCoord_i + vec2(0, texelSizeY))[0];
float p1q1 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX , texelSizeY))[0];
float a = fract( texCoord_i.x * fWidth ); // Get Interpolation factor for X direction.
// Fraction near to valid data.
float pInterp_q0 = mix( p0q0, p1q0, a ); // Interpolates top row in X direction.
float pInterp_q1 = mix( p0q1, p1q1, a ); // Interpolates bottom row in X direction.
float b = fract( texCoord_i.y * fHeight );// Get Interpolation factor for Y direction.
return mix( pInterp_q0, pInterp_q1, b ); // Interpolate in Y direction.
}
在 Nvidia GPU 上看起来不错,但在其他两台配备 Intel 集成 GPU 的计算机上看起来像这样:
出现了不应该出现的较亮或较暗的线条。如果您放大它们,它们就会变得可见,并且随着您放大的次数越来越多,它们往往会变得更频繁。当非常接近放大时,它们会出现在我正在过滤的纹理的每个纹素的边缘。我尝试在片段着色器中更改精度语句,但这并没有解决它。
内置线性过滤适用于两个 GPU,但对于不支持使用 WebGL 对浮点纹理进行线性过滤的 GPU,我仍然需要手动过滤作为备用。
英特尔 GPU 来自台式机 Core i5-4460 和配备英特尔 HD 5500 GPU 的笔记本电脑。对于浮点值的所有精度,我从getShaderPrecisionFormat 得到 rangeMin 和 rangeMax 为 127,精度为 23。
对导致这些伪影的原因以及如何解决这些问题有任何想法吗?
编辑:
通过更多试验,我发现减少片段着色器中的纹素大小变量可以消除这些伪影:
float texelSizeX = 1.0/fWidth*0.998;
float texelSizeY = 1.0/fHeight*0.998;
乘以 0.999 是不够的,但是将纹素大小乘以 0.998 可以消除伪影。
这显然不是一个令人满意的修复,我仍然不知道是什么原因造成的,我现在可能在其他 GPU 或驱动程序上造成了伪影。所以我仍然有兴趣弄清楚这里的实际问题是什么。
【问题讨论】:
-
"我尝试在片段着色器中更改精度语句,但这并没有解决问题。" 如果您降低精度会发生什么NVIDIA 版本的?
-
@NicolBolas 我将不得不重新检查,但我认为它看起来仍然很好并且没有造成任何伪影。但我也不确定精度声明是否真的会导致 NVIDIA GPU 上的精度降低。
-
另外,你能添加几个不同分辨率的英特尔版本吗?哦,还有一件事:你能验证这些线条的颜色是否总是相同的吗?
-
@NicolBolas 我添加了更多图像,颜色不一样。但是我现在也找到了一种解决方法,可以删除这些线条,尽管我仍然不明白这个问题。
标签: opengl-es glsl webgl fragment-shader