国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

【連載】現(xiàn)代OpenGL介紹(五)

發(fā)布時間:2014-7-22 11:38    發(fā)布者:eechina
關(guān)鍵詞: OpenGL
現(xiàn)在在我們的"hello world"程序中,我們已經(jīng)加載了我們的緩沖和紋理,并且編譯和鏈接了我們的著色器程序。終于到最后一步了--讓我們來渲染我們的圖片。

渲染作業(yè)綜述

渲染可能需要很多的參數(shù)。除了所有的緩沖,紋理,著色器,以及它所涉及到的uniform參數(shù),還有許多的其它控制渲染作業(yè)的設(shè)置我沒提到。OpenGL的方法是將這些設(shè)置做成了一個狀態(tài)機(jī),而不是提供一個完整的帶所有標(biāo)記作為參數(shù)的"draw"函數(shù),或者一個需要你去填充各個域的結(jié)構(gòu)體。當(dāng)你使用glBindTexture,glBindBuffer以及類似的方法綁定一個對象的時候,你不僅是使這些對象可以修改,你還將它們綁定到了當(dāng)前渲染作業(yè)的狀態(tài)。并且有狀態(tài)操作函數(shù)可以設(shè)置當(dāng)前著色器,賦值到uniform參數(shù)和描述頂點(diǎn)數(shù)組的結(jié)構(gòu)。當(dāng)你最后使用glDrawElements將一個作業(yè)提交時,OpenGL取當(dāng)前狀態(tài)機(jī)的一個快照并將它添加到GPU的命令隊列,它將在當(dāng)GPU可用時被執(zhí)行。同時,你可以改變OpenGL狀態(tài)以及將更多任務(wù)加到隊列中,而不用等待之前的作業(yè)完成。一旦你將作業(yè)排隊完畢,你可以讓窗口系統(tǒng)"切換緩沖",這個操作將會等待所有的排隊作業(yè)完成然后將結(jié)果顯示在窗口中。

讓我們寫一些代碼設(shè)置渲染作業(yè)狀態(tài):

激活著色器程序并賦值uniform

static void render(void)
{
glUseProgram(g_resources.program);

我們首先通過傳遞鏈接的程序?qū)ο蟮拿纸oglUseProgram來激活我們的著色器對象。一旦程序激活,我們可以開始對我們的uniform變量進(jìn)行賦值。如果你回憶下我們的片元著色器的代碼,我們需要給float fade_factor和一個叫做textures的sampler2D數(shù)組進(jìn)行賦值。

glUniform1f(g_resources.uniforms.fade_factor, g_resources.fade_factor);
OpenGL提供了一組glUniform*函數(shù)用于給uniform變量賦值,其中每一個對應(yīng)GLSL程序中的一種uniform變量類型。這些函數(shù)都是glUniform{dim}{type}的形式,其中dim表示vector類型的大小(int或float的uniform是1,vec2是2,等等),type表示組元的類型:要么是i表示integer,要么是f表示float。我們的fade_factor uniform是一個簡單的float,因此我們通過調(diào)用glUniform1f給它賦值,傳入uniform的位置以及新的值作為參數(shù)。

glActiveTexture(GLTEXTURE0); glBindTexture(GLTEXTURE2D, gresources.textures[0]); glUniform1i(g_resources.uniforms.textures[0], 0);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, g_resources.textures[1]);
glUniform1i(g_resources.uniforms.textures[1], 1);

將紋理賦值給samplers有一點(diǎn)點(diǎn)復(fù)雜。GPU只有數(shù)量有限的紋理單元可以提供給紋理數(shù)據(jù)給渲染作業(yè)。我們必須將我們的紋理對象綁定到這些紋理單元,然后將紋理單元的索引賦值給我們的sampler uniform變量,如果它們是int的話。我們綁定的GL_TEXTURE_*目標(biāo)名必須對應(yīng)于sampler uniform的類型。在這里,GLTEXTURE2D對應(yīng)于我們的textures變量使用的sample2D類型。glActiveTexture設(shè)置當(dāng)前活躍的紋理單元。glBindTexture其實(shí)是使用活躍紋理單元作為一個隱含參數(shù)(其它的紋理對象操作的函數(shù)像glTexParameteri和glTexImage2D也是操作綁定到當(dāng)前活躍的紋理單元的紋理)。一旦我們綁定紋理單元之后,我們可以使用glUniform1i對它的索引進(jìn)行賦值。

