首页 科技正文

allbet gmaing:[OpenGL](翻译+弥补)投影矩阵的推导

admin 科技 2020-06-06 42 0

1.简介

基本是翻译和弥补 http://www.songho.ca/opengl/gl_projectionmatrix.html

盘算机显示器是一个2D的平面,一个3D的场景要被OpenGL渲染必须被投影到2D平面上以天生2D的图像。在OpenGL中,GL_PROJECTION矩阵可以用来举行投影变换。首先,它将所有的极点数据从相机坐标系(eye coordinates)转换到裁剪坐标系(clip coordinates),然后通过除以裁剪空间坐标的w值,将裁剪空间坐标系转换到归一化装备坐标系(normalized device coordinates,NDC)

我们需要注重的一点就是,裁剪和NDC变换都通过GL_PROJECTION矩阵来完成。之后的文章,将会行使6个参数来构建投影矩阵,这六个参数是:left,right,bottom,top,near,far,分别为近裁剪面的左右下上界限,近裁剪面,远裁剪面。

视锥体剔除是在裁剪坐标下举行的,在转换到NDC坐标系之前。已经变换到裁剪坐标系的坐标\(x_c,y_c,z_c\)会和\(w_c\)举行对照,若是裁剪坐标大于\(w_c\)或小于\(-w_c\),则极点会被剔除,OpenGL会重修多边形的边。
ps.解释一下为什么要和\(w_c\)举行对照。由于NDC坐标的局限是\([-1,1]\),而裁剪坐标和NDC坐标之间的关系是\(x_c/w_c = x_n\),以是\(x_c\)必须得在\([-w_c,w_c]\)之间才可见,其他两个轴同理。不是在NDC坐标阶段举行裁剪,是由于不能见的极点,没有必要在对其举行运算,会消耗资源。在作用完投影矩阵后,获得的是齐次坐标,OpenGL会自动除以\(w_c\),以获得笛卡尔坐标,OpenGL应该是在除以\(w_c\)之前举行视锥体剔除事情。

2.透视投影

在透视投影中,1个3D的点在一个像被切了一刀的金字塔的视锥体中,此时的坐标系是相机坐标系,这个坐标系会被映射正方体的NDC坐标系中。

  • \(x:[l,r]->[-1,1]\)
  • \(y:[b,t]->[-1,1]\)
  • \(z:[-n,-f]->[-1,1]\)

相机坐标系界说在右手坐标系,NDC是左手坐标系,以是相机朝着-Z的偏向看去,而NDC朝着+Z的偏向看去。由于glFrustum()裁剪面的参数必须为正数,以是在建立投影矩阵的时刻,我们要对其举行去取反。
ps.glFrustum是opengl类库中的函数,它是将当前矩阵与一个透视矩阵相乘,把当前矩阵转变成透视矩阵,在使用它之前,通常会先挪用glMatrixMode(GL_PROJECTION).
void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearVal, GLdouble farVal),left,right指明相对于垂直平面的左右坐标位置,bottom,top指明相对于水平剪切面的下上位置,nearVal,farVal指明相对于深度剪切面的远近的距离,两个必须为正数。

在OpenGL中,1个3D的点将会被投影到近裁剪平面上,下图展示了点\((x_e,y_e,z_e)\)若何投影到\((x_p,y_p,z_p)\)

allbet gmaing:[OpenGL](翻译+弥补)投影矩阵的推导 第1张

在视锥体的顶视图,我们可以行使相似三角形盘算\(x_p\)的值

\[\frac{x_p}{x_e} = \frac{-n}{z_e}\\ x_p = \frac{-nx_e}{z_e}=\frac{nx_e}{-z_e} \]

同理,在侧视图中,行使相似三角形盘算\(y_p\)的值

\[\frac{y_p}{y_e} = \frac{-n}{z_e}\\ y_p = \frac{-ny_e}{z_e}=\frac{ny_e}{-z_e} \]

我们考察到\(x_p,y_p\)都依赖于\(z_e\),他们都除以\(z_e\),这是第一个线索,来辅助我们构建透视投影矩阵。当相机坐标系经由透视投影矩阵变换后,获得的是裁剪坐标系的齐次坐标,最后通过除以齐次坐标的\(w_c\),来获得NDC

