必要なのは別の種類の補間です (二次補間になると思います)。この場合 (空間のエッジの長さはテクスチャのエッジの長さと一致しません)、線形補間はそれをカットしません。
残念ながら、OpenGL で行うのはかなり複雑なタスクです (ただし、ソフトウェアのラスタライズを使用すると非常に簡単です)。画面空間の任意の四角形をテクスチャ空間の単位正方形に変換しようとしています。ここで問題の完全な解決策を見つけることができます: http://alumni.media.mit.edu/~cwren/interpolator/これにより、正しいテクスチャ座標を取得するためにスクリーンスペース座標を乗算する必要があるマトリックスが得られます (フラグメントシェーダーで) )。
それにはかなり厄介な数学が含まれているため、単純な静的ケースで実際に機能する単純なソリューションを提案します(手動で調整する必要があります)。頂点シェーダーで計算されたテクスチャ座標は、実際には中央のエッジでのみオフになっており、残りは正しいです。texcoords が (0, 0)、(1, 0)、(1, 1)、(0, 1) であると仮定すると、補正係数は次のようになります。
u * v // for the first triangle
(1 - u) * (1 - v) // for the second triangle
補正ベクトルを推定してから、すべてをまとめる必要があります。シンプルな C++ OpenGL アプリを使用してテストしました。次のように描画します。
Vector2f ta(0, 1), tb(1, 1), tc(1, 0), td(0, 0);
Vector2f a(-.1f, 1), b(1, .7f), c(1, .1f), d(0, 0);
// quad texcoords and vertices
Vector2f t_corr(-.01f, .5f);
// correction for the above quad
glBegin(GL_TRIANGLES);
glMultiTexCoord2f(GL_TEXTURE1, 1, -1); // first triangle
glTexCoord4f(ta.x, ta.y, t_corr.x, t_corr.y);
glVertex2f(a.x, a.y);
glTexCoord4f(tb.x, tb.y, t_corr.x, t_corr.y);
glVertex2f(b.x, b.y);
glTexCoord4f(tc.x, tc.y, t_corr.x, t_corr.y);
glVertex2f(c.x, c.y);
glMultiTexCoord2f(GL_TEXTURE1, 0, 1); // second triangle
glTexCoord4f(ta.x, ta.y, t_corr.x, t_corr.y);
glVertex2f(a.x, a.y);
glTexCoord4f(tc.x, tc.y, t_corr.x, t_corr.y);
glVertex2f(c.x, c.y);
glTexCoord4f(td.x, td.y, t_corr.x, t_corr.y);
glVertex2f(d.x, d.y);
glEnd();
頂点シェーダーは次のようになります。
void main()
{
gl_Position = ftransform();
gl_FrontColor = gl_Color;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1] = gl_MultiTexCoord1; // just copy coords, nothing else to do
}
フラグメント シェーダー:
uniform sampler2D sam;
void main()
{
vec2 corr = vec2(gl_TexCoord[1].x + gl_TexCoord[1].y * gl_TexCoord[0].x,
gl_TexCoord[1].x + gl_TexCoord[1].y * gl_TexCoord[0].y);
gl_FragColor = texture2D(sam, gl_TexCoord[0].xy + gl_TexCoord[0].zw * corr.x * corr.y);
}
これは非常に単純ですが、修正ベクトルを適切に調整することで、これを次のようにすることができます: http://www.luki.webzdarma.cz/up/deskew.png
もう 1 つのオプションは、3D の実際のクワッドでこれを行い、2D クワッドのように見える位置まで手動で回転させることです。または、クワッドの「深さ」テクスチャ座標を考案し、頂点シェーダーで 1/深さを計算し、補間 (u/深さ、v/深さ、1/深さ) し、後でフラグメント シェーダーで補間された 1/深さで割り、適切な値を取得します。 . これは単純に思えるかもしれませんが、適切な深さの値を見つけるのは非常に難しいことに注意してください。