• 数学基础


    参考games101和unity shader 入门精要

    一些重点的推导

    透视变换矩阵

    1. 将锥体压缩成长方体

    2. 将长方体压缩成中心移到原点

    3. 将长方体压缩成\([-2 , 2]^3\)的正方体 , [-1 , 1]也行

    先将这个锥体压缩成和Znear(近平面)同宽同高的长方体 ,远平面Zfar

    方法:假设一个4x4的仿射变换矩阵,找一些特殊的点

    比如:近平面的点\(\left(\begin{matrix} x \\ y \\ Znear \\ 1\end{matrix}\right)\tag{2}\) 经过变换之后还是\(\left(\begin{matrix} x \\ y \\ Znear \\ 1\end{matrix}\right)\tag{2}\),也可以写成\(\left(\begin{matrix} x*Znear \\ y * Znear \\ Znear*Znear \\ Znear\end{matrix}\right)\tag{2}\)

    \[\left(\begin{matrix}x_{11} & x_{12} &x_{13} & x_{14} \\x_{21} & x_{22} &x_{23} & x_{24}\\x_{31} & x_{32} &x_{33} & x_{34}\\x_{41} & x_{42} &x_{43} & x_{44} \end{matrix}\right) * {\left(\begin{matrix} x \\ y \\ Znear \\ 1\end{matrix}\right)} = {\left(\begin{matrix} x*Znear \\ y * Znear \\ Znear*Znear \\ Znear\end{matrix}\right)\tag{2}} \]

    \[这个仿射变换的矩阵就可以写成 \left(\begin{matrix} Znear & 0 & 0 & 0 \\ 0 & Znear & 0 & 0\\ 0 & 0 &x_{33} & x_{34}\\ 0 & 0 & 1 & 0 \end{matrix}\right) \]

    再找一个远平面Zfar最中心的点\(\left(\begin{matrix} 0 \\ 0 \\ Zfar \\ 1\end{matrix}\right)\tag{2}\), 经过变换之后依旧是\(\left(\begin{matrix} 0 \\ 0 \\ Zfear \\ 1\end{matrix}\right)\tag{2}\) , 也可以写成\(\left(\begin{matrix} 0 \\ 0 \\ Zfar * Zfar\\ Zfar\end{matrix}\right)\tag{2}\)

    \[这个仿射变换的矩阵就可以写成 \left(\begin{matrix} Znear & 0 & 0 & 0 \\ 0 & Znear & 0 & 0\\ 0 & 0 &x_{33} & x_{34}\\ 0 & 0 & 1 & 0 \end{matrix}\right) * \left(\begin{matrix} 0 \\ 0 \\ Zfar \\ 1\end{matrix}\right) = \left(\begin{matrix} 0 \\ 0 \\ Zfar * Zfar\\ Zfar\end{matrix}\right) \\解:perspective\_orth = \left(\begin{matrix} Znear & 0 & 0 & 0 \\ 0 & Znear & 0 & 0\\ 0 & 0 & Zfar * Znear & -Znear*Zfar\\ 0 & 0 & 1 & 0 \end{matrix}\right) \]

    将长方体压缩成中心移到原点

    此时定义一个摄像头的视角fov , 还有一个宽高比 那么长方体上下左右坐标分别为

        eye_fov = eye_fov * 0.5 * MY_PI / 180.0;
        float top = tan(eye_fov) * zNear, bottom = -top;
        float right = top * aspect_ratio, left = -right;
    

    那么移动到原点的仿射变换方程为

    \[orth\_to\_origin = \left(\begin{matrix} 1 & 0 & 0 & \frac{-(right+ left)}{2} \\ 0 & 1& 0 & \frac{-(top + bottom)}{2}\\ 0 & 0 & 1 & \frac{-(Znear + Zfar)}{2})\\ 0 & 0 & 0 & 1 \end{matrix}\right) \]

    将长方体压缩成\([-2 , 2]^3\)的正方体 , [-1 , 1]也行

    \[orth = \left(\begin{matrix} \frac{2}{(right - left)} & 0 & 0 & 0 \\ 0 & \frac{2}{top - bottom}& 0 & 0\\ 0 & 0 & \frac{2}{Znear - Zfar} & 0 \\ 0 & 0 & 0 & 1 \end{matrix}\right) \]

    最后 \(projection = orth * orth\_to\_orgin * perspective\_orth;\)

    空间变换

    上面的透视变换矩阵只是一种,还有一种高级用法:法线变换

    法线变换:由法线空间变换到观察空间内

    1. 首先看空间变换是怎么回事,是怎么变的

      父空间P以及子空间C , 一般有两种需求,1,从子空间变换到父空间;2,从父空间变换到子空间,只要把这个矩阵表示为正交矩阵,两者求一个就行,另一个转置即可

      我们求从子空间变换到父空间

      子坐标表示下的矢量或者坐标\(A_C\) 转换到父坐标空间\(A_p\)

      \(A_p = M_{c->p} * A_c \\ M_{c->p}即为子空间变换到父空间的变换坐标\)

      那么怎么求?

      使用一个很简单的例子:

      子空间的坐标轴在父空间的表示为\(X_C ,Y_C , Z_C , 以及O_C\)

      还有一点子坐标空间内的\(A_C = (a , b , c)\)

      那么从坐标原点\(O_c\) 走到\(A_c\) 即为 \(O_c + a * X_c + b * Y_c + c * Z_c\)

      在父空间下面同样的步骤也会走到\(A_c\) , 但是此时此刻实在父空间下,也可以写成\(A_p = O_c + a * X_c + b * Y_c + c * Z_c\)

      写成矩阵即为

      \[A_p = \left(\begin{matrix}| & | & | & x_{O_c} \\X_c &Y_c&Z_c&Y_{O_c}\\|&|&|&Z_{O_c}\\0&0&0&1\end{matrix}\right) *\left(\begin{matrix}a\\b\\c\\1\end{matrix}\right)\\ M_{c->p} = {\left(\begin{matrix}| & | & | & x_{O_c} \\X_c &Y_c&Z_c&Y_{O_c}\\|&|&|&Z_{O_c}\\0&0&0&1\end{matrix}\right) } \]

      1. 那么一个矢量从子空间变换到父空间的矩阵

        因为上面是点,需要位移,这个是矢量,不需要位移把最后一行,最后一列去掉

        \[M_{c->p} = {\left(\begin{matrix}| & | & | \\X_c &Y_c&Z_c\\|&|&|\end{matrix}\right) } \]

      2. 那么从父空间到子空间的矩阵为

    \[M_{p->c} = {M_{c->p}} ^{-1} = {M_{c->p}} ^{T} = {\left(\begin{matrix}- & X_c & - \\ - &Y_c& - \\ - & Z_c &-\end{matrix}\right) } \]

    前提,这个矩阵必须正交,三个向量相互垂直(三个坐标轴肯定垂直) , 然后将三个向量单位化,ok

    法线变换

    在法线进行非同一伸缩变换的时候,不能够直接使用上述公式

    法线不能,但是切线可以。

    假设如同上面,切线为\(父空间下 T_p , 子空间下T_c\)

    法线为\(父空间下 N_P, 子空间下N_c\)

    切线变换公式

    \[T_p = {M_{c->p}} T_c \]

    无论在父空间还是子空间下面法线始终和切线垂直

    \[T_p * N_p = (M_{c->p}T_c) * (GN_c) = 0 \]

    这个G为从子空间将法线变换到父空间的正交矩阵

    上式等于

    \[{T_c}^T{M^T_{c->p}}GN_c = 0\\{T_c}^TN_c = 0\\{M_{c->p}}^TG = I\\ G = {M^T_{c->p}}^{-1} = {M^{-1}_{c->p}}^{T} = {M^T_{p->c}}\\ 是不是突然第一步突然把上面中间的点乘去掉了,左边换成转置了 \\上面那个是 数学逻辑上面的点乘,这个是实际做法点乘\\当时我也困惑了好久,举个例子\\ \left(\begin{matrix} a\\b\\c \end{matrix}\right) *\left(\begin{matrix} x\\y\\z \end{matrix}\right) = \left(\begin{matrix} ax\\by\\cz \end{matrix}\right) \\但是我们实际上计算这两个点乘肯定是这样的\\ \left(\begin{matrix} a & b & c \end{matrix}\right) * \left(\begin{matrix} x\\y\\z \end{matrix}\right) = \left(\begin{matrix} ax & by & cz \end{matrix}\right) \]

    ​ 那么在unity中法线最后从子空间C变换到P空间是什么呢。

    \[GN_C = {M^T_{p->c}}N_c \\ 注意这个此时 M_{3×3}N_c(_{3×1}) = N_p(_{3×1})\\ 在线性代数上面这个肯定不能相乘,上面这个只是逻辑上的 \\N_p(_{1×3}) = N_c(_{1×3})M_{p->c} \]

    如有错误,敬请指正

    每次做题提醒自己:题目到底有没有读懂,有没有分析彻底、算法够不够贪心、暴力够不够优雅。
  • 相关阅读:
    学生管理系统代写
    学生竞赛评价系统
    《划时代51单片机C语言全新教程》前言
    《划时代51单片机C语言全新教程》第三章 开发环境 概览
    校验和
    NBOOT分析-S3C244xInit.s(1)
    《划时代51单片机C语言全新教程》第一章 8051简介 概览
    《划时代51单片机C语言全新教程》第二章 STC89C52RC 处理器 概览
    ARM9中断调试(1)
    NBOOT分析-NBOOT.c(2)
  • 原文地址:https://www.cnblogs.com/spnooyseed/p/15603973.html
Copyright © 2020-2023  润新知