\[\begin{bmatrix} x_c\\ y_c\\ z_c\\ w_c \end{bmatrix} =M_{projection} \begin{bmatrix} x_e\\ y_e\\ z_e\\ w_e \end{bmatrix} , \begin{bmatrix} x_n\\ y_n\\ z_n\\ \end{bmatrix} = \begin{bmatrix} x_c/w_c\\ y_c/w_c\\ z_c/w_c\\ \end{bmatrix} \]

因此我们可以设置\(w_c\)的值为\(-z_e\),现在投影矩阵看起来是

\[\begin{bmatrix} x_c\\ y_c\\ z_c\\ w_c \end{bmatrix} = \begin{bmatrix} .&.&.&.\\ .&.&.&.\\ .&.&.&.\\ 0&0&-1&0\\ \end{bmatrix} \begin{bmatrix} x_e\\ y_e\\ z_e\\ w_e \end{bmatrix} \]

接着,我们需要将\(x_p,y_p\)映射到\(x_n,y_n\)\([l,r]->[-1,1],[b,t]->[-1,1]\)
相当于是给定l,我要获得-1,给定r,我要获得1,这不就是给定二维平面上的两个点,求其直线方程的问题

\[令x_n = kx_p+\beta,求其斜率为\frac{1-(-1)}{r-l}=\frac{2}{r-l}\\ 带入点(r,1),1 = \frac{2r}{r-l}+\beta\\ 化简求得\beta=-\frac{r+l}{r-l}\\ 最终得x_n = \frac{2x_p}{r-l}-\frac{r+l}{r-l} \]

\[令y_n = ky_p+\beta,求其斜率为\frac{1-(-1)}{t-b}=\frac{2}{t-b}\\ 带入点(t,1),1 = \frac{2t}{t-b}+\beta\\ 化简求得\beta=-\frac{t+b}{t-b}\\ 最终得y_n = \frac{2y_p}{t-b}-\frac{t+b}{t-b} \]

现在有了从\(x_e,y_e\)\(x_p,y_p\)和从\(x_p,y_p\)\(x_n,y_n\),现在联立一下就可以获得从\(x_e,y_e\)\(x_n,y_n\)的关系表达式。

\[x_n = \frac{2x_p}{r-l}-\frac{r+l}{r-l}\\ x_p = \frac{-nx_e}{z_e}=\frac{nx_e}{-z_e}\\ 最终可以化简为(\underbrace{\frac{2n}{r-l}x_e+\frac{r+l}{r-l}z_e}_{x_c})/-z_e \]

同理

\[y_n = \frac{2y_p}{t-b}-\frac{t+b}{t-b}\\ y_p = \frac{-ny_e}{z_e}=\frac{ny_e}{-z_e}\\ 最终可以化简为(\underbrace{\frac{2n}{t-b}y_e+\frac{t+b}{t-b}z_e}_{y_c})/-z_e \]

现在我们的透视矩阵现在是这个样子

\[\begin{bmatrix} x_c\\ y_c\\ z_c\\ w_c \end{bmatrix} = \begin{bmatrix} \frac{2n}{r-l}&0&\frac{r+l}{r-l}&0\\ 0&\frac{2n}{t-b}&\frac{t+b}{t-b}&0\\ .&.&.&.\\ 0&0&-1&0\\ \end{bmatrix} \begin{bmatrix} x_e\\ y_e\\ z_e\\ w_e \end{bmatrix} \]

现在还剩下矩阵的第三行。\(z_n\)和其他两个轴的坐标稍有差别,由于\(z_e\)总是投影到-n的近裁剪面,然则我们需要差别的z值来举行裁剪和深度测试,另外我们应该可以举行逆操作(逆变换)。由于我们知道z的值不依赖于x,y,我们借用w的值来寻找\(z_n,z_e\)之间的关系,因此我们指定第三行矩阵为

\[\begin{bmatrix} x_c\\ y_c\\ z_c\\ w_c \end{bmatrix} = \begin{bmatrix} \frac{2n}{r-l}&0&\frac{r+l}{r-l}&0\\ 0&\frac{2n}{t-b}&\frac{t+b}{t-b}&0\\ 0&0&A&B\\ 0&0&-1&0\\ \end{bmatrix} \begin{bmatrix} x_e\\ y_e\\ z_e\\ w_e \end{bmatrix} \]

\[z_n = z_c/w_c = \frac{Az_e+Bw_e}{-z_e} \]

在相机坐标系中,\(w_e\)的值是1,因此有\(z_n = \frac{Az_e+B}{-z_e}\),为了获得A和B的值,我们使用\((z_e,z_n)\)的关系,\((-n,-1),(-f,1)\),然后将他们代入表达式。

