2

私はこの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の実装の違いについて知っておくべき一般的なことはありますか?

4

2 に答える 2

4

nVidiaはより寛容です。たとえば、nVidiaでは誤ってキャストできます(つまり、float4からfloatになります)が、警告になりますが、ATIは(エラー)しません。OpenGLを使用する場合はDirectXを使用する場合よりも大きな違いがあります。たとえば、非常に複雑な頂点シェーダー(マトリックスパレットスキニング)があり、わずかな警告がなくてもATIでは機能しませんでした(nVidiaでは機能しました)。

したがって、シェーダーを「どこでも」機能させたくない場合は、ATIカードを入手してください:-)(または、統合されたチップセット^^)。

于 2011-06-29T18:01:51.960 に答える
2

私が知る限り、テクスチャをサンプリングする前にテクスチャ座標を定量化していないことがわかります。入力テクスチャ座標がテクセル間の境界に正確に位置するようになるため、これがこれらの線が表示される理由である可能性があります。uvしたがって、最初にテクセル中心に量子化する必要があります。テクスチャ座標0と1はテクセルの中心ではなく、グリッドの境界を定義することに注意してください。グリッドセルはテクセルであり、テクセルの中心はに(texel_n + 0.5) / texture_dimあります。または、GLSL1.30以降で使用可能なGLSL関数を使用しtexelFetchます。

于 2011-06-29T21:35:11.207 に答える