纹理投影+透视校正,使数学正确

时间:2012-04-05 09:33:55

标签: math opengl graphics glsl textures

我渲染动画几何体。在每个帧中,我想使用前一帧中的屏幕空间纹理对几何进行纹理贴图(投影到几何图形中,就像在前一帧中一样)。所以结果应该是这样,如果屏幕空间纹理在一帧前投影到几何体上,然后由几何体动画转换为当前帧。

计算每个顶点的正确纹理坐标并不困难。在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进行划分。但是,只有从摄像机视图投射纹理时,这才是正确的。在这种情况下,我需要别的东西。我需要一个插值,用于前一帧中的前向透视校正插值和当前帧中的后向透视校正插值。

此图说明了三种不同的情况: enter image description here

-Case A很简单。在这里,我可以保留纹理坐标的正常透视校正插值(由光栅化器默认执行)。

然而,在案例B中,我需要纹理坐标的线性插值以获得正确的结果(通过乘以vertexShader中的vPos.w并在片段着色器中除以vPos.w。或者在较新的GLSL版本中使用“noperspective”插值限定符)。

- 在案例C中,我需要透视校正插值,但根据oldPos.w值。所以我必须通过将u'与顶点中的currentPos.w相乘并将插值除以currentPos.w来线性化u'=(u / oldPos.w)和v'=(v / oldPos.w)的插值。分段。我还需要以相同的方式线性插值w'=(1 / oldPos.w),然后通过将插值的u'除以插值的w'(并且对于v''分别相同)来计算片段中的最终u'' )。

所以 - 现在的问题是,在任何一种情况下,正确的结果是什么才是正确的数学?

再次,计算顶点的正确uv不是问题。它是关于在三角形上实现正确的插值。

//也许是相关的:在同一个传递中,我还想使用非投影,透视校正纹理对对象进行一些常规纹理处理。这意味着我不能改变gl_Position.w值。

1 个答案:

答案 0 :(得分: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功能,但我知道the 1.30+ function:

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

这个功能将执行必要的W分步。