




已閱讀5頁(yè),還剩4頁(yè)未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
一步步學(xué)OpenGL復(fù)合變換背景在前面的幾個(gè)教程中我們建立了幾種基本圖形變換是我們能靈活的將物體移動(dòng)到3d世界的任意地方。我們還有很多要學(xué)(相機(jī)控制和透視投影等等),但你可能也已經(jīng)想到,復(fù)合的圖形變換也是必的。多數(shù)情況下,你會(huì)想縮放物體來(lái)和3d世界相適應(yīng),旋轉(zhuǎn)物體到合適的方向,移動(dòng)物體到某個(gè)地方等等。到現(xiàn)在我們已經(jīng)實(shí)踐了每一次的單一圖形變換。為了實(shí)現(xiàn)上面一系列的變換,我們需要對(duì)頂點(diǎn)位置左乘第一個(gè)變換矩陣,然后得到的結(jié)果再左乘下一個(gè)變換矩陣等等,將所有變換矩陣都左乘頂點(diǎn)位置之后實(shí)現(xiàn)多個(gè)變換。一種笨辦法就是在shader中應(yīng)用每一個(gè)變換矩陣實(shí)現(xiàn)所有的變換,但這樣很低效,因?yàn)閷?duì)于所有頂點(diǎn)這些矩陣都是一樣的,只有頂點(diǎn)的位置發(fā)生變化,這樣要不斷重復(fù)對(duì)每個(gè)頂點(diǎn)位置進(jìn)行這一系列的矩陣相乘操作。幸運(yùn)的是線性代數(shù)中有一些規(guī)則可以說(shuō)讓我們的生活更加簡(jiǎn)易,他告我們對(duì)于給定的一組矩陣M0Mn和一個(gè)向量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這意味著我們可以一次性計(jì)算N,然后把它作為一致變量傳給shader和每一個(gè)頂點(diǎn)位置相乘完成所有的變換,這個(gè)只需要GPU對(duì)每個(gè)頂點(diǎn)進(jìn)行一次矩陣/向量相乘操作。當(dāng)計(jì)算N的時(shí)候怎樣安排每個(gè)變換矩陣的先后順序呢?你首先要記住向量最開(kāi)始先是被最右邊的矩陣左乘的(上面的例子就是M0)。然后向量被從右邊到左邊所有的變換矩陣所變換。在3d圖形中你通常希望先縮放物體,然后旋轉(zhuǎn)它,然后平移,之后再進(jìn)行camera轉(zhuǎn)換最后投影到2d屏幕。讓我們先看先旋轉(zhuǎn)后平移會(huì)怎樣:可以看出,如果先平移物體的話會(huì)很難來(lái)設(shè)置物體的最終位置,因?yàn)楫?dāng)你將物體遠(yuǎn)離坐標(biāo)原點(diǎn)后,再旋轉(zhuǎn)物體會(huì)同時(shí)造成物體的平移效果(是繞原點(diǎn)旋轉(zhuǎn),而不是繞自身旋轉(zhuǎn)了),這是我們希望能避免的。通過(guò)先旋轉(zhuǎn)后移動(dòng)可以避免這兩個(gè)操作的相互依賴性,這也是盡量圍繞原點(diǎn)對(duì)稱建模的原因,那樣當(dāng)你縮放或者旋轉(zhuǎn)物體不會(huì)產(chǎn)生副作用,縮放和旋轉(zhuǎn)后物體依然保持和之前一樣對(duì)稱。源代碼詳解(1) #define ToRadian(x) (x) * M_PI / 180.0f)#define ToDegree(x) (x) * 180.0f / M_PI)在這個(gè)教程中我們開(kāi)始要使用具體的角度值了。標(biāo)準(zhǔn)C語(yǔ)言庫(kù)中三角函數(shù)使用弧度值作為參數(shù)。上面的宏定義可以實(shí)現(xiàn)角度和弧度之間的轉(zhuǎn)換。(2)inline Matrix4f operator*(const Matrix4f& Right) const Matrix4f Ret; for (unsigned int i = 0 ; i 4 ; 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é)果矩陣的值依次是左邊矩陣每一行和右邊矩陣對(duì)應(yīng)每一列的點(diǎn)乘。這個(gè)矩陣相乘的操作對(duì)實(shí)現(xiàn)管線類十分重要。(3)class Pipeline public: Pipeline() . void Scale(float ScaleX, float ScaleY, float ScaleZ) . 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;管線類抽象出了一個(gè)物體的所有變換的數(shù)據(jù)信息?,F(xiàn)在有3個(gè)私有vector成員變量分別來(lái)存儲(chǔ)物體在世界空間中的縮放比例,位置和每個(gè)像素的旋轉(zhuǎn)角度。另外有接口函數(shù)來(lái)設(shè)置他們的值,以及可以獲取表示所有變換最終的復(fù)合變換矩陣。(4)const Matrix4f* Pipeline:GetTrans() Matrix4f ScaleTrans, RotateTrans, TranslationTrans; InitScaleTransform(ScaleTrans); InitRotateTransform(RotateTrans); InitTranslationTransform(TranslationTrans); m_transformation = TranslationTrans * RotateTrans * ScaleTrans; return &m_transformation;這個(gè)函數(shù)初始化了那三個(gè)獨(dú)立的變換矩陣并把它們一個(gè)一個(gè)的相乘然后返回最終的積。注意相乘的順序是和上面描述的一樣固定死的。如果你想更靈活一點(diǎn)你可以設(shè)置一個(gè)定義變換順序的位掩碼。還要注意它總是將最終的復(fù)合變換矩陣作為一個(gè)陳成員變量。你可以通過(guò)檢查標(biāo)記來(lái)做優(yōu)化,當(dāng)上一次的變換函數(shù)沒(méi)有任何變化時(shí)可以返回上一次存儲(chǔ)的變換矩陣,避免重復(fù)計(jì)算。這個(gè)函數(shù)按照之前教程的內(nèi)容講的使用私有方法來(lái)產(chǎn)生不同的變換。在下一個(gè)教程中這個(gè)類還將被擴(kuò)展,來(lái)進(jìn)行相機(jī)控制和透視變換。(5)Pipeline p;p.Scale(sinf(Scale * 0.1f), sinf(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();上面的語(yǔ)句是渲染函數(shù)中做的變化。我們實(shí)例化一個(gè)pipeline管線類對(duì)象,初始化配置好之后傳遞給shader。通過(guò)調(diào)整參數(shù)來(lái)看最終圖像的效果。示例Demo用到了matrix4x4頭文件中的擴(kuò)展工具函數(shù);#include #include #include #include #include #include ogldev_util.h#include ogldev_pipeline.hGLuint VBO;GLuint IBO;GLuint gWorldLocation;const char* pVSFileName = shader.vs;const char* pFSFileName = shader.fs;static void RenderSceneCB() glClear(GL_COLOR_BUFFER_BIT); static float Scale = 0.0f; Scale += 0.001f; / 實(shí)例化一個(gè)pipeline管線類對(duì)象,初始化配置好之后傳遞給shader Pipeline p; p.Scale(sinf(Scale * 0.1f), sinf(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.GetWorldTrans(); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, VBO); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(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 = 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 void 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* pShaderText, 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); glCompileShader(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: %sn, ShaderType, InfoLog); exit(1); glAttachShader(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); ; AddShader(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, sizeof(ErrorLog), NULL, ErrorLog); fprintf(stderr, Error linking ader program: %sn, ErrorLog); exit(1); glValidateProgram(ShaderProgram); glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success); if (!Success) glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog); fprintf(stderr, Invalid shader program: %sn, 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 1
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024-2025學(xué)年海興縣三下數(shù)學(xué)期末達(dá)標(biāo)檢測(cè)試題含解析
- 深圳大學(xué)《面向?qū)ο蟮南到y(tǒng)分析與設(shè)計(jì)》2023-2024學(xué)年第二學(xué)期期末試卷
- 2025福建福州左臺(tái)置業(yè)有限公司項(xiàng)目建設(shè)合同制人員招聘33人筆試參考題庫(kù)附帶答案詳解
- 湖北文理學(xué)院理工學(xué)院《信息檢索與論文寫(xiě)作》2023-2024學(xué)年第二學(xué)期期末試卷
- 徐州幼兒師范高等??茖W(xué)校《攝像實(shí)務(wù)》2023-2024學(xué)年第二學(xué)期期末試卷
- 沈陽(yáng)城市建設(shè)學(xué)院《歷史學(xué)課程教學(xué)論》2023-2024學(xué)年第二學(xué)期期末試卷
- 蘭州工商學(xué)院《計(jì)算機(jī)組成實(shí)驗(yàn)》2023-2024學(xué)年第二學(xué)期期末試卷
- 萍鄉(xiāng)衛(wèi)生職業(yè)學(xué)院《建筑師執(zhí)業(yè)知識(shí)與設(shè)計(jì)管理》2023-2024學(xué)年第二學(xué)期期末試卷
- 海南政法職業(yè)學(xué)院《電子技術(shù)》2023-2024學(xué)年第二學(xué)期期末試卷
- 伊犁師范大學(xué)《綠色制造技術(shù)(雙語(yǔ))》2023-2024學(xué)年第二學(xué)期期末試卷
- 胸椎小關(guān)節(jié)紊亂診斷與治療-課件
- 四川省德陽(yáng)市各縣區(qū)鄉(xiāng)鎮(zhèn)行政村村莊村名居民村民委員會(huì)明細(xì)及行政區(qū)劃代碼
- Unit1Developingideaslittlewhitelies課件-高中英語(yǔ)外研版必修第三冊(cè)
- Unit 2 Listening and speaking 課件-高中英語(yǔ)人教版(2019)選擇性必修第二冊(cè)
- (參考)食品加工操作流程圖
- 員工面試登記表
- 鋼棧橋施工方案型鋼
- PySide學(xué)習(xí)教程
- 事業(yè)單位綜合基礎(chǔ)知識(shí)考試題庫(kù) 綜合基礎(chǔ)知識(shí)考試題庫(kù).doc
- 譯林初中英語(yǔ)教材目錄
- 物業(yè)交付后工程維修工作機(jī)制
評(píng)論
0/150
提交評(píng)論