【问题标题】:Fragment shaders on ATI cards versus NVIDIA onesATI 卡与 NVIDIA 卡上的片段着色器
【发布时间】:2011-06-29 17:50:01
【问题描述】:

我使用这个 Fragent 着色器(灵感来自前段时间在 NVIDIA 网站上找到的一些教程)。它基本上计算 2D 纹理的双线性插值。

uniform sampler2D myTexture;
uniform vec2 textureDimension;

#define texel_size_x 1.0 / textureDimension[0]
#define texel_size_y 1.0 / textureDimension[1]

vec4 texture2D_bilinear( sampler2D texture, vec2 uv)
{
    vec2 f;
    uv = uv + vec2( - texel_size_x / 2.0, - texel_size_y / 2.0);

    f.x = fract( uv.x * textureDimension[0]);
    f.y = fract( uv.y * textureDimension[1]);

    vec4 t00 = texture2D( texture, vec2(uv));
    vec4 t10 = texture2D( texture, vec2(uv) + vec2( texel_size_x, 0));
    vec4 tA = mix( t00, t10, f.x);

    vec4 t01 = texture2D( texture, vec2(uv) + vec2( 0, texel_size_y));
    vec4 t11 = texture2D( texture, vec2(uv) + vec2( texel_size_x, texel_size_y));
    vec4 tB = mix( t01, t11, f.x);

    vec4 result = mix( tA, tB, f.y);
    return result;
}

它看起来非常简单和严格。我最近在几张 ATI 卡(最新驱动程序...)上对其进行了测试,结果如下:

(左:最近的邻居)(右:正在使用的分片)

如您所见,出现了一些水平和垂直线,重要的是要提到这些在视口坐标中和纹理坐标中都不是固定的。

我必须移植几个着色器以使它们在 ATI 卡上正常工作,看起来 NVIDIA 的实现对 不好宽松我写了一段时间的代码。但在这种情况下,我看不出我应该改变什么!

关于克服这个问题的 NVIDIA 和 ATI GLSL 实现之间的差异,我应该知道什么?

【问题讨论】:

  • 你能重现 Mesa 的问题吗?
  • @genpfault 我忘了说目标操作系统是 windows 7/Vista/XP ... mesa 驱动程序可用于这些吗?
  • 是的。仅限软件,但就是这样。
  • 差异?是的,nVidia 的 OpenGL 驱动程序可以工作,ATI 不能。

标签: c++ opengl nvidia shader ati


【解决方案1】:

nVidia 更宽容,例如 nVidia 让您错误地投射(即 float4 到 float)只会发出警告,ATI 不会(错误)。 使用 OpenGL 与使用 DirectX 有更大的区别,例如,我有一个非常复杂的顶点着色器(矩阵调色板蒙皮),即使没有丝毫警告,它也不能在 ATI 上工作(但在 nVidia 上)。

因此,如果您不想让着色器“无处不在”地工作,请获得 ATI 卡 :-)(或者更好的是,集成芯片组 ^^)。

【讨论】:

  • ps。您遇到的错误可能是在纹理查找(即使用 CLAMP 或 MIRROR)或再次溢出时如何处理纹理的问题,将所有查找添加到 float2(vec2)并乘以 0.25(即 div by 4) 而不是 mix() 函数。
  • @Valmond 如果我将所有时间除以 4,我想我会放弃这个双线性插值着色器的双线性部分 :) ...但我明白你的意思,我会尝试手动完成 mix 部分。
  • 我可能解释得不好,只需将 4 个纹理查找加在一起并除以 4(当您执行 4 个查找时,如果将它们加在一起,则需要除以 4)。这将执行双线性插值(并且没有 ovarflows)。
  • 如果不这样做,您可能需要删除 'fract()' 调用(只需立即使用该值(即 X 而不是 fract(X) ),并结合 CLAMP .
  • @Valmond:将四个纹素相加并除以四将在纹理的该区域产生一个常量值。它不会是任何类型的插值。
【解决方案2】:

据我所知,您没有在对纹理进行采样之前量化纹理坐标。这很可能是这些线条出现的原因,因为您的输入纹理坐标恰好位于那里的纹素之间的边界上。所以你需要先将uv 量化为纹素中心。请记住,纹理坐标 0 和 1 不在纹素中心,而是定义了网格的边界,其中网格单元是纹素,纹素中心在 (texel_n + 0.5) / texture_dim,或者您使用 GLSL 函数 texelFetch 可用 GLSL 1.30及以后。

【讨论】:

  • 谢谢我移动了uv,偏移了-f*texel_size ... 没关系。我天真地希望glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 在整个单元格中应用文本颜色......我知道在网格边界(0 和 1)上可以做出一些选择,但它应该是确定性的,对吧?
猜你喜欢
  • 2014-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多