我编写了以下着色器来测试线性过滤在OpenGL中的工作原理。
这里我们有一个5x1纹理喷溅到立方体的一个面上(megenta区域只是背景的颜色)。
纹理是这个(它非常小)。
botton-left 一角对应<?php
class newelement extends WPBakeryShortCode {
# Construct ----------------
function __construct() {
add_action( 'init', [ $this, 'elementMapping' ] );
add_shortcode( 'element_Shortcode', [ $this, 'elementShortcode' ] );
add_action( 'wp_enqueue_scripts', [ $this, 'elementCss' ]);
}
# Fields -------------------
public function elementMapping() {
if ( !defined( 'WPB_VC_VERSION' ) ) {
return;
}
vc_map(
[
"base" => "elementShortcode",
"params" => [
[
"type" => "colorpicker",
"param_name" => "elementcolor"
],
],
]
);
}
# Output Code ---------------------------------
public function elementShortcode () {
$atts = shortcode_atts([
"elementcolor" => "",
], $atts);
extract($atts);
ob_start();
?>
<?php
$output = ob_get_contents();
ob_end_clean();
return $output;
}
# css ---------------------------------
public function elementCss() {
// this value $elementcolor = $atts["elementcolor"];
$css = "
.element{ color: {$elementcolor} ;}
";
wp_add_inline_style( 'main', $css);
}
}
new newelement();
,右上角对应uv=(0, 0)
。
启用线性过滤。
着色器将uv=(1, 1)
坐标垂直分成5行(从上到下):
问题是在v
和3
之间有一行像素闪烁。通过改变相机距离来改变闪烁,有时你甚至可以让它消失。问题似乎在处理第四行的着色器代码中。
4
这对我来说很奇怪,因为在该区域中// sample at the left of the pixel
// the following line can fix the problem if I add any number different from 0
tc.y += 0.000000; // replace by any number other than 0 and works fine
tc.x = floor(5 * tc.x) * 0.2;
c = texture(tex0, tc);
坐标不在纹理的任何边缘附近。
答案 0 :(得分:4)
在纹理提取过程中,您的代码依赖于未定义值。
第8.9节纹理函数中的here状态(强调我的):
某些纹理函数(非“Lod”和非“Grad”版本)可能需要 隐含衍生物。 内隐衍生物未定义 非均匀控制流和非片段着色器纹理提取。
虽然大多数人认为这些衍生物只是mip-mapping所必需的,但这是不正确的。还需要LOD因子来确定纹理是放大还是缩小(以及非mipmapped情况下的各向异性过滤,但这里不感兴趣)。
GPU通常通过2x2像素四边形中的相邻像素之间的有限差分来近似导数。 发生的事情是,在各种选项之间的边缘处,您有非均匀的控制流,其中对于一行您进行纹理过滤,而在上面的行中,您没有这样做。有限差分将导致尝试访问上行中纹理采样操作的纹理坐标,这些操作根本无法保证计算,因为该着色器调用没有主动执行该代码路径 - 这就是为什么spec将它们视为未定义。
现在取决于您的边缘位于2x2像素四边形中的哪个位置,您可以得到正确的结果,或者您没有。对于没有得到正确结果的情况,一个可能的结果可能是GL在您的示例中使用了GL_NEAREST
的缩小过滤器。
将两个过滤器设置为GL_LINEAR
可能会有所帮助。但是,这仍然不是正确的代码,因为根据规范,结果仍未定义。
唯一正确的解决方案是将纹理采样移出非均匀控制流程,如
vec4 c1=texture(tex, tc); // sample directly at tc
vec4 c2=texture(tex, some_function_of(tc)); // sample somewhere else
vec4 c3=texture(tex, ...);
// select output color in some non-uniform way
if (foo) {
c=c1;
} else if (bar) {
c=c2;
} else {
c=c3;
}