我渲染动画几何体。在每个帧中,我想使用前一帧中的屏幕空间纹理对几何进行纹理贴图(投影到几何图形中,就像在前一帧中一样)。所以结果应该是这样,如果屏幕空间纹理在一帧前投影到几何体上,然后由几何体动画转换为当前帧。
计算每个顶点的正确纹理坐标并不困难。在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进行划分。但是,只有从摄像机视图投射纹理时,这才是正确的。在这种情况下,我需要别的东西。我需要一个插值,用于前一帧中的前向透视校正插值和当前帧中的后向透视校正插值。
此图说明了三种不同的情况:
-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值。
答案 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分步。