我渲染动画几何。在每一帧中,我想使用前一帧的屏幕空间纹理对几何图形进行纹理映射(像在前一帧中一样投影到几何图形上)。所以结果应该是这样的,如果屏幕空间纹理在一帧前被投影到几何体上,然后通过几何体动画转换到当前帧。
计算每个顶点的正确纹理坐标并不困难。在 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。然而,只有当纹理从相机视图中投影出来时,这才是正确的。在这种情况下,我需要别的东西。我需要一个插值,该插值用于前一帧中的前向透视正确插值和当前帧中的后向透视正确插值。
该图说明了三种不同的情况:
-案例A很简单。在这里,我可以保留纹理坐标的正常透视校正插值(由光栅化器默认执行)。
- 但是,在案例 B 中,我需要纹理坐标的线性插值以获得正确的结果(通过在 vertexShader 中与 vPos.w 相乘并在片段着色器中除以 vPos.w。或者在较新的 GLSL 版本中使用“noperspective”插值限定符)。
- 如果 CI 需要透视校正插值,但根据 oldPos.w 值。所以我必须通过将 u' 与顶点中的 currentPos.w 相乘并将插值除以 currentPos.w 来线性化 u'=(u/oldPos.w) 和 v'=(v/oldPos.w) 的插值分段。我还需要以相同的方式线性插值 w'=(1/oldPos.w) ,然后通过将插值的 u' 除以插值的 w' 来计算片段中的最终 u'' (对于 v'' 分别相同) )。
所以 - 现在的问题是,在这两种情况下产生正确结果的正确数学是什么?
同样,为顶点计算正确的 uv 不是问题。这是关于在三角形上实现正确的插值。
//可能相关:在同一通道中,我还想使用非投影、透视校正纹理对对象进行一些常规纹理处理。这意味着我不能更改 gl_Position.w 值。