設(shè)置紋理數(shù)組

glBindBuffer(GL_ARRAY_BUFFER, g_resources.vertex_buffer);
glVertexAttribPointer(
g_resources.attributes.position, /* attribute */
2, /* size */
GL_FLOAT, /* type */
GL_FALSE, /* normalized? */
sizeof(GLfloat)*2, /* stride */
(void*)0 /* array buffer offset */
);
glEnableVertexAttribArray(g_resources.attributes.position);

接下來,我們告訴OpenGL我們使用的紋理數(shù)組的格式。我們通過調(diào)用glVertexAttribPointer設(shè)置每一個頂點(diǎn)屬性格式,這個函數(shù)告訴OpenGL在渲染時從頂點(diǎn)數(shù)組中讀出屬性值。glVertexAttribPointer使用屬性位置,關(guān)聯(lián)的屬性變量的元素大小和類型(對于我們的position屬性,大小為2,類型為GLFLOAT),屬性值之間的字節(jié)數(shù)(稱為stride),以及當(dāng)前第一個屬性在當(dāng)前綁定的GLARRAY_BUFFER中的偏移作為參數(shù)。由于歷史原因,offset是作為一個指針傳遞的,但它實(shí)際上被當(dāng)作integer值使用,因此我們傳遞一個整形的0并傳換為void*類型。



在我們這里,我們的頂點(diǎn)數(shù)組只由單個vec2 position屬性組成;如果我們有多個屬性值,屬性值可以是交錯的,像是一個結(jié)構(gòu)體數(shù)組,或者是分別存儲在不同的數(shù)組里。靈活的glVertexAttribPointer讓我們可以選擇這兩種情況中每個屬性如何選擇stride和offset去適應(yīng)它們的存儲布局;改變GLARRAYBUFFER綁定不影響由我們已經(jīng)設(shè)置過的屬性數(shù)組指針使用的緩沖。

(上面我沒有提到的normalized?參數(shù)是跟頂點(diǎn)數(shù)組中的整型的數(shù)組一起使用的。如果為true,元素將從它們的integer類型的范圍進(jìn)行映射,比如0-255用于unsigned byte,0.0-1.0用于符點(diǎn)數(shù),像圖片中的顏色組分。如果為false,它們的整型值將被保存。像我們這樣使用的已經(jīng)是符點(diǎn)數(shù)的元素,該參數(shù)沒有任何作用。)

提交渲染作業(yè)

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_resources.element_buffer);
glDrawElements(
GL_TRIANGLE_STRIP, /* mode */
4, /* count */
GL_UNSIGNED_SHORT, /* type */
(void*)0 /* element array buffer offset */
);

glDrawElements是設(shè)置繪圖管線動作為函數(shù)。我們告訴它我們使用哪種三種角組裝模式,使用多少頂點(diǎn)組裝三角形,我們元素數(shù)組的組成類型,以及當(dāng)前綁定的第一個要渲染的元素在GLELEMENTARRAY_BUFFER內(nèi)部的偏移,這也是一個實(shí)際上是integer的指針參數(shù)。它將獲取指向的元素數(shù)組的索引,將它們跟當(dāng)前綁定的著色器程序,uniform變量,紋理單元,我們剛剛設(shè)置的頂點(diǎn)屬性指針集合在一起,綁定成為一個渲染作業(yè),并將這個作業(yè)放到GPU隊列中。

清理工作

glDisableVertexAttribArray(g_resources.attributes.position);

