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。然而,只有当纹理从相机视图中投影出来时,这才是正确的。在这种情况下,我需要别的东西。我需要一个插值,该插值用于前一帧中的前向透视正确插值和当前帧中的后向透视正确插值。

该图说明了三种不同的情况: 在此处输入图像描述

-案例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 值。

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 矩阵,它执行从剪辑到屏幕空间所需的缩放和平移。这就是你的规模0.5和添加1.0正在做的事情。在这里,它是矩阵形式;通常,您只需将“previousMVP”与此进行左乘,因此这将是一个单一的矩阵乘法。

在您的片段着色器中,您需要进行投影纹理查找。我不记得 GLSL 1.20 的功能,但我知道1.30+ 的功能:

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

正是这个函数将执行必要的 W 除法步骤。

于 2012-04-05T09:53:48.080 回答