zoukankan      html  css  js  c++  java
  • 数学基础

    参考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} \]

    如有错误,敬请指正

    每次做题提醒自己:题目到底有没有读懂,有没有分析彻底、算法够不够贪心、暴力够不够优雅。
  • 相关阅读:
    IXmlSerializable With WCFData Transfer in Service Contracts
    Difference Between XmlSerialization and BinarySerialization
    Using XmlSerializer (using Attributes like XmlElement , XmlAttribute etc ) Data Transfer in Service Contracts
    Introducing XML Serialization
    Version Tolerant Serialization
    Which binding is bestWCF Bindings
    Data Transfer in Service Contracts
    DataContract KnownTypeData Transfer in Service Contracts
    Using the Message ClassData Transfer in Service Contracts
    DataContract POCO SupportData Transfer in Service Contracts
  • 原文地址:https://www.cnblogs.com/spnooyseed/p/15603973.html
Copyright © 2011-2022 走看看