首页 文章

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

提问于
浏览
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进行划分 . 但是,只有从摄像机视图投射纹理时,这才是正确的 . 在这种情况下,我需要别的东西 . 我需要一个插值,该插值属性用于前一帧中的前向透视校正插值和当前帧中的后向透视校正插值 .

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

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

-in Case 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 回答

  • 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 正在做的事情 . 这里,'s in matrix form; normally, you' d只是左 - 乘"previousMVP"这样,所以它都是单个矩阵乘法 .

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

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

    正是这个功能将进行必要的W分步 .

相关问题