1

2D テクスチャ (非 2 乗) からサブ長方形を取得し、シェーダー (glSubImage などは使用しない) を使用して出力 2D テクスチャのコピー先サブ長方形にコピーする関数を作成する必要があります。また、送信元と送信先のサイズが異なる場合があるため、線形フィルタリング (またはミップマップ) を使用する必要があります。

void CopyToTex(GLuint dest_tex,GLuint src_tex,
               GLuint src_width,GLuint src_height,
               GLuint dest_width,GLuint dest_height,
               float srcRect[4],
               GLuint destRect[4]);

ここで、srcRect は正規化された 0-1 座標にあります。つまり、四角形 [0,1]x[0,1] が入力テクスチャのすべての境界ピクセルの中心に接触しています。

入力とソースのディメンションが一致しない場合に良い結果を得るには、GL_LINEARフィルタリングを使用したいと考えています。

この関数が一貫した方法で動作することを望みます。つまり、多くのサブレクトで複数回呼び出すと、サブレクトの結合で 1 回呼び出した場合と同じ結果が生成されます。つまり、線形サンプラーは入力ピクセルの正確な中心をサンプリングする必要があります。

さらに、入力長方形がコピー先の長方形に正確に適合する場合、正確なコピーが発生するはずです。これは特に難しいようです。

私が今持っているものは次のようなものです:

//Setup RTT, filtering and program

float vertices[4] = { 
      float(destRect[0]) / dest_width * 2.0 - 1.0,
      float(destRect[1]) / dest_height * 2.0 - 1.0, 
      //etc..
};

float texcoords[4] = {
      (srcRect[0] * (src_width - 1) + 0.5) / src_width - 0.5 / dest_width,
      (srcRect[1] * (src_height - 1) + 0.5) / src_height - 0.5 / dest_height,
      (srcRect[2] * (src_width - 1) + 0.5) / src_width + 0.5 / dest_width,
      (srcRect[3] * (src_height - 1) + 0.5) / src_height + 0.5 / dest_height,
};

glBegin(GL_QUADS);
glTexCoord2f(texcoords[0], texcoords[1]);
glVertex2f(vertices[0], vertices[1]);

glTexCoord2f(texcoords[2], texcoords[1]);
glVertex2f(vertices[2], vertices[1]);

//etc...
glEnd();

このコードを書くために、このページの情報に従いました。

これは、いくつかのまれなケース (正確なコピー、1 ピクセルの行または列のコピー) では意図したとおりに機能するようです。

私の最も困難なテスト ケースは、入力テクスチャと出力テクスチャの両方が 2xN よりも大きい場合に、2xN の長方形の正確なコピーを実行することです。

おそらく、オフセットとスケーリングに問題があります (単純なものは機能しません)。

4

1 に答える 1

0

解決:

0.5/tex_widthtexcoords の定義の一部が間違っていました。回避する簡単な方法は、その部分を完全に削除することです。

float texcoords[4] = {
      (srcRect[0] * (src_width - 1) + 0.5) / src_width,
      (srcRect[1] * (src_height - 1) + 0.5) / src_height,
      (srcRect[2] * (src_width - 1) + 0.5) / src_width,
      (srcRect[3] * (src_height - 1) + 0.5) / src_height
};

代わりに、次のように頂点をオフセットして、より小さなクワッドを描画します。

float dx = 1.0 / (dest_rect[2] - dest_rect[0]) - epsilon;
float dy = 1.0 / (dest_rect[3] - dest_rect[1]) - epsilon;

// assume glTexCoord for every vertex 
glVertex2f(vertices[0] + dx, vertices[1] + dy);
glVertex2f(vertices[2] - dx, vertices[1] + dy);
glVertex2f(vertices[2] - dx, vertices[3] - dy);
glVertex2f(vertices[0] + dx, vertices[3] - dy);

このようにして、すべての境界ピクセルの正確な中心から通過するクワッドを描画します。この場合、OpenGL は境界ピクセルを描画する場合と描画しない場合があるため、イプシロンが必要です。

元のソリューション (頂点座標をオフセットしない) は引き続き機能すると思いますが、texcoords の正しいオフセットを計算するには、少し余分な計算が必要です。

于 2013-08-23T15:45:34.290 に答える