"Always leave things the way you found them",Bill Brasky曾經(jīng)建議過。OpenGL狀態(tài)機(jī)的缺點(diǎn)就是所有的綁和設(shè)置都是全局地持久的,即使調(diào)用glDrawElements之后。這意味著我們必須注意整個程序生命期中,我們的OpenGL代碼是怎樣和其它的OpenGL代碼交互的。盡管在這個程序中還沒有其它的OpenGL代碼與之交互,我們?nèi)匀粦?yīng)該養(yǎng)成一個好的習(xí)慣。尤其要注意頂點(diǎn)屬性:在涉及到多個著色器程序和多個頂點(diǎn)數(shù)組的復(fù)雜程序中,不正確地使用頂點(diǎn)屬性可能會造成glDrawElements去使用無效的GPU數(shù)據(jù),導(dǎo)致錯誤的輸出或者段錯誤。只在需要的時候去使用頂點(diǎn)數(shù)組是一個好習(xí)慣。這里,我們對position禁用頂點(diǎn)屬性。

你也可能會想,每次渲染時,我們重新綁定了所有相同的對象,設(shè)置了所有的相同的uniform值(除了fade_factor),并且重新激活了所有的同樣的頂點(diǎn)屬性。如果狀態(tài)設(shè)置在glDrawElements調(diào)用之間是持久的,從技術(shù)上講在進(jìn)入glutMainLoop之后,我們可以幾乎完全沒必要要每幀都進(jìn)行設(shè)置,并且每次渲染只更新混色因子并調(diào)用glDrawElements。但是,在你每次期望的時候都設(shè)置好狀態(tài),這是個好主意。

顯示我們完成的場景


glutSwapBuffers();
}

我們只有一個渲染作業(yè)需要等待,因此當(dāng)我們提交作業(yè)并清理之后,我們可以立即執(zhí)行同步。GLUT函數(shù)glutSwapBuffers等待所有的運(yùn)行中的作業(yè)完成,然后用我們的雙緩沖的framebuffer交換顏色緩沖,在下一幀時將當(dāng)前可見的緩沖移到要渲染的"后面",然后將我們剛剛渲染好的圖象推到前面,在我們的窗口中顯示新渲染好的場景。我們的渲染流程完成了!

讓場景動起來


static void update_fade_factor(void)
{
int milliseconds = glutGet(GLUT_ELAPSED_TIME);
g_resources.fade_factor = sinf((float)milliseconds * 0.001f) * 0.5f + 0.5f;
glutPostRedisplay();
}

為了讓圖片動起來,我們的glutIdleFunc回調(diào)函數(shù)不停地更新我們給fadefactor賦值的uniform。GLUT維護(hù)一個毫秒級的計時器,我們可以使用glutGet(GLUTELAPSED_TIME)訪問到;我們使用標(biāo)準(zhǔn)C語言的sinf函數(shù)來得到一個平滑的,周期性的0到1之前的數(shù)。每次我們更新混色因子,我們調(diào)用glutPostRedisplay,這會強(qiáng)制我們的渲染回調(diào)函數(shù)去執(zhí)行,更新窗口。

再次編譯運(yùn)行程序


這是我們最后一次編譯和運(yùn)行整個程序,使用所有我們的新的代碼。構(gòu)建和執(zhí)行的命令看起來很像上次我們構(gòu)建的空函數(shù)版本,但是這次,你將編譯真正的hello-gl.c和util.c源文件。如果你使用Makefiles,你可以這樣編譯默認(rèn)的目標(biāo):

make -f Makefile.MacOSX # or Makefile.Unix or Makefile.Mingw
nmake /f Nmakefile.Windows

一旦編譯后,程序假定它的圖片和著色器資源是在當(dāng)前目錄的,因此最好從包含可執(zhí)行文件,圖片,著色器代碼的目錄用命令行運(yùn)行它。最后我們終于可以曬一下我們的成果了:



結(jié)論