\[\frac{-An+B}{n}=-1\\ \frac{-Af+B}{f}=1 \]

联立,这是一个简朴二元一次方程组,容易求得

\[A = -\frac{f+n}{f-n}\\ B = -\frac{2fn}{f-n} \]

以是最终获得

\[z_n = \frac{-\frac{f+n}{f-n}z_e--\frac{2fn}{f-n}}{-z_e} \]

最终整个投影矩阵的表达式为

\[\begin{bmatrix} x_c\\ y_c\\ z_c\\ w_c \end{bmatrix} = \begin{bmatrix} \frac{2n}{r-l}&0&\frac{r+l}{r-l}&0\\ 0&\frac{2n}{t-b}&\frac{t+b}{t-b}&0\\ 0&0&-\frac{f+n}{f-n}&-\frac{2fn}{f-n}\\ 0&0&-1&0\\ \end{bmatrix} \begin{bmatrix} x_e\\ y_e\\ z_e\\ w_e \end{bmatrix} \]

这个投影矩阵是一样平常的视锥体,若是是对称的话,有\(r=-l,t=-b\),那么有

\[r+l=0,r-l=2r(width)\\ t+b=0,t-b=2t(height) \]

最后矩阵可以简朴的化为

\[\begin{bmatrix} \frac{n}{r}&0&0&0\\ 0&\frac{n}{t}&0&0\\ 0&0&-\frac{f+n}{f-n}&-\frac{2fn}{f-n}\\ 0&0&-1&0\\ \end{bmatrix} \]

注重考察\(z_e,z_n\)的关系式,这是一个非线性的反比例函数,这意味着,在近裁剪平面的是很好,精度很高,而在远裁剪面的时刻,精度很低。当\([-n,-f]\)很大时,可能导致深度精度问题(z-fighting),一个较小的\(z_e\)的转变,在远裁剪面可能不会影响\(z_n\)的值,n和f之间的距离应该短一些,从而最小化这个问题。
ps.由于浮点数会存在精度问题,究竟盘算机的存储是离散的。

allbet gmaing:[OpenGL](翻译+弥补)投影矩阵的推导 第2张

3.正交投影

正交投影的要比透视投影简朴许多,\(x_e,y_e,z_e\)相机坐标系将会线性映射到NDC坐标系。我们仅需要将长方体变为正方体,然后移动至原点。

allbet gmaing:[OpenGL](翻译+弥补)投影矩阵的推导 第3张

\[x_n = \frac{1-(-1)}{r-l}x_e+\beta\\ 代入(r,1),最终可得\\ x_n = \frac{2}{r-l}x_e-\frac{r+l}{r-l} \]

同理

\[y_n = \frac{1-(-1)}{t-b}y_e+\beta\\ 代入(t,1),最终可得\\ y_n = \frac{2}{t-b}y_e-\frac{t+b}{t-b} \]

同理

\[z_n = \frac{1-(-1)}{-f-(-n)}z_e+\beta\\ 代入(-f,1),最终可得\\ z_n = \frac{-2}{f-n}z_e-\frac{f+n}{f-n} \]

由于w的值在正交投影中不必要,以是我们设置为1,因此正交投影矩阵为

\[ \begin{bmatrix} \frac{2}{r-l}&0&0&-\frac{r+l}{r-l}\\ 0&\frac{2}{t-b}&0&-\frac{t+b}{t-b}\\ 0&0&-\frac{2}{f-n}&-\frac{f+n}{f-n}\\ 0&0&0&1\\ \end{bmatrix} \]

同透视投影一样,若是是对称的话,那么就可以矩阵就可以变简朴

\[ \begin{bmatrix} \frac{1}{r}&0&0&0\\ 0&\frac{1}{t}&0&0\\ 0&0&-\frac{2}{f-n}&-\frac{f+n}{f-n}\\ 0&0&0&1\\ \end{bmatrix} \]

,

Allbet

www.zhu-tie-guan.com欢迎进入欧博平台(Allbet Gaming),欧博平台开放欧博(Allbet)开户、欧博(Allbet)代理开户、欧博(Allbet)电脑客户端、欧博(Allbet)APP下载等业务。

版权声明

本文仅代表作者观点,
不代表本站Allbet的立场。
本文系作者授权发表,未经许可,不得转载。

评论