<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 第三課:矩陣 # 第三課: 矩陣 引擎完全沒有推動飛船。飛船靜止在原處,而引擎推動了環繞著飛船的宇宙。 *《飛出個未來》(一部美國科幻動畫片)* > 這一課是所有課程中最重要的。請至少看八遍。 ## 齊次坐標(Homogeneous coordinates) 目前為止,我們仍然把三維頂點視為三元組(x, y, z)。現在引入一個新的分量w,得到向量(x, y, z, w)。 請先記住以下兩點(稍后我們會給出解釋): 若w==1,則向量(x, y, z, 1)為空間中的點。 若w==0,則向量(x, y, z, 0)為方向。 `(事實上,要永遠記著。)` 這有什么不同呢?對于旋轉,二者沒什么不同。當你旋轉點和方向時,結果是一樣的。但對于平移(將點沿著某個方向移動),情況就不同了。『平移一個方向』是毫無意義的。 齊次坐標使我們能用同一個公式對點和方向作運算。 ## 變換矩陣(Transformation matrices) ### 矩陣簡介 簡而言之,矩陣就是一個行、列數固定的,縱橫排列的數表。比如,一個2×3矩陣看起來像這樣: ![](https://box.kancloud.cn/2015-11-02_5636f30204279.png) 三維圖形學中我們只用到4×4矩陣,它能對頂點(x, y, z, w)作變換。這一變換是用矩陣左乘頂點來實現的: 矩陣x頂點(記住順序!!矩陣左乘頂點,頂點用列向量表示)= 變換后的頂點 ![](https://box.kancloud.cn/2015-11-02_5636f30210012.gif) 這看上去復雜,實則不然。左手指著a,右手指著x,得到ax。 左手移向右邊一個數b,右手移向下一個數y,得到by。依次類推,得到cz、dw。最后求和ax + by + cz + dw,就得到了新的x!每一行都這么算下去,就得到了新的(x, y, z, w)向量。 這種重復無聊的計算就讓計算機代勞吧。 **用C++,GLM表示:** ``` <pre class="calibre16">``` glm<span class="token1">:</span><span class="token1">:</span>mat4 myMatrix<span class="token1">;</span> glm<span class="token1">:</span><span class="token1">:</span>vec4 myVector<span class="token1">;</span> <span class="token2">// fill myMatrix and myVector somehow</span> glm<span class="token1">:</span><span class="token1">:</span>vec4 transformedVector <span class="token">=</span> myMatrix <span class="token">*</span> myVector<span class="token1">;</span> <span class="token2">// Again, in this order ! this is important.</span> ``` ``` **用GLSL表示:** ``` <pre class="calibre16">``` mat4 myMatrix<span class="token1">;</span> vec4 myVector<span class="token1">;</span> <span class="token2">// fill myMatrix and myVector somehow</span> vec4 transformedVector <span class="token">=</span> myMatrix <span class="token">*</span> myVector<span class="token1">;</span> <span class="token2">// Yeah, it's pretty much the same than GLM</span> ``` ``` `(還沒把這些復制到你的代碼里跑跑嗎?趕緊試試!)` ### 平移矩陣(Translation matrices) 平移矩陣是最簡單易懂的變換矩陣。平移矩陣是這樣的: ![](https://box.kancloud.cn/2015-11-02_5636f30228b6d.png) 其中,X、Y、Z是點的位移增量。 例如,若想把向量(10, 10, 10, 1)沿X軸方向平移10個單位,可得: ![](https://box.kancloud.cn/2015-11-02_5636f3023403f.png) `(算算看!一定要動手算算!!)` 這樣就得到了齊次向量(20, 10, 10, 1)!記住,末尾的1表示這是一個點,而不是方向。經過變換計算后,點仍然是點,很合理。 下面來看看,對一個代表Z軸負方向的向量,作上述平移變換會得到什么結果: ![](https://box.kancloud.cn/2015-11-02_5636f30241a21.png) 即還是原來的(0, 0, -1, 0)方向,這也很合理,正好印證了前面的結論:“平移一個方向是毫無意義的”。 那怎么用代碼表示平移變換呢? **用C++,GLM表示:** ``` <pre class="calibre16">``` #include <span class="token"><</span>glm<span class="token">/</span>transform<span class="token1">.</span>hpp<span class="token">></span> <span class="token2">// after <glm/glm.hpp></span> glm<span class="token1">:</span><span class="token1">:</span>mat4 myMatrix <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">translate</span><span class="token1">(</span><span class="token6">10</span><span class="token1">,</span><span class="token6">0</span><span class="token1">,</span><span class="token6">0</span><span class="token1">)</span><span class="token1">;</span> glm<span class="token1">:</span><span class="token1">:</span>vec4 <span class="token3">myVector</span><span class="token1">(</span><span class="token6">10</span><span class="token1">,</span><span class="token6">10</span><span class="token1">,</span><span class="token6">10</span><span class="token1">,</span><span class="token6">0</span><span class="token1">)</span><span class="token1">;</span> glm<span class="token1">:</span><span class="token1">:</span>vec4 transformedVector <span class="token">=</span> myMatrix <span class="token">*</span> myVector<span class="token1">;</span> <span class="token2">// guess the result</span> ``` ``` \*\*用GLSL表示:\*\*呃,實際中我們幾乎不用GLSL做。大多數情況下在C++代碼中用glm::translate()算出矩陣,然后把它傳給GLSL。在GLSL中只做一次乘法: ``` <pre class="calibre16">``` vec4 transformedVector <span class="token">=</span> myMatrix <span class="token">*</span> myVector<span class="token1">;</span> ``` ``` ### 單位矩陣(Identity matrix) 單位矩陣很特殊,它什么也不做。我提到它是因為,知道它和知道A\*1.0=A一樣重要。 ![](https://box.kancloud.cn/2015-11-02_5636f3024efb0.png) 用C++表示: ``` <pre class="calibre16">``` glm<span class="token1">:</span><span class="token1">:</span>mat4 myIdentityMatrix <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">mat4</span><span class="token1">(</span><span class="token6">1.0</span><span class="token1">)</span><span class="token1">;</span> ``` ``` ### 縮放矩陣(Scaling matrices) 縮放矩陣也很簡單: ![](https://box.kancloud.cn/2015-11-02_5636f3025a6cb.png) 例如把一個向量(點或方向皆可)沿各方向放大2倍: ![](https://box.kancloud.cn/2015-11-02_5636f302662d0.png) w還是沒變。你也許會問:“縮放一個向量”有什么用?嗯,大多數情況下是沒什么用,所以一般不會去做;但在某些罕見情況下它就有用了。(順便說一下,單位矩陣只是縮放矩陣的一個特例,其(X, Y, Z) = (1, 1, 1)。單位矩陣同時也是旋轉矩陣的一個特例,其(X, Y, Z)=(0, 0, 0))。 **用C++表示:** ``` <pre class="calibre16">``` <span class="token2">// Use #include <glm/gtc/matrix_transform.hpp> and #include <glm/gtx/transform.hpp></span> glm<span class="token1">:</span><span class="token1">:</span>mat4 myScalingMatrix <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">scale</span><span class="token1">(</span><span class="token6">2</span><span class="token1">,</span><span class="token6">2</span><span class="token1">,</span><span class="token6">2</span><span class="token1">)</span><span class="token1">;</span> ``` ``` ### 旋轉矩陣(Rotation matrices) 旋轉矩陣比較復雜。這里略過細節,因為日常應用中,你并不需要知道矩陣的內部構造。想了解更多,請看[矩陣和四元組常見問題](http://www.cs.princeton.edu/~gewang/projects/darth/stuff/quat_faq.html)(這個資源很熱門,應該有中文版吧)。 **用C++表示:** ``` <pre class="calibre16">``` <span class="token2">// Use #include <glm/gtc/matrix_transform.hpp> and #include <glm/gtx/transform.hpp></span> glm<span class="token1">:</span><span class="token1">:</span>vec3 <span class="token3">myRotationAxis</span><span class="token1">(</span> <span class="token">?</span><span class="token">?</span><span class="token1">,</span> <span class="token">?</span><span class="token">?</span><span class="token1">,</span> <span class="token">?</span><span class="token">?</span><span class="token1">)</span><span class="token1">;</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">rotate</span><span class="token1">(</span> angle_in_degrees<span class="token1">,</span> myRotationAxis <span class="token1">)</span><span class="token1">;</span> ``` ``` ### 復合變換 前面已經學習了如何旋轉、平移和縮放向量。要是能將它們組合起來就更好了。只需把這些矩陣相乘即可,例如: ``` <pre class="calibre16">``` TransformedVector <span class="token">=</span> TranslationMatrix <span class="token">*</span> RotationMatrix <span class="token">*</span> ScaleMatrix <span class="token">*</span> OriginalVector<span class="token1">;</span> ``` ``` !!!千萬注意!!!這行代碼最先執行縮放,接著旋轉,最后才是平移。這就是矩陣乘法的工作方式。 變換的順序不同,得出的結果也不同。體驗一下: - 向前一步(小心別磕著愛機)然后左轉; - 左轉,然后向前一步 實際上,上述順序正是你在變換游戲人物或者其他物體時所需的:先縮放;再調整方向;最后平移。例如,假設有個船的模型(為簡化,略去旋轉): `錯誤做法:` - 按(10, 0, 0)平移船體。船體中心目前距離原點10個單位。 - 將船體放大2倍。以原點為參照,每個坐標都變成原來的2倍,就出問題了。……最后你是得到一艘放大的船,但其中心位于2\*10=20。這可不是你想要的結果。 `正確做法:` - 將船體放大2倍,得到一艘中心位于原點的大船。 - 平移船體。船大小不變,移動距離也正確。 矩陣-矩陣乘法和矩陣-向量乘法類似,所以這里也會省略一些細節,不清楚的請移步“矩陣和四元數常見問題”。現在,就讓計算機來算: **用C++,GLM表示:** ``` <pre class="calibre16">``` glm<span class="token1">:</span><span class="token1">:</span>mat4 myModelMatrix <span class="token">=</span> myTranslationMatrix <span class="token">*</span> myRotationMatrix <span class="token">*</span> myScaleMatrix<span class="token1">;</span> glm<span class="token1">:</span><span class="token1">:</span>vec4 myTransformedVector <span class="token">=</span> myModelMatrix <span class="token">*</span> myOriginalVector<span class="token1">;</span> ``` ``` **用GLSL表示:** ``` <pre class="calibre16">``` mat4 transform <span class="token">=</span> mat2 <span class="token">*</span> mat1<span class="token1">;</span> vec4 out_vec <span class="token">=</span> transform <span class="token">*</span> in_vec<span class="token1">;</span> ``` ``` ## 模型(Model)、視圖(View)和投影(Projection)矩陣 *在接下來的課程中,我們假定已知繪制Blender經典三維模型:小猴Suzanne的方法。* 利用模型、視圖和投影矩陣,可以將變換過程清晰地分解為三個階段。這個方法你可以不用(我們在前兩課就沒用),但最好要用。我們即將看到,它們把整個流程劃分得很清楚,故被廣為使用。 ### 模型矩陣 這個三維模型,和我們心愛的紅色三角形一樣,是由一組頂點定義的。頂點的XYZ坐標是相對于物體中心定義的:也就是說,若某頂點位于(0, 0, 0),它就在物體的中心。 ![](https://box.kancloud.cn/2015-11-02_5636f3027467e.png) 也許玩家需要用鍵鼠控制這個模型,所以我們希望能夠移動它。這簡單,只需學會:縮放*旋轉*平移就行了。在每一幀中,用算出的這個矩陣,去乘(在GLSL中乘,不是C++中!)所有的頂點,物體就動了。唯一不動的就是世界坐標系(World Space)的中心。 ![](https://box.kancloud.cn/2015-11-02_5636f30289c51.png) 現在,物體所有頂點都位于世界坐標系。下圖中黑色箭頭的意思是:*從模型坐標系(Model Space)(頂點都相對于模型的中心定義)變換到世界坐標系(頂點都相對于世界坐標系中心定義)。* ![](https://box.kancloud.cn/2015-11-02_5636f302a1aa2.png) 下圖概括了這一過程: ![](https://box.kancloud.cn/2015-11-02_5636f302b29a3.png) ### 視圖矩陣 這里再引用一下《飛出個未來》: 引擎完全沒有推動飛船。飛船靜止在原處,而引擎推動了環繞著飛船的宇宙。 ![](https://box.kancloud.cn/2015-11-02_5636f302bd7e5.png) 仔細想想,相機的原理也是相通的。如果想換個角度觀察一座山,你可以移動相機也可以……移動山。后者在生活中不可行,在計算機圖形學中卻十分方便。 起初,相機位于世界坐標系的原點。移動世界只需乘上一個矩陣。假如你想把相機向右(X軸正方向)移動3個單位,這和把整個世界(包括網格)向左(X軸負方向)移3個單位是等效的!腦子有點亂?來寫代碼: ``` <pre class="calibre16">``` <span class="token2">// Use #include <glm/gtc/matrix_transform.hpp> and #include <glm/gtx/transform.hpp></span> glm<span class="token1">:</span><span class="token1">:</span>mat4 ViewMatrix <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">translate</span><span class="token1">(</span><span class="token">-</span><span class="token6">3</span><span class="token1">,</span><span class="token6">0</span><span class="token1">,</span><span class="token6">0</span><span class="token1">)</span><span class="token1">;</span> ``` ``` 下圖展示了:從世界坐標系(頂點都相對于世界坐標系中心定義)到觀察坐標系(Camera Space,頂點都相對于相機定義)的變換。 ![](https://box.kancloud.cn/2015-11-02_5636f302ce291.png) **在腦袋撐爆前,來欣賞一下GLM偉大的glm::LookAt函數吧:** ``` <pre class="calibre16">``` glm<span class="token1">:</span><span class="token1">:</span>mat4 CameraMatrix <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">LookAt</span><span class="token1">(</span> cameraPosition<span class="token1">,</span> <span class="token2">// the position of your camera, in world space</span> cameraTarget<span class="token1">,</span> <span class="token2">// where you want to look at, in world space</span> upVector <span class="token2">// probably glm::vec3(0,1,0), but (0,-1,0) would make you looking upside-down, which can be great too</span> <span class="token1">)</span><span class="token1">;</span> ``` ``` 下圖解釋了上述變換過程: ![](https://box.kancloud.cn/2015-11-02_5636f302e3376.png) 還沒完呢。 ### 投影矩陣 現在,我們處于觀察坐標系中。這意味著,經歷了這么多變換后,現在一個坐標為(0,0)的頂點,應該被畫在屏幕的中心。但僅有x、y坐標還不足以確定物體是否應該畫在屏幕上:它到相機的距離(z)也很重要!兩個x、y坐標相同的頂點,z值較大的一個將會最終顯示在屏幕上。 這就是所謂的透視投影(perspective projection): ![](https://box.kancloud.cn/2015-11-02_5636f302f23d0.png) 好在用一個4×4矩陣就能表示這個投影1 : ``` <pre class="calibre16">``` <span class="token2">// Generates a really hard-to-read matrix, but a normal, standard 4x4 matrix nonetheless</span> glm<span class="token1">:</span><span class="token1">:</span>mat4 projectionMatrix <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">perspective</span><span class="token1">(</span> FoV<span class="token1">,</span> <span class="token2">// The horizontal Field of View, in degrees : the amount of "zoom". Think "camera lens". Usually between 90° (extra wide) and 30° (quite zoomed in)</span> <span class="token6">4.0</span>f <span class="token">/</span> <span class="token6">3.0</span>f<span class="token1">,</span> <span class="token2">// Aspect Ratio. Depends on the size of your window. Notice that 4/3 == 800/600 == 1280/960, sounds familiar ?</span> <span class="token6">0.1</span>f<span class="token1">,</span> <span class="token2">// Near clipping plane. Keep as big as possible, or you'll get precision issues.</span> <span class="token6">100.0</span>f <span class="token2">// Far clipping plane. Keep as little as possible.</span> <span class="token1">)</span><span class="token1">;</span> ``` ``` 最后一個變換: *從觀察坐標系(頂點都相對于相機定義)到齊次坐標系(Homogeneous Space)(頂點都在一個小立方體中定義。立方體內的物體都會在屏幕上顯示)的變換。* 最后一幅圖示: ![](https://box.kancloud.cn/2015-11-02_5636f30313631.png) 再添幾張圖,以便大家更好地理解投影變換。投影前,藍色物體都位于觀察坐標系中,紅色的東西是相機的視域四棱錐(frustum):這是相機實際能看見的區域。 ![](https://box.kancloud.cn/2015-11-02_5636f303254ee.png) 用投影矩陣去乘前面的結果,得到如下效果: ![](https://box.kancloud.cn/2015-11-02_5636f303466ca.png) 此圖中,視域四棱錐變成了一個正方體(每條棱的范圍都是-1到1,圖上不太明顯),所有的藍色物體都經過了相同的形變。因此,離相機近的物體就顯得大一些,遠的顯得小一些。和真實生活中一樣! 讓我們從視域四棱錐的“后面”看看它們的模樣: ![](https://box.kancloud.cn/2015-11-02_5636f30370697.png) 這就是你得出的圖像了!看上去太方方正正了,因此,還需要做一次數學變換使之適合實際的窗口大小: ![](https://box.kancloud.cn/2015-11-02_5636f30384093.png) 這就是實際渲染的圖像啦! ### 復合變換:模型視圖投影矩陣(MVP) … 再來一串親愛的矩陣乘法: ``` <pre class="calibre16">``` <span class="token2">// C++ : compute the matrix</span> glm<span class="token1">:</span><span class="token1">:</span>mat3 MVPmatrix <span class="token">=</span> projection <span class="token">*</span> view <span class="token">*</span> model<span class="token1">;</span> <span class="token2">// Remember : inverted !</span> <span class="token2">// GLSL : apply it</span> transformed_vertex <span class="token">=</span> MVP <span class="token">*</span> in_vertex<span class="token1">;</span> ``` ``` ## 總結 **第一步:創建模型視圖投影(MVP)矩陣。任何要渲染的模型都要做這一步。** ``` <pre class="calibre16">``` <span class="token2">// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit 100 units</span> glm<span class="token1">:</span><span class="token1">:</span>mat4 Projection <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">perspective</span><span class="token1">(</span><span class="token6">45.0</span>f<span class="token1">,</span> <span class="token6">4.0</span>f <span class="token">/</span> <span class="token6">3.0</span>f<span class="token1">,</span> <span class="token6">0.1</span>f<span class="token1">,</span> <span class="token6">100.0</span>f<span class="token1">)</span><span class="token1">;</span> <span class="token2">// Camera matrix</span> glm<span class="token1">:</span><span class="token1">:</span>mat4 View <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">lookAt</span><span class="token1">(</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">vec3</span><span class="token1">(</span><span class="token6">4</span><span class="token1">,</span><span class="token6">3</span><span class="token1">,</span><span class="token6">3</span><span class="token1">)</span><span class="token1">,</span> <span class="token2">// Camera is at (4,3,3), in World Space</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">vec3</span><span class="token1">(</span><span class="token6">0</span><span class="token1">,</span><span class="token6">0</span><span class="token1">,</span><span class="token6">0</span><span class="token1">)</span><span class="token1">,</span> <span class="token2">// and looks at the origin</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">vec3</span><span class="token1">(</span><span class="token6">0</span><span class="token1">,</span><span class="token6">1</span><span class="token1">,</span><span class="token6">0</span><span class="token1">)</span> <span class="token2">// Head is up (set to 0,-1,0 to look upside-down)</span> <span class="token1">)</span><span class="token1">;</span> <span class="token2">// Model matrix : an identity matrix (model will be at the origin)</span> glm<span class="token1">:</span><span class="token1">:</span>mat4 Model <span class="token">=</span> glm<span class="token1">:</span><span class="token1">:</span><span class="token3">mat4</span><span class="token1">(</span><span class="token6">1.0</span>f<span class="token1">)</span><span class="token1">;</span> <span class="token2">// Changes for each model !</span> <span class="token2">// Our ModelViewProjection : multiplication of our 3 matrices</span> glm<span class="token1">:</span><span class="token1">:</span>mat4 MVP <span class="token">=</span> Projection <span class="token">*</span> View <span class="token">*</span> Model<span class="token1">;</span> <span class="token2">// Remember, matrix multiplication is the other way around</span> ``` ``` **第二步:把MVP傳給GLSL** ``` <pre class="calibre16">``` <span class="token2">// Get a handle for our "MVP" uniform.</span> <span class="token2">// Only at initialisation time.</span> GLuint MatrixID <span class="token">=</span> <span class="token3">glGetUniformLocation</span><span class="token1">(</span>programID<span class="token1">,</span> <span class="token5">"MVP"</span><span class="token1">)</span><span class="token1">;</span> <span class="token2">// Send our transformation to the currently bound shader,</span> <span class="token2">// in the "MVP" uniform</span> <span class="token2">// For each model you render, since the MVP will be different (at least the M part)</span> <span class="token3">glUniformMatrix4fv</span><span class="token1">(</span>MatrixID<span class="token1">,</span> <span class="token6">1</span><span class="token1">,</span> GL_FALSE<span class="token1">,</span> <span class="token">&</span>MVP<span class="token1">[</span><span class="token6">0</span><span class="token1">]</span><span class="token1">[</span><span class="token6">0</span><span class="token1">]</span><span class="token1">)</span><span class="token1">;</span> ``` ``` **第三步:在GLSL中用MVP變換頂點** ``` <pre class="calibre16">``` <span class="token4">in</span> vec3 vertexPosition_modelspace<span class="token1">;</span> uniform mat4 MVP<span class="token1">;</span> void <span class="token3">main</span><span class="token1">(</span><span class="token1">)</span><span class="token1">{</span> <span class="token2">// Output position of the vertex, in clip space : MVP * position</span> vec4 v <span class="token">=</span> <span class="token3">vec4</span><span class="token1">(</span>vertexPosition_modelspace<span class="token1">,</span><span class="token6">1</span><span class="token1">)</span><span class="token1">;</span> <span class="token2">// Transform an homogeneous 4D vector, remember ?</span> gl_Position <span class="token">=</span> MVP <span class="token">*</span> v<span class="token1">;</span> <span class="token1">}</span> ``` ``` **完成!三角形和第二課的一樣,仍然在原點(0, 0, 0),然而是從點(4, 3, 3)透視觀察的;相機的上方向為(0, 1, 0),視場角(field of view)45°。** ![](https://box.kancloud.cn/2015-11-02_5636f30393aba.png) 第6課中你會學到怎樣用鍵鼠動態修改這些值,從而創建一個和游戲中類似的相機。但我們會先學給三維模型上色(第4課)、貼紋理(第5課)。 ## 練習 **試著替換glm::perspective** **不用透視投影,試試正交投影(orthographic projection )(glm::ortho)** **把ModelMatrix改成先平移,再旋轉,最后放縮三角形** **其他不變,但把模型矩陣運算改成平移-旋轉-放縮的順序,會有什么變化?如果對一個人作變換,你覺得什么順序最好呢?** *附注* *1 : \[...\]好在用一個4×4矩陣就能表示這個投影:實際上,這句話并不對。透視變換不是仿射(affine)的,因此,透視投影無法完全由一個矩陣表示。向量與投影矩陣相乘之后,它齊次坐標的每個分量都要除以自身的W(透視除法)。W分量恰好是-Z(投影矩陣會保證這一點)。這樣,離原點更遠的點,被除了較大的Z值;其X、Y坐標變小,點與點之間變緊,物體看起來就小了,這才產生了透視效果。*
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看