必須承認(rèn)從一個簡單的"hello world"已經(jīng)起了很遠(yuǎn)了。但是這里我們所創(chuàng)建的框架是非常靈活的;你可以替換成你自己的圖片并調(diào)整著色器代碼在圖片取樣之前對它們進(jìn)行變換或者進(jìn)一步處理,都不需要重新編譯C。下一章中,我們將繼續(xù)頂點(diǎn)著色器來展示基本的3D變換和投影。

如果你很感興趣,這個時候你也可以停下來,自己看一下OpenGL標(biāo)準(zhǔn),注意,OpenGL 2標(biāo)準(zhǔn)仍然包含了很多我沒有提到的過時的特性。我強(qiáng)烈推薦你看OpenGL 3.1之后的版本,一定要看看核心標(biāo)準(zhǔn)部分而不是為了兼容的部分。盡管OpenGL 3之后相對于OpenGL 2添加了很多新的特征,所有的OpenGL 2中的基本的API也仍然是新版本的基本部分。

OpenGL ES 2也是值得一看的。它大部分由我這里提到的OpenGL 2之后的一個子集;所有的我前面提到的OpenGL API也都是在OpenGL ES 2中的。OpenGL ES還對移動平臺添加了一些額外的特性,比如浮點(diǎn)數(shù)支持以及離線著色器編譯,這是桌面版標(biāo)準(zhǔn)中所有提供的。如果你想試一下OpenGL ES開發(fā),它是Android NDK和iPhone SDK的部分。在Windows下,Google的ANGLE項目還提供一個OpenGL ES2在DirectX上的實(shí)現(xiàn)。
本文地址:http://www.qingdxww.cn/thread-131050-1-1.html     【打印本頁】

本站部分文章為轉(zhuǎn)載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀點(diǎn)和對其真實(shí)性負(fù)責(zé);文章版權(quán)歸原作者及原出處所有,如涉及作品內(nèi)容、版權(quán)和其它問題,我們將根據(jù)著作權(quán)人的要求,第一時間更正或刪除。
您需要登錄后才可以發(fā)表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區(qū)
  • Dev Tool Bits——使用MPLAB® Discover瀏覽資源
  • Dev Tool Bits——使用條件軟件斷點(diǎn)宏來節(jié)省時間和空間
  • Dev Tool Bits——使用DVRT協(xié)議查看項目中的數(shù)據(jù)
  • Dev Tool Bits——使用MPLAB® Data Visualizer進(jìn)行功率監(jiān)視
  • 貿(mào)澤電子(Mouser)專區(qū)
關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權(quán)所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 国产国语在线播放视频 | 天天综合久久久网 | 久热精品香蕉在线视频 | 福利一区二区三区视频午夜观看 | 免费福利在线观看 | 日本韩国高清 | 成人亚洲欧美日韩在线 | 超级乱淫视频播放日韩 | 国产亚洲精品网站 | 欧美国产在线一区 | 制服师生一区二区三区在线 | 亚洲天堂视频在线观看免费 | 日韩在线不卡一区在线观看 | 四虎影视在线看免费 720p | 亚洲大尺度在线观看 | 中文精品99久久国产 | h色视频在线 | 四虎国产精品永久在线播放 | 视频在线观看91 | 亚洲国产精品久久久久久网站 | 国产亚洲亚洲精品777 | 日韩高清片 | 最近中文字幕2019视频1 | 国产成人精品高清在线观看99 | 国内自拍视频在线播放 | 亚洲欧美日本国产一区二区三区 | 午夜视频免费 | 中文精品久久久久国产网址 | 四虎影视永久免费视频观看 | 亚洲精品国产精品国自产网站 | 色免费在线观看 | 日韩精品1区 | 日韩午夜免费视频 | 日韩精品一区二区三区在线观看l | 最新色网站 | 91入口 | 91蝌蚪在线视频 | 久久精品蜜芽亚洲国产a | 成人欧美在线观看 | 好爽毛片一区二区三区四 | 久久91亚洲精品中文字幕 |