1

アニメーション ジオメトリをレンダリングします。各フレームで、前のフレームのスクリーン スペース テクスチャを使用してジオメトリをテクスチャ マップします (前のフレームと同じようにジオメトリに投影されます)。したがって、結果は、スクリーン スペース テクスチャが 1 フレーム前にジオメトリに投影され、ジオメトリ アニメーションによって現在のフレームに変換されたようなものになるはずです。

頂点ごとに適切なテクスチャ座標を計算することは難しくありません。GLSL では、次のようになります。

void main(void)
{
   vPos = currentMVP  * vec4(position,1);
   gl_Position = vPos;
   vec4 oldPos = previousMVP * vec4(position,1);
   vec2 UV = vec2(((oldPos.x/oldPos.w)+1)*0.5f, ((oldPos.y/oldPos.w)+1)*0.5f);
   ...
}

しかし、テクスチャ座標をジオメトリ上で正しく補間することは、私が思っているよりも難しいことです。通常、投影用のテクスチャ座標はスクリーン空間で直線的に補間する必要があります。そのため、これを実現するには、頂点シェーダーで vPos.w を乗算し、フラグメントシェーダーで vPos.w で再び除算します。ただし、これは、テクスチャがカメラビューから投影されている場合にのみ正しいです。この場合、私は何か他のものが必要です。前のフレームでの前方透視補正補間と現在のフレームでの後方透視補正補間に属性を持つ補間が必要です。

この図は、3 つの異なるケースを示しています。 ここに画像の説明を入力

- ケース A は単純です。ここでは、(ラスタライザーによってデフォルトで実行されるように) テクスチャ座標の通常のパースペクティブ補正補間をそのままにしておくことができます。

-ただし、ケース B では、適切な結果を得るためにテクスチャ座標の線形補間が必要になります (頂点シェーダーで vPos.w を乗算し、フラグメント シェーダーで vPos.w で除算するか、新しい GLSL バージョンでは「ノーパースペクティブ」を使用)。補間修飾子)。

-CI の場合、遠近法で修正された補間が必要になりますが、oldPos.w の値に従います。したがって、u'=(u/oldPos.w) と v'=(v/oldPos.w) の補間を線形化し、u' に頂点の currentPos.w を掛けて、補間された値を currentPos.w で割る必要があります。断片。また、同じ方法で w'=(1/oldPos.w) を線形補間し、補間された u' を補間された w' で割ってフラグメントの最終的な u'' を計算する必要があります (それぞれ v'' についても同じです)。 )。

では、問題は、どちらの場合でも正しい結果を導き出すための適切な数学は何かということです。

繰り返しますが、頂点の正しい UV を計算することは問題ではありません。それは、三角形に対して正しい補間を達成することです。

//関連する可能性があります: 同じパスで、非射影の遠近法で修正されたテクスチャリングを使用して、オブジェクトの通常のテクスチャリングも実行したいと考えています。これは、gl_Position.w の値を変更してはならないことを意味します。

4

1 に答える 1

2
vec2 UV = vec2(((oldPos.x/oldPos.w)+1)*0.5f, ((oldPos.y/oldPos.w)+1)*0.5f);

違う。Wが必要です。あなたはまだ分割したくない。あなたが欲しいのはこれです:

vec4 oldPos = previousMVP * vec4(position,1);
oldPos = clipToTexture * oldPos;
vec3 UV = oldPos.xyw;

マトリックスは、clipToScreenクリップからスクリーン スペースに移動するために必要なスケーリングと変換を行う 4x4 マトリックスです。それがあなたのscale of0.5とadding1.0が行っていたことです。ここでは、行列形式です。通常、これで「previousMVP」を左乗算するだけなので、すべて単一の行列乗算になります。

フラグメント シェーダーでは、射影テクスチャ ルックアップを行う必要があります。GLSL 1.20 関数は覚えていませんが、1.30 以降の関数は知っています。

vec4 color = textureProj(samplerName, UV.stp);

必要な W による除算ステップを実行するのはこの関数です。

于 2012-04-05T09:53:48.080 に答える