投影矩阵推导

转:http://blog.csdn.net/gggg_ggg/article/details/45969499
透视投影利用w不为1对向量缩放
投影矩阵将物体物体投影到规范视域体(vvp)中
一般规范视域体是:x[-1,1](左到右),y[-1,1](下到上),z[0,1](近到远)
opengl范视视域体 x[-1,1](左到右),y[-1,1](下到上),z[-1,1](近到远),即左手坐标系
ortho
//-------------------------------------------------------------------------------
xn [-1,1];
x [l,r]; 
=>线性代数 
=> (xn-(-1)/(1-(-1)) = (x-l)/(r-l)
=>yn,zn同理
=>
xn=2*x/(r-l)-(r+l)/(r-l)
yn=2*y/(t-b)-(t+b)/(t-b)
zn=2*z/(f-n)-(f+n)/(f-n)
=>行矩阵
=>const mat4 result = mat4(
vec4(2.0f/(r-l), 0.0f, 0.0f, 0.0f),
vec4(0.0f, 2.0f/(t-b), 0.0f, 0.0f),
vec4(0.0f, 0.0f, 2.0f/(f-n), 0.0f),
vec4(-(r+l)/(r-l), -(t+b)/(t-b), -(f+n)/(f-n), 1.0f));
//------------------------------------------------------------------------------- 


frustum 
//-------------------------------------------------------------------------------
由比例3角形得
=>
x = x * (n/z)
y = y * (n/z)
根据ortho求法带入x,y
=>
xn=2(x*n/z)/(r-l)-(r+l)/(r-l)
yn=2(y*n/z)/(t-b)-(t+b)/(t-b)
=>zn的求法:(zn主要是为了深度测试才保留)
深度值为depth[0,1]
如果像ortho那样线性的
//左手坐标系z==========================================================
=>(zn-(-1)/(1-(-1)) = (z-n)/(f-n)
=>depth = (zn-(-1)/(1-(-1)) = (z-n)/(f-n)
然而,在实践中是几乎从来不使用这样的线性深度缓冲区。
正确的投影特性的非线性深度方程是和1/z成正比的 。
这样基本上做的是在z很近是的高精度和 z 很远的时候的低精度。
用几秒钟想一想: 我们真的需要让1000单位远的物体和只有1单位远的物体的深度值有相同的精度吗?线性方程没有考虑这一点。
=>depth = (zn-(-1)/(1-(-1)) = (1/z-1/n)/(1/f-1/n)
=>depth = (zn-(-1)/(1-(-1)) = (f/z) * (z-n)/(f-n):结果depth随zn变化是个曲线,随着zn增加,depth增加的越来越小
=>zn = (f+n)/(f-n) - (1/z)*(2*n*f/(f-n))
=>行矩阵
=>result = mat4(
vec4(2.0f*n/(r-l), 0.0f, 0.0f, 0.0f),
vec4(0.0f, 2.0f*n/(t-b), 0.0f, 0.0f),
vec4(-(r+l)/(r-l), -(t+b)/(t-b), (f+n)/(f-n), 1.0f),
vec4(0.0f, 0.0f, -2.0f*f*n/(f-n), 0.0f));

猜你喜欢

转载自blog.csdn.net/u010400998/article/details/80676154