Perspective Correct Interpolation
线性插值的问题
OpenGL在进行光栅化时,对于每个fragment shader的input attribute作插值,这个插值默认情况下perspective correct的。插值默认是screen space进行的,如果使用简单的线性插值,对于texture mapping会得到错误的结果,来看下图(图片取自《Graphics Shaders 2nd》)。
可以明显地看到采用线性插值的quad中两个triangles的边界。
Perspective Correct Interpolation的简单推导
OpenGL 4.5 spec 14.6 p456中给出地插值公式如下
其中为fragment对应的重心坐标,为顶点处地attribute,为顶点齐次坐标地最后一个分量。
为了简化讨论,我们这里在2D中进行讨论,结论对3D同样有效。
考虑上图中的线段AB,投影后的线段为A’B’,其中A’B’的中心。我们可以容易地发现,A’B’中心并不对应AB中心,所以直接使用对AB属性进行线性插值会得到错误的结果。容易想到,如果我们通过screen space的插值系数,得到camera space的插值系数,那么就可以得到perspective correct的interpolation。
假设screen space的点P的插值系数为,A为,B为,near plane (不影响结果,为1可以简化讨论),可知
计算与的交点,我们可以得到camera space的插值系数为为
若我们在A处属性为,B处属性为,那么使用进行插值,结果为
如果使用标准透视矩阵,那么中的,我们可以看出公式与是一致的。
公式可以进一步表示为线性插值
gl_Position
也许有人会有疑问,我们能不能在vertex shader中进行透视除呢?即对于齐次坐标,手动进行透视除,得到并赋值给gl_Position。我们可以将代入,得到
显然这退化成为了screen space的线性插值,所以必然最后结果是不正确的。在Unity中作一个简单的实验就可以看到结果
上图是未进行透视除的结果,下图是进行透视除的结果。
测试代码如下
Shader "Unlit/VertexColor"
{
Properties
{
_MainTex ("Main Texture", 2D) = "white" {}
[Toggle] _ManualPerspectiveDivision ("Manual Perspective Division", Float) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
GLSLPROGRAM
#include "UnityCG.glslinc"
#ifdef VERTEX
uniform int _ManualPerspectiveDivision;
out vec2 vST;
void main()
{
vST = gl_MultiTexCoord0.st;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
if (_ManualPerspectiveDivision != 0) {
gl_Position /= gl_Position.w;
}
}
#endif
#ifdef FRAGMENT
in vec2 vST;
uniform sampler2D _MainTex;
void main()
{
gl_FragColor = texture(_MainTex, vST);
}
#endif
ENDGLSL
}
}
}
结论
- 要进行perspective correct interpolation,不能直接在screen space利用重心坐标直接进行插值。
- 齐次坐标的对于进行perspective correct interpolation至关重要,不能在vertex shader中手动进行透视除。
上一篇: react路由router
下一篇: Override和Overload
推荐阅读
-
3D变形 CSS3 transform---rotateX(), rotateY(), rotateZ(), 透视(perspective)
-
perspective属性简介
-
sourcetree pull时出错Please make sure you have the correct access rights and the repository exists
-
详解CSS3的perspective属性设置3D变换距离的方法
-
css深入剖析transform的translate和perspective
-
CSS3景深-perspective
-
libA : Depends: libB but it is not going to be installed E: Unable to correct problems
-
实例讲解CSS3中Transform的perspective属性的用法
-
Disable auto-correct in oh-my-zsh
-
Opencv学习笔记 透视变换(perspective transform)