![一步步學OpenGL《復合變換》_第1頁](http://file3.renrendoc.com/fileroot_temp3/2021-12/18/da9a55f4-d0c6-493a-bb6b-97c206a0da7e/da9a55f4-d0c6-493a-bb6b-97c206a0da7e1.gif)
![一步步學OpenGL《復合變換》_第2頁](http://file3.renrendoc.com/fileroot_temp3/2021-12/18/da9a55f4-d0c6-493a-bb6b-97c206a0da7e/da9a55f4-d0c6-493a-bb6b-97c206a0da7e2.gif)
![一步步學OpenGL《復合變換》_第3頁](http://file3.renrendoc.com/fileroot_temp3/2021-12/18/da9a55f4-d0c6-493a-bb6b-97c206a0da7e/da9a55f4-d0c6-493a-bb6b-97c206a0da7e3.gif)
![一步步學OpenGL《復合變換》_第4頁](http://file3.renrendoc.com/fileroot_temp3/2021-12/18/da9a55f4-d0c6-493a-bb6b-97c206a0da7e/da9a55f4-d0c6-493a-bb6b-97c206a0da7e4.gif)
![一步步學OpenGL《復合變換》_第5頁](http://file3.renrendoc.com/fileroot_temp3/2021-12/18/da9a55f4-d0c6-493a-bb6b-97c206a0da7e/da9a55f4-d0c6-493a-bb6b-97c206a0da7e5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、一步步學OpenGL復合變換背景在前面的幾個教程中我們建立了幾種基本圖形變換是我們能靈活的將物體移動到3d世界的任意地方。我們還有很多要學(相機控制和透視投影等等),但你可能也已經(jīng)想到,復合的圖形變換也是必的。多數(shù)情況下,你會想縮放物體來和3d世界相適應,旋轉(zhuǎn)物體到合適的方向,移動物體到某個地方等等。到現(xiàn)在我們已經(jīng)實踐了每一次的單一圖形變換。為了實現(xiàn)上面一系列的變換,我們需要對頂點位置左乘第一個變換矩陣,然后得到的結(jié)果再左乘下一個變換矩陣等等,將所有變換矩陣都左乘頂點位置之后實現(xiàn)多個變換。一種笨辦法就是在shader中應用每一個變換矩陣實現(xiàn)所有的變換,但這樣很低效,因為對于所有頂點這些矩陣都是
2、一樣的,只有頂點的位置發(fā)生變化,這樣要不斷重復對每個頂點位置進行這一系列的矩陣相乘操作。幸運的是線性代數(shù)中有一些規(guī)則可以說讓我們的生活更加簡易,他告我們對于給定的一組矩陣M0Mn和一個向量V有下面的等式換算:Mn * Mn-1 * . * M0 * V = (Mn* Mn-1 * . * M0) * V所以如果你令:N = Mn * Mn-1 * . * M0那么:Mn * Mn-1 * . * M0 * V = (Mn * Mn-1 * . * M0) * V = N * V這意味著我們可以一次性計算N,然后把它作為一致變量傳給shader和每一個頂點位置相乘完成所有的變換,這個只需要GPU
3、對每個頂點進行一次矩陣/向量相乘操作。當計算N的時候怎樣安排每個變換矩陣的先后順序呢?你首先要記住向量最開始先是被最右邊的矩陣左乘的(上面的例子就是M0)。然后向量被從右邊到左邊所有的變換矩陣所變換。在3d圖形中你通常希望先縮放物體,然后旋轉(zhuǎn)它,然后平移,之后再進行camera轉(zhuǎn)換最后投影到2d屏幕。讓我們先看先旋轉(zhuǎn)后平移會怎樣:可以看出,如果先平移物體的話會很難來設(shè)置物體的最終位置,因為當你將物體遠離坐標原點后,再旋轉(zhuǎn)物體會同時造成物體的平移效果(是繞原點旋轉(zhuǎn),而不是繞自身旋轉(zhuǎn)了),這是我們希望能避免的。通過先旋轉(zhuǎn)后移動可以避免這兩個操作的相互依賴性,這也是盡量圍繞原點對稱建模的原因,那樣當
4、你縮放或者旋轉(zhuǎn)物體不會產(chǎn)生副作用,縮放和旋轉(zhuǎn)后物體依然保持和之前一樣對稱。源代碼詳解(1) #define ToRadian(x) (x) * M_PI / 180.0f)#define ToDegree(x) (x) * 180.0f / M_PI)在這個教程中我們開始要使用具體的角度值了。標準C語言庫中三角函數(shù)使用弧度值作為參數(shù)。上面的宏定義可以實現(xiàn)角度和弧度之間的轉(zhuǎn)換。(2)inline Matrix4f operator*(const Matrix4f& Right) const Matrix4f Ret; for (unsigned int i = 0 ; i < 4
5、; i+) for (unsigned int j = 0 ; j < 4 ; j+) Ret.mij = mi0 * Right.m0j + mi1 * Right.m1j + mi2 * Right.m2j + mi3 * Right.m3j; return Ret;這里是定義了矩陣相乘的操作符??梢钥吹浇Y(jié)果矩陣的值依次是左邊矩陣每一行和右邊矩陣對應每一列的點乘。這個矩陣相乘的操作對實現(xiàn)管線類十分重要。(3)class Pipeline public: Pipeline() . void Scale(float ScaleX, float ScaleY, float ScaleZ)
6、. void WorldPos(float x, float y, float z) . void Rotate(float RotateX, float RotateY, float RotateZ) . const Matrix4f* GetTrans(); private: Vector3f m_scale; Vector3f m_worldPos; Vector3f m_rotateInfo; Matrix4f m_transformation;管線類抽象出了一個物體的所有變換的數(shù)據(jù)信息。現(xiàn)在有3個私有vector成員變量分別來存儲物體在世界空間中的縮放比例,位置和每個像素的旋轉(zhuǎn)角度。
7、另外有接口函數(shù)來設(shè)置他們的值,以及可以獲取表示所有變換最終的復合變換矩陣。(4)const Matrix4f* Pipeline:GetTrans() Matrix4f ScaleTrans, RotateTrans, TranslationTrans; InitScaleTransform(ScaleTrans); InitRotateTransform(RotateTrans); InitTranslationTransform(TranslationTrans); m_transformation = TranslationTrans * RotateTrans * ScaleTrans
8、; return &m_transformation;這個函數(shù)初始化了那三個獨立的變換矩陣并把它們一個一個的相乘然后返回最終的積。注意相乘的順序是和上面描述的一樣固定死的。如果你想更靈活一點你可以設(shè)置一個定義變換順序的位掩碼。還要注意它總是將最終的復合變換矩陣作為一個陳成員變量。你可以通過檢查標記來做優(yōu)化,當上一次的變換函數(shù)沒有任何變化時可以返回上一次存儲的變換矩陣,避免重復計算。這個函數(shù)按照之前教程的內(nèi)容講的使用私有方法來產(chǎn)生不同的變換。在下一個教程中這個類還將被擴展,來進行相機控制和透視變換。(5)Pipeline p;p.Scale(sinf(Scale * 0.1f), sin
9、f(Scale * 0.1f), sinf(Scale * 0.1f);p.WorldPos(sinf(Scale), 0.0f, 0.0f);p.Rotate(sinf(Scale) * 90.0f, sinf(Scale) * 90.0f, sinf(Scale) * 90.0f);glUniformMatrix4fv(gWorldLocation, 1, GL_TRUE, (const GLfloat*)p.GetTrans();上面的語句是渲染函數(shù)中做的變化。我們實例化一個pipeline管線類對象,初始化配置好之后傳遞給shader。通過調(diào)整參數(shù)來看最終圖像的效果。示例Demo用到了
10、matrix4x4頭文件中的擴展工具函數(shù);#include <stdio.h>#include <string.h>#include <math.h>#include <GL/glew.h>#include <GL/freeglut.h>#include "ogldev_util.h"#include "ogldev_pipeline.h"GLuint VBO;GLuint IBO;GLuint gWorldLocation;const char* pVSFileName = "sha
11、der.vs"const char* pFSFileName = "shader.fs"static void RenderSceneCB() glClear(GL_COLOR_BUFFER_BIT); static float Scale = 0.0f; Scale += 0.001f; / 實例化一個pipeline管線類對象,初始化配置好之后傳遞給shader Pipeline p; p.Scale(sinf(Scale * 0.1f), sinf(Scale * 0.1f), sinf(Scale * 0.1f); p.WorldPos(sinf(Scal
12、e), 0.0f, 0.0f); p.Rotate(sinf(Scale) * 90.0f, sinf(Scale) * 90.0f, sinf(Scale) * 90.0f); glUniformMatrix4fv(gWorldLocation, 1, GL_TRUE, (const GLfloat*)p.GetWorldTrans(); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, VBO); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindB
13、uffer(GL_ELEMENT_ARRAY_BUFFER, IBO); glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0); glDisableVertexAttribArray(0); glutSwapBuffers();static void InitializeGlutCallbacks() glutDisplayFunc(RenderSceneCB); glutIdleFunc(RenderSceneCB);static void CreateVertexBuffer() Vector3f Vertices4; Vertices0
14、 = Vector3f(-1.0f, -1.0f, 0.0f); Vertices1 = Vector3f(0.0f, -1.0f, 1.0f); Vertices2 = Vector3f(1.0f, -1.0f, 0.0f); Vertices3 = Vector3f(0.0f, 1.0f, 0.0f); glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);static v
15、oid CreateIndexBuffer() unsigned int Indices = 0, 3, 1, 1, 3, 2, 2, 3, 0, 0, 1, 2 ; glGenBuffers(1, &IBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);static void AddShader(GLuint ShaderProgram, const char* pShaderTe
16、xt, GLenum ShaderType) GLuint ShaderObj = glCreateShader(ShaderType); if (ShaderObj = 0) fprintf(stderr, "Error creating shader type %dn", ShaderType); exit(1); const GLchar* p1; p0 = pShaderText; GLint Lengths1; Lengths0= strlen(pShaderText); glShaderSource(ShaderObj, 1, p, Lengths); glCo
17、mpileShader(ShaderObj); GLint success; glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success); if (!success) GLchar InfoLog1024; glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog); fprintf(stderr, "Error compiling shader type %d: '%s'n", ShaderType, InfoLog); exit(1); glAttachSh
18、ader(ShaderProgram, ShaderObj);static void CompileShaders() GLuint ShaderProgram = glCreateProgram(); if (ShaderProgram = 0) fprintf(stderr, "Error creating shader programn"); exit(1); string vs, fs; if (!ReadFile(pVSFileName, vs) exit(1); ; if (!ReadFile(pFSFileName, fs) exit(1); ; AddSha
19、der(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER); AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER); GLint Success = 0; GLchar ErrorLog1024 = 0 ; glLinkProgram(ShaderProgram); glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success); if (Success = 0) glGetProgramInfoLog(ShaderProgram, size
20、of(ErrorLog), NULL, ErrorLog); fprintf(stderr, "Error linking ader program: '%s'n", ErrorLog); exit(1); glValidateProgram(ShaderProgram); glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success); if (!Success) glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorL
21、og); fprintf(stderr, "Invalid shader program: '%s'n", ErrorLog); exit(1); glUseProgram(ShaderProgram); gWorldLocation = glGetUniformLocation(ShaderProgram, "gWorld"); assert(gWorldLocation != 0xFFFFFFFF);int main(int argc, char* argv) glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA); glutInitWindowSize(1024, 768); glutInitWindowPosition(100, 100); glutCreateWindow("Tutorial 11");
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 《液面變化專題》課件
- 《零售專業(yè)術(shù)語》課件
- 《鋼筋平法配法計算》課件
- 薪酬管理的創(chuàng)新與優(yōu)化
- 數(shù)字化轉(zhuǎn)型的挑戰(zhàn)與人力資源管理的應對策略
- 《零售分銷》課件
- 《勾股定理的逆定理》課件
- 《明龍骨吊頂工程》課件
- 《濕地生態(tài)系統(tǒng)》課件
- 21古詩詞三首長相思 說課稿2024-2025學年統(tǒng)編版語文五年級上冊
- 呼吸科護理組長述職報告
- 【歷史】秦漢時期:統(tǒng)一多民族國家的建立和鞏固復習課件-2024-2025學年統(tǒng)編版七年級歷史上冊
- 社區(qū)中心及衛(wèi)生院65歲及以上老年人健康體檢分析報告模板
- 化工過程安全管理導則AQT 3034-2022知識培訓
- 2024電力建設(shè)工程質(zhì)量問題通病防止手冊
- 大學生就業(yè)指導教學-大學生就業(yè)形勢與政策
- 第五講鑄牢中華民族共同體意識-2024年形勢與政策
- 隧道危險源清單
- 中華人民共和國學前教育法
- 2024年貴州公務員考試申論試題(B卷)
- 解剖臺項目運營指導方案
評論
0/150
提交評論