日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【Modern OpenGL】第一个三角形

發(fā)布時(shí)間:2023/12/10 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Modern OpenGL】第一个三角形 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
>說明:跟著learnopengl的內(nèi)容學(xué)習(xí),不是純翻譯,只是自己整理記錄。>強(qiáng)烈推薦原文,無論是內(nèi)容還是排版。 [原文鏈接](http://learnopengl.com/#!Getting-started/OpenGL)本文地址:http://blog.csdn.net/aganlengzi/article/details/50354237

并不簡單的三角形繪制

在OpenGL的世界中,一切都是在三維空間中的,但是屏幕和窗口是二維的像素?cái)?shù)組。所以O(shè)penGL的一大工作就是將三維坐標(biāo)轉(zhuǎn)換為適合屏幕顯示的二維像素。這個(gè)把三維坐標(biāo)轉(zhuǎn)換為二維坐標(biāo)的過程是由OpenGL的圖形渲染流水線來管理的。這個(gè)圖形渲染流水線分為兩大部分:首先是將三維坐標(biāo)轉(zhuǎn)換為二維坐標(biāo);其次是鍵二維坐標(biāo)轉(zhuǎn)換為真正的有顏色值的像素。在本次教程中,我們將會(huì)簡單地討論這個(gè)圖形渲染流水線以及我們應(yīng)該怎樣使用它來幫助我們創(chuàng)建一些酷炫的像素出來。

注意一個(gè)二維坐標(biāo)和一個(gè)像素點(diǎn)是不同的。一個(gè)二維坐標(biāo)是一個(gè)點(diǎn)在二維空間中的精確表示,但是一個(gè)二維的像素點(diǎn)是一個(gè)二維空間中的點(diǎn)在屏幕分辨率的限制下的一個(gè)近似表示。

圖形渲染流水線以一組三維坐標(biāo)為輸入,把它們轉(zhuǎn)換成屏幕上著色的二維像素點(diǎn)。圖形渲染流水線又可以分成許多步驟,每個(gè)步驟都是以前面步驟的輸出作為當(dāng)前步驟的輸入。每一個(gè)步驟都是專用的,它們具有特定的功能,這方便了并行執(zhí)行。因?yàn)檫@種并行特性,當(dāng)今顯卡基本上都包含成千上萬個(gè)小的處理核心,這些核心幫助我們在GPU圖形渲染流水線中的每個(gè)步驟中利用小的程序來快速處理數(shù)據(jù)。而這些在每個(gè)核心上面跑的小程序就叫做著色程序(shaders)。

在這些shader中,有一些是可以被開發(fā)者配置的,這些可配置的shader允許我們用自己寫的shader來替換默認(rèn)的shader。這給了我們對這個(gè)流水線的某些部分更細(xì)粒度的控制權(quán),因?yàn)樗鼈兪窃贕PU上運(yùn)行的,這或許也能夠幫助我們節(jié)省寶貴的CPU時(shí)間。shader是用GLSL(OpenGL Shading Language,簡稱GLSL)語言開發(fā)的,我們將在下個(gè)教程中了解更多關(guān)于GLSL的知識。

下面這幅圖展示的是對圖形渲染管線所有階段的一個(gè)抽象表示,其中藍(lán)色的部分代表我們可以注入自己的shader,應(yīng)該就是可以自己配置的意思。這里的圖借鑒了

如你所見,這個(gè)圖形渲染管線中包含了很多階段,每個(gè)階段完成從頂點(diǎn)數(shù)據(jù)項(xiàng)最終顯示像素點(diǎn)的一部分特定的工作。我們將會(huì)以一個(gè)簡化的方式簡短地解釋其中的每個(gè)階段,目的是讓你有一個(gè)對這個(gè)流水線工作方式的整體把握。

作為輸入,我們把數(shù)組中能構(gòu)成一個(gè)三角形的三個(gè)三維坐標(biāo)值(稱作頂點(diǎn)數(shù)據(jù),Vertex Data)傳遞進(jìn)這個(gè)流水線;頂點(diǎn)數(shù)據(jù)實(shí)際上就是所有頂點(diǎn)的集合,而每個(gè)頂點(diǎn)實(shí)際上就是每個(gè)三維坐標(biāo)系中表示這個(gè)頂點(diǎn)的數(shù)據(jù)。實(shí)際上,我們用于表示一個(gè)點(diǎn)的數(shù)據(jù)中可以包含我們想要包含的屬性,但是為了簡化起見,在本例中,我們假設(shè)每個(gè)頂點(diǎn)只包含這個(gè)頂點(diǎn)的三維坐標(biāo)和頂點(diǎn)的顏色值。

為了讓OpenGL知道你想用這些頂點(diǎn)數(shù)據(jù)或者顏色值繪制什么圖形,你需要指定你想用這些數(shù)據(jù)繪制的圖形類型:是需要用它們繪制一些獨(dú)立的點(diǎn),還是需要用它們繪制三角形,或者是用它們繪制一條長長的線?點(diǎn),三角形或者線,這些稱作圖元,是在任何繪制命令調(diào)用前需要告訴OpenGL的,也只有這樣,OpenGL才知道在下一個(gè)狀態(tài)用繪制命令和給定的數(shù)據(jù)繪制什么。指定的方式是通過前面說的狀態(tài)設(shè)置函數(shù)完成的,這在后面具體用到的時(shí)候會(huì)說明。而OpenGL支持的圖元類型永宏表示,比如GL_POINTS,GL_TRIANGLES和GL_LINE_STRIP。

好的,以上圖為例,假設(shè)我們已經(jīng)指定了要繪制三角形,并且已經(jīng)輸入了頂點(diǎn)數(shù)據(jù)(包含三個(gè)頂點(diǎn)的位置坐標(biāo)和顏色值),下面真正進(jìn)入圖形渲染流水線:

流水線的第一階段是頂點(diǎn)處理器,它以單獨(dú)的頂點(diǎn)(在本例中包含位置坐標(biāo)和顏色值)作為輸入,完成的主要功能是將頂點(diǎn)的三維坐標(biāo)轉(zhuǎn)換成另一種三維坐標(biāo)(后面具體會(huì)講到),還有就是對頂點(diǎn)的屬性做一些基本的處理。

圖元裝配階段,以所有頂點(diǎn)處理器處理過的的頂點(diǎn)為輸入(如果在前面指定的繪制的內(nèi)容是GL_POINTS的話,那么就以單個(gè)頂點(diǎn)作為輸入),生成一個(gè)圖元并且根據(jù)圖元的形狀放置所有的頂點(diǎn)。在本例中就是構(gòu)成一個(gè)三角形圖元,而且將這個(gè)三角形的各個(gè)頂點(diǎn)放到該放的位置。

圖元裝配的輸入作為幾何處理器的輸入。幾何shader以形成圖元的頂點(diǎn)幾何為輸入,它能夠生成新的頂點(diǎn)形成新的圖元(不僅限于前面指定的圖元,比如像本例中的三角形)。在本例中,它從給定的三角形(圖元裝配階段的輸出)中又生成了一個(gè)三角形。

幾何處理器的輸出被傳遞給光柵化階段作為輸入。光柵化階段完成圖元和最終要顯示屏幕的對應(yīng)像素之間的映射,它生成片段處理器用到的片段。在將這些片段輸出到片段處理器之前,裁剪被首先執(zhí)行。裁剪操作將所有超出顯示范圍的片段都去除,這樣可以提高性能。

在OpenGL中,一個(gè)片段就是OpenGL渲染一個(gè)像素點(diǎn)需要的所有數(shù)據(jù)。

片段處理器最主要的作用是計(jì)算像素點(diǎn)最終的顏色,這個(gè)階段也是所有高級OpenGL效果施展的地方。通常,片段中包含3D場景的數(shù)據(jù)(比如說光照、陰影和光照顏色等等),這些數(shù)據(jù)被用來計(jì)算出最終的像素顏色值。

在所有相關(guān)的顏色值都被確定后,最終的對象將會(huì)被傳遞到下一個(gè)階段,我們稱其為alpha通道測試和混合階段。這個(gè)階段檢查片段的深度值和模板值(我們后面會(huì)了解到),并且用他們來檢查這些生成的片段是否在其它對象的前面或者后面,如果在其它對象的后面,即被其它對象遮擋,那么這個(gè)片段就會(huì)被裁減掉。這個(gè)階段也會(huì)檢查alpha值(alpha值定義了一個(gè)對象的透明度)并且進(jìn)行對象的混合操作(根據(jù)透明度的不同生成不同的效果)。所以即使一個(gè)像素的顏色值是在片段處理器階段就生成的,但是到最終顯示的時(shí)候,還是有可能完全不同(因?yàn)樵谶@個(gè)階段還會(huì)和其它對象進(jìn)行相互作用,比如透明遮擋等等)。

如你所見,圖形渲染流水線是相當(dāng)復(fù)雜的,而且包含了很多可配置的部分(圖中藍(lán)色著色的階段)。但是,我們大部分只關(guān)心頂點(diǎn)和片段處理器。幾何處理器雖然是可選的,但是經(jīng)常被設(shè)置為默認(rèn)的。

在現(xiàn)代OpenGL中,我們需要自己至少定義一個(gè)頂點(diǎn)處理器(處理程序,shader)和一個(gè)片段處理器。因?yàn)樵贕PU中沒有默認(rèn)的頂點(diǎn)或者片段處理程序供我們選擇。基于此,通常開始學(xué)習(xí)現(xiàn)代OpenGL是非常困難的,因?yàn)閮H僅是渲染我們的第一個(gè)三角形都需要大量的相關(guān)知識。但是一旦你成功渲染了你的第一個(gè)三角形,你將會(huì)學(xué)到更多的OpenGL圖形編程知識。

下面我們就來渲染我們的第一個(gè)三角形吧~

##頂點(diǎn)輸入開始繪制之前我們首先要給OpenGL一些頂點(diǎn)數(shù)據(jù)。OpenGL是一個(gè)三維圖形庫,所以所有的坐標(biāo)都應(yīng)該是三維的,即包含x,y和z坐標(biāo)。OpenGL不會(huì)簡單地將你的三維坐標(biāo)轉(zhuǎn)換成屏幕上的二維像素。前面已經(jīng)提到過,OpenGL中的坐標(biāo)是標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系,即在x,y和z方向上都是-1到1之間的立方體。所有在這個(gè)標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系中的坐標(biāo)才是可以顯示在屏幕上的,而在這個(gè)標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系之外的坐標(biāo)都不可能顯示。因?yàn)槲覀兿胍秩疽粋€(gè)三角形。所以我們總共需要提供構(gòu)成這個(gè)三角形的三個(gè)點(diǎn)的三維坐標(biāo)值。我們利用一個(gè)GLfloat類型的數(shù)組定義他們在標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系的可見區(qū)域。 GLfloat vertices[] = {-0.5f, -0.5f, 0.0f,0.5f, -0.5f, 0.0f,0.0f, 0.5f, 0.0f };

因?yàn)镺penGL在三維空間中進(jìn)行處理,但是我們希望渲染的是一個(gè)二維的三角形,所以我們將三個(gè)頂點(diǎn)的坐標(biāo)值中的z值全部都設(shè)置為0.0。這樣的能夠使三角形的深度之保持一致,看上去像一個(gè)二維圖形一樣。>####標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系 Normalized Device Coordinates (NDC)當(dāng)你的頂點(diǎn)坐標(biāo)在頂點(diǎn)處理器中處理過,它們就應(yīng)該在標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系中。標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系是一個(gè)小的立方體空間中,這個(gè)立方體的三個(gè)維度上(x,y和z)都在-1到1之間。任何在這個(gè)范圍之外的坐標(biāo)都不會(huì)在屏幕上顯示。下圖中可見在標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系統(tǒng)我們上面定義的三角形(先不考慮z軸,可以認(rèn)為z軸是垂直于紙面的)。


通常的屏幕坐標(biāo)系的原點(diǎn)是在屏幕的左上角上,而且y正軸是自原點(diǎn)垂直向下的。在標(biāo)準(zhǔn)化坐標(biāo)系中卻不同,其原點(diǎn)在正中,y軸垂直向上。最終你會(huì)希望你繪制的所有的對象的坐標(biāo)都在這個(gè)標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系之內(nèi),否則它們不會(huì)被顯示出來。你的標(biāo)準(zhǔn)化設(shè)備坐標(biāo)最終都會(huì)被轉(zhuǎn)換成屏幕坐標(biāo)系中的坐標(biāo)。這個(gè)轉(zhuǎn)化過程是基于在程序中你設(shè)置的glViewport參數(shù)來完成的。生成的屏幕坐標(biāo)系中的坐標(biāo)被轉(zhuǎn)換成片段并輸入到片段處理器。上面我們已經(jīng)完成了三角形頂點(diǎn)數(shù)據(jù)的定義,現(xiàn)在我們想要將這些數(shù)據(jù)作為圖形渲染流水線的第一階段的輸入,也就是頂點(diǎn)處理器的輸入。為此,我們需要在GPU中申請內(nèi)存來存儲(chǔ)這些頂點(diǎn)數(shù)據(jù)、告訴OpenGL應(yīng)該如何解釋這塊內(nèi)存并且指定應(yīng)該如何將這些數(shù)據(jù)發(fā)送到顯卡。之后頂點(diǎn)處理器就可以從內(nèi)存中處理我們指定數(shù)量的頂點(diǎn)了。我們利用所謂的頂點(diǎn)緩存對象(vertex buffer objects,簡稱VBO)來管理這塊內(nèi)存。VBO能夠在GPU的內(nèi)存中存儲(chǔ)大量的頂點(diǎn)。利用這種緩存對象的好處是我們可以一次就發(fā)送大批量的數(shù)據(jù)到顯卡,而不用每次之傳輸一個(gè)頂點(diǎn)。畢竟從CPU向顯卡中傳輸數(shù)據(jù)是非常慢的,所以我們總是找機(jī)會(huì)一次傳輸盡可能多的數(shù)據(jù)。一旦數(shù)據(jù)存儲(chǔ)在顯卡內(nèi)存中,頂點(diǎn)處理器對這些數(shù)據(jù)的訪問可以看成是瞬時(shí)的,這極大提升了頂點(diǎn)處理器的處理速度。VBO是我們在這個(gè)教程中遇到的第一個(gè)OpenGL對象。像OpenGL中的其它對象一樣,它有一個(gè)ID唯一的表示一個(gè)緩沖區(qū),所以我們可以像下面這樣用glGenBuffers創(chuàng)建一個(gè)VBO。

GLuint VBO; glGenBuffers(1, &VBO);
  • 1
  • 2
OpenGL的緩沖區(qū)對象有多種緩沖區(qū)類型,頂點(diǎn)緩存區(qū)對象的緩沖區(qū)類型是GL_ARRAY_BUFFER。我們通過下面的方式使用glBindBuffer將新生成的緩存區(qū)綁定到GL_ARRAY_BUFFER目標(biāo)類型。 glBindBuffer(GL_ARRAY_BUFFER, VBO);
  • 1
此后,我們對任何緩沖區(qū)的調(diào)用(以GL_ARRAY_BUFFER為目標(biāo)類型),都會(huì)被用于當(dāng)前綁定的緩沖區(qū),即VBO。于是我們可以通過調(diào)用glBufferData函數(shù)來將之前定義的頂點(diǎn)數(shù)據(jù)拷貝到這個(gè)緩沖區(qū)內(nèi)存中: glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  • 1
glBufferData函數(shù)負(fù)責(zé)將用戶定義的數(shù)據(jù)拷貝到當(dāng)前綁定的緩沖區(qū)中,它的第一個(gè)參數(shù)是我們想要拷貝進(jìn)數(shù)據(jù)的緩沖區(qū)類型:在本例中頂點(diǎn)緩沖區(qū)對象當(dāng)前被綁定到了GL_ARRAY_BUFFER目標(biāo)類型。第二個(gè)參數(shù)指定了我們想要傳輸進(jìn)緩沖區(qū)的數(shù)據(jù)量大小(以字節(jié)為單位),即使用運(yùn)算符sizeof對我們定義的數(shù)組計(jì)算值。第三個(gè)參數(shù)指定我們想要傳輸?shù)臄?shù)據(jù)。第四個(gè)參數(shù)指定了我們想要讓顯卡怎樣來管理這些給定的數(shù)據(jù)(我感覺是高速顯卡我們可能怎樣操作這些數(shù)據(jù),在其進(jìn)行存儲(chǔ)的時(shí)候,為提高性能或者節(jié)省能耗而“心里有數(shù)”),它有三種形式: GL_STATIC_DRAW: 這些數(shù)據(jù)基本上不會(huì)改變或者極少情況下會(huì)被改變。 GL_DYNAMIC_DRAW: 這些數(shù)據(jù)可能會(huì)經(jīng)常被改變。 GL_STREAM_DRAW: 這些數(shù)據(jù)在每次繪制的時(shí)候都會(huì)被改變。

三角形三個(gè)點(diǎn)的位置數(shù)據(jù)不會(huì)改變,在每次渲染的時(shí)候都保持在原來的位置,所以應(yīng)該被設(shè)置為GL_STATIC_DRAW。舉例來說,如果緩沖區(qū)中的數(shù)據(jù)會(huì)經(jīng)常改變,那么使用GL_DYNAMIC_DRAW或者GL_STREAM_DRAW參數(shù)將會(huì)讓顯卡將這些數(shù)據(jù)分配到能夠更快寫入的地方(以提高性能)。到目前,我們通過頂點(diǎn)緩沖區(qū)對象(VBO)將頂點(diǎn)數(shù)據(jù)存儲(chǔ)到了顯存中。接下來我們想要?jiǎng)?chuàng)建一個(gè)頂點(diǎn)處理程序和片段處理程序。>說明:頂點(diǎn)處理器聽上去像是GPU中的硬件名稱,這里之所以這么翻譯,是想和下面的頂點(diǎn)處理程序區(qū)別。實(shí)際上,頂點(diǎn)處理程序完成的就是上面圖形渲染流水線中頂點(diǎn)處理器完成的功能。這樣翻譯便于理解。實(shí)際上原文中上面的和下面的都叫做vertex shader。如果都翻譯成頂點(diǎn)處理程序,那么上面流水線的一個(gè)階段是頂點(diǎn)處理程序,怪怪的。所以這樣翻譯。##頂點(diǎn)處理程序 vertex shader頂點(diǎn)處理程序是我們可以編程的流水線中的一個(gè)部分?,F(xiàn)代OpenGL要求我們,如果想要進(jìn)行渲染,至少要建立起頂點(diǎn)處理程序和片段處理程序。所以我們將會(huì)簡短介紹處理程序而且配置兩個(gè)非常簡單的shaders來繪制我們的第一個(gè)三角形,在下一個(gè)教程匯總將會(huì)討論關(guān)于shader的更多細(xì)節(jié)。我們首要做的是利用shader語言GLSL來寫我們的頂點(diǎn)處理程序并且編譯這個(gè)shader以便于我們可以再我們自己的程序中使用。下面我們將看到一個(gè)用GLSL寫的非?;镜膙ertex shader。 #version 330 corelayout (location = 0) in vec3 position;void main() {gl_Position = vec4(position.x, position.y, position.z, 1.0); }

正如你所見,GLSL和C類似。每個(gè)shader的開頭都會(huì)定義它的版本,330對應(yīng)著OpenGL3.3,420對應(yīng)著OpenGL4.2。我們還明確地聲明我們使用core-profile模式。接下來我們聲明了這個(gè)頂點(diǎn)渲染程序的頂點(diǎn)屬性輸入,以關(guān)鍵字in標(biāo)明的position。因?yàn)槟壳拔覀冎魂P(guān)心位置,所以只需要指定單獨(dú)這個(gè)頂點(diǎn)屬性作為輸入就夠了。GLSL中,有一個(gè)可以包含1到4個(gè)GLfloat類型的vector數(shù)據(jù)類型。因?yàn)槿切蔚拿總€(gè)頂點(diǎn)都是一個(gè)三維坐標(biāo),所以我們可以使用vec3類型的vector(vec3表示vector中含有3個(gè)GLfloat)來定義名稱為position的輸入。我們同時(shí)還通過layout關(guān)鍵字和location的值(本例設(shè)置為0)明確地指定這些輸入數(shù)據(jù)的位置。這在后面告訴GPU我們用的數(shù)據(jù)在哪兒的時(shí)候會(huì)用到。>這個(gè)程序可以這么理解:聲明類型為vec3的變量position,用關(guān)鍵字in指明這是此頂點(diǎn)處理器的輸入,并且用關(guān)鍵字layout(location = 0)指明輸入數(shù)據(jù)的索引號,便于后面查找。然后是函數(shù)體。>>矢量Vector在圖形編程中我們經(jīng)常使用數(shù)學(xué)中矢量的概念,因?yàn)槭噶靠梢院軆?yōu)雅地在任何維度內(nèi)表示對象的位置、方向和其他屬性(所有想要表示的都可以放到一個(gè)矢量中)。而且矢量具有很好的數(shù)學(xué)特定。GLSL中的矢量最多可以含有四個(gè)數(shù)值,而且可以通過與C結(jié)構(gòu)體中元素類似的訪問方式訪問,如vec.x,vec.y,vec.z和vec.w。它們分別代表了對象在空間中的每一個(gè)維度的表示。注意vec.w分量在表示三維空間中的位置時(shí)是不需要的。但是它用于稱作透視圖處理中。在后面的教程中應(yīng)該會(huì)對vector有更深入的講解。在程序中,設(shè)置頂點(diǎn)處理程序的輸出到在圖形渲染流水線中已經(jīng)定義好的gl_Position變量中。它是一個(gè)vec4類型的變量。這個(gè)gl_Position理解成是定點(diǎn)處理器和下一個(gè)階段圖元裝配的接口。因?yàn)樯厦嫖覀冊O(shè)置的輸入是3維矢量,我們需要把它轉(zhuǎn)化成4維矢量。妝花方式比較簡單,即利用vec4的構(gòu)造函數(shù)來生成四個(gè)分量已經(jīng)指定的一個(gè)vec4對象就好了。這里w分量設(shè)置為了1,具體原因后面會(huì)講到。目前這個(gè)頂點(diǎn)渲染程序應(yīng)該是可以想象到的最簡單的頂點(diǎn)處理程序了。因?yàn)樗鼘斎霂缀跏裁匆矝]有做,只是轉(zhuǎn)換了一下數(shù)據(jù)類型就作為結(jié)果輸出了。在真正的應(yīng)用程序中,一般輸入的數(shù)據(jù)不會(huì)(像本例中)已經(jīng)被標(biāo)準(zhǔn)化(所有的坐標(biāo)值都在標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系中),所以定點(diǎn)處理程序可能首先需要先將這些坐標(biāo)轉(zhuǎn)化為OpenGL能夠處理的標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系。>這里需要說明一下,上面寫的定點(diǎn)處理程序(vertex shader)并不是放在單獨(dú)一個(gè)源文件編譯鏈接執(zhí)行的程序,它是一個(gè)shader程序。只是我們用到的圖形渲染流水線中的一個(gè)階段(頂點(diǎn)處理器)中用到的程序。所以它是被存儲(chǔ)在類似于C的字符數(shù)組中的。像下面這樣: const GLchar* vertexShaderSource ="#version 330 core\n \ layout (location = 0) in vec3 position;\n \ void main()\n \ {\n \ gl_Position = vec4(position.x, position.y, position.z, 1.0);\n \ }\n\0";那么怎么將它組裝到我們的圖形渲染流水線中呢?首先編譯,然后組裝。接著向下看吧。##編譯shader我們已經(jīng)有了頂點(diǎn)渲染程序(像上面那樣存儲(chǔ)在了字符數(shù)組中),在使用的時(shí)候,我們需要在運(yùn)行時(shí)從它的源碼動(dòng)態(tài)編譯它。為了編譯這個(gè)shader,我們需要先創(chuàng)建一個(gè)shader對象,同樣需要一個(gè)唯一的ID來標(biāo)識。像下面這樣通過GLuint來存儲(chǔ)ID,通過glCreateShader來創(chuàng)建shader對象: GLuint vertexShader; vertexShader = glCreateShader(GL_VERTEX_SHADER);

需要注意的是,我們需要在調(diào)用glCreateShader的時(shí)候指定我們想要?jiǎng)?chuàng)建的shader的類型,因?yàn)槲覀儎?chuàng)建的是頂點(diǎn)處理程序,所以給的參數(shù)是GL_VERTEX_SHADER。接下來我們將上面寫的shader源碼和新創(chuàng)建的這個(gè)shader對象綁定。并且通過調(diào)用glCompileShader來編譯這個(gè)shader: glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); glCompileShader(vertexShader);

glShaderSource函數(shù)的第一個(gè)參數(shù)是一個(gè)shader對象,第二個(gè)參數(shù)指定傳遞的源碼數(shù)量,第三個(gè)參數(shù)是shader源碼字符數(shù)組的指針,第四個(gè)參數(shù)目前我們先不用管,直接設(shè)置為NULL就可以。>實(shí)際上完成上面的過程也就完成了一個(gè)shader的編譯,不管編譯哪個(gè)shader,其原理和做法都是相似的。但是總感覺不是那么放心,編譯成功沒有?錯(cuò)在哪兒了?以下提供了可以檢查編譯結(jié)果的方法: GLint success; GLchar infoLog[512]; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);

即首先設(shè)置一個(gè)flag,即success變量,然后設(shè)置一個(gè)比較大的緩沖區(qū)來裝編譯結(jié)果輸出信息。最重要的是glGetShaderiv函數(shù),它幫助我們得到編譯結(jié)果信息。如果success為0,表示編譯出錯(cuò),這時(shí)我們應(yīng)該來獲取錯(cuò)誤輸出信息,這通過glGetShaderInfoLog來完成: if(!success) {glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; }

當(dāng)然如果編譯成功,就不會(huì)有報(bào)錯(cuò)信息,也就是編譯成功了。## 片段處理程序 Fragment shader上面提到,為了渲染三角形,我們還需要提供片段處理程序。片段處理程序提供圖形渲染流水線中片段處理器完成的功能。它負(fù)責(zé)計(jì)算像素點(diǎn)的顏色值。簡化起見,我們的片段處理程序?yàn)樗械南袼囟伎偸禽敵鲆环N顏色——橙色。在計(jì)算機(jī)圖形中,顏色值是由四個(gè)值來表示的:分別是紅、綠、藍(lán)和alpha通道分量,通常簡寫為RGBA。在OpenGL和GLSL中,我們通過設(shè)置每種分量值(0.0-1.0)來定義一個(gè)顏色值。舉例來說,如果我們想要設(shè)置黃色,那么我們將紅綠兩個(gè)分量設(shè)置成1.0。由三種顏色分量我們可以得到16,000,000種顏色值。 #version 330 coreout vec4 color;void main() {color = vec4(1.0f, 0.5f, 0.2f, 1.0f); }

如上面的程序所示,片段渲染程序只輸出一個(gè)vec4類型的變量,也就是color,通過out關(guān)鍵字來標(biāo)識。程序的主體部分知識將這個(gè)輸出值賦值為橙色。這應(yīng)該也是一個(gè)非常簡單的片段處理器了。編譯片段處理程序的過程和編譯頂點(diǎn)處理程序的過程是十分相似的。只是在調(diào)用glCreateShader的時(shí)候指定的參數(shù)是GL_FRAGMENT_SHADER: GLuint fragmentShader; fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); glCompileShader(fragmentShader);

>同樣,可以使用上面介紹的方法檢驗(yàn)我們的編譯是否成功。現(xiàn)在我們已經(jīng)準(zhǔn)備好了我們必須要提供的兩個(gè)shader,下面就是要將它們組裝到我們的圖形渲染流水線中(別忘了它們只是整個(gè)圖形渲染流水線中的兩個(gè)階段),以便于我們使用它來進(jìn)行渲染。## Shader program整個(gè)圖像渲染流水線可以看成是一個(gè)渲染程序,它由不同階段的shader構(gòu)建而成。OpenGL中對應(yīng)的概念是渲染程序?qū)ο?#xff08;shader program object),它是編譯好和連接到一起的不同階段的shader的整體。這里可以把它看成是可以裝配的流水線。為了使用剛剛編譯好的頂點(diǎn)和片段shader,我們需要把它們裝配到渲染程序?qū)ο笾胁⑶壹せ钏鼈?。這樣我們才能夠在調(diào)用渲染指令的之后使用包含這些shaders的渲染程序?qū)ο髞礓秩疚覀兊膱D形。這個(gè)過程應(yīng)該是一個(gè)狀態(tài)設(shè)置過程,而調(diào)用渲染命令是狀態(tài)使用過程。如上面講到的,在圖形渲染流水線中,前面階段的輸出是后面階段的輸入。同理,在渲染程序?qū)ο笾?#xff0c;裝配不同的shader的時(shí)候也是這樣,將前面階段的shader的輸出作為后面階段shader的輸入,而且其它階段默認(rèn)已經(jīng)存在。理解成渲染程序?qū)ο髸?huì)幫我們處理這些就好了。創(chuàng)建一個(gè)渲染程序?qū)ο笫呛唵蔚?#xff1a; GLuint shaderProgram; shaderProgram = glCreateProgram();

glCreateProgram創(chuàng)建了一個(gè)程序?qū)ο?#xff0c;而shaderProgram保存了其ID,現(xiàn)在我們將我們之前創(chuàng)建并編譯好的兩個(gè)shader通過調(diào)用glAttachShader和glLinkProgram裝配到這個(gè)渲染程序?qū)ο笾?#xff1a; glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram);

好的,上面的過程就像是我們組裝了一條生產(chǎn)線,讓人激動(dòng)的是,其中的兩個(gè)模塊使我們自己實(shí)現(xiàn)的。它幾乎可以開始生產(chǎn)了,而其產(chǎn)品將會(huì)是輸出到屏幕上的圖形。>我們可以像檢查shader程序是否編譯好一樣檢查這條生產(chǎn)線是否組裝好。只不過需要使用與之不同但是十分類似的函數(shù): glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if(!success) {glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);... }

怎么樣啟動(dòng)這個(gè)生產(chǎn)線呢?我們首先需要告訴OpenGL我們想要激活這個(gè)渲染程序?qū)ο?#xff0c;這通過函數(shù)glUseProgram完成: glUseProgram(shaderProgram);
  • 1
這樣,在此之后我們調(diào)用的任何渲染指令,都會(huì)用這個(gè)渲染程序(這條生產(chǎn)線)來執(zhí)行。當(dāng)然不要忘記在將編譯好的shader裝配到渲染程序?qū)ο蠛髣h除它們,因?yàn)槲覀儾辉傩枰鼈?#xff1a; glDeleteShader(vertexShader); glDeleteShader(fragmentShader);

上面的過程相當(dāng)于我們已經(jīng)準(zhǔn)備好了生產(chǎn)產(chǎn)品的硬件條件。一條我們定制化(頂點(diǎn)和片段處理器都由我們創(chuàng)建)的生產(chǎn)線(渲染程序?qū)ο?#xff09;,而且我們已經(jīng)準(zhǔn)備好了原材料(頂點(diǎn)數(shù)據(jù))。我們似乎可以開工生產(chǎn)我們的產(chǎn)品(渲染我們的圖形)了。但是并沒有。OpenGL并不知道它應(yīng)該如何使用我們的原材料(數(shù)據(jù))。比如應(yīng)該怎樣取出和存入,怎樣將它們和頂點(diǎn)渲染程序中定義的輸入數(shù)據(jù)聯(lián)系起來。下面我們將告訴OpenGL應(yīng)該怎么使用這些數(shù)據(jù)。 ##設(shè)定頂點(diǎn)輸入方式 前面,我們寫的頂點(diǎn)處理程序只是設(shè)定了輸入的類型(vec3)和輸入后的索引(location=0),但是并沒有指明我們的頂點(diǎn)數(shù)據(jù)的輸入方式。我們的數(shù)組中一共有三個(gè)頂點(diǎn)9個(gè)數(shù)據(jù),是下標(biāo)為2的先輸進(jìn)去還是下標(biāo)為0的先輸進(jìn)去?實(shí)際上,在OpenGL中頂點(diǎn)定點(diǎn)渲染程序允許我們以多種方式指定類似的輸入方式,這提供了數(shù)據(jù)輸入的巨大靈活性,但是也意味著我們需要手工指定我們的頂點(diǎn)數(shù)據(jù)和頂點(diǎn)處理程序中的頂點(diǎn)屬性的對應(yīng)關(guān)系。即我們需要指定OpenGL在渲染前應(yīng)該如何解釋或理解這些頂點(diǎn)數(shù)據(jù)。我們的頂點(diǎn)緩沖區(qū)中的數(shù)據(jù)的個(gè)數(shù)如下圖所示:



位置坐標(biāo)值都是32位(4字節(jié))的浮點(diǎn)類型;每個(gè)位置由三個(gè)坐標(biāo)值構(gòu)成;在每組3個(gè)坐標(biāo)值之間沒有任何間隙,換句話說,數(shù)值在內(nèi)存中是連續(xù)緊密存放的;數(shù)據(jù)的第一個(gè)值位于緩沖區(qū)開始的位置?;谝陨线@些信息,我們可以通過glVertexAttribPointer函數(shù)來告訴OpenGL應(yīng)該如何解釋這些頂點(diǎn)數(shù)據(jù):

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0);

glVertexAttribPointer函數(shù)的參數(shù)較多,我們逐一來看一下:第一個(gè)參數(shù):指定了我們想要配置哪個(gè)頂點(diǎn)屬性(頂點(diǎn)屬性是一個(gè)詞,這里可以理解成一個(gè)頂點(diǎn)屬性集合,即矢量)。還記得我們在頂點(diǎn)處理程序的開始處指定的輸入的位置頂點(diǎn)屬的location值嗎,就是這個(gè)實(shí)參0的含義?!發(fā)ayout (location = 0)“就限定了頂點(diǎn)屬性的位置是0,方便我們在這個(gè)地方使用的時(shí)候易于索引。第二個(gè)參數(shù)指定了頂點(diǎn)屬性的大小,因?yàn)槲覀冊O(shè)置的輸入是vec3類型的,所以這里設(shè)置為3,表示由3個(gè)數(shù)據(jù)構(gòu)成。第三個(gè)參數(shù)指定數(shù)據(jù)的類型,設(shè)置為GL_FLOAT。因?yàn)镚LSL中的vector中的數(shù)值類型是GLfloat。第四個(gè)參數(shù)指定我們是否需要將數(shù)據(jù)標(biāo)準(zhǔn)化,因?yàn)槲覀兊臄?shù)據(jù)在生成的時(shí)候就已經(jīng)標(biāo)準(zhǔn)化了,所以這里并不需要,設(shè)置為GL_FALSE。如果設(shè)置為GL_TRUE,所有不滿足數(shù)值大小范圍為[-1,1]的數(shù)值都會(huì)被首先標(biāo)準(zhǔn)化為標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系中的坐標(biāo)值。第五個(gè)參數(shù)指定了在連續(xù)頂點(diǎn)屬性集合之間的空隙——稱作步進(jìn)長度。我們的例子中每兩個(gè)頂點(diǎn)屬性之間相差三個(gè)GLfloat空間,所以設(shè)置為“3 * sizeof(GLfloat)“,實(shí)際上,因?yàn)檫@里數(shù)據(jù)都是緊密排列的,設(shè)置為0,OpenGL就會(huì)認(rèn)為頂點(diǎn)屬性之間沒有空隙,也是能夠正常解析的。最后一個(gè)參數(shù)將0轉(zhuǎn)換為GLvoid*類型,它指明了數(shù)據(jù)在緩沖區(qū)中的偏移。上面已經(jīng)說了,我們例子中的數(shù)據(jù)在緩沖區(qū)中的偏移是0,所以這里這么給實(shí)參。>還記得前面講的VBO嗎?實(shí)際上,上述頂點(diǎn)屬性的取得都要經(jīng)過VBO,因?yàn)閂BO是OpenGL和Memory之間的接口。那么在有多個(gè)VBO時(shí),哪一個(gè)才是我們要取的呢?也就是說,如果我們設(shè)定的取數(shù)據(jù)的地方不是我們想象的,而是其他的VBO呢?實(shí)際上,在每次取數(shù)據(jù)的時(shí)候,程序能看到的VBO只有一個(gè),也就是綁定到 GL_ARRAY_BUFFER目標(biāo)的那個(gè)VBO。那么,如果我們想要從其他VBO中取數(shù)據(jù)也是簡單的,只需要在取之前將含有我們想要數(shù)據(jù)的VBO綁定到 GL_ARRAY_BUFFER就好了。到目前為止,我們已經(jīng)指定好了OpenGL應(yīng)該怎樣解釋我們的原材料(頂點(diǎn)數(shù)據(jù))。我們還應(yīng)該通過上面所示的glEnableVertexAttribArray函數(shù)設(shè)置頂點(diǎn)屬性生效,因?yàn)轫旤c(diǎn)屬性默認(rèn)是disabled的,參數(shù)就是設(shè)置的location(為0)。OK,到這兒基本上所有該準(zhǔn)備的都已經(jīng)準(zhǔn)備完成了!我們首先利用VBO準(zhǔn)備好了頂點(diǎn)數(shù)據(jù),接著創(chuàng)建了兩個(gè)shader(頂點(diǎn)和片段),然后將它們裝配到當(dāng)前使用的渲染程序?qū)ο笾?#xff0c;最后我們告訴OpenLGL應(yīng)該如何解釋我們的數(shù)據(jù)。是時(shí)候繪制我們的圖形了。至此,我們知道了渲染圖形的整個(gè)流程大致是這么個(gè)樣子: // 0. Copy our vertices array in a buffer for OpenGL to use glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 1. Then set the vertex attributes pointers glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); // 2. Use our shader program when we want to render an object glUseProgram(shaderProgram); // 3. Now draw the object someOpenGLFunctionThatDrawsOurTriangle();

在繪制之前,還有最后一步——更標(biāo)準(zhǔn)地繪制我們的三角形! 在每一次我們想要繪制一個(gè)對象的時(shí)候,這個(gè)流程都需要執(zhí)行一次?,F(xiàn)在看上去可能不是那么多,但是,如果后面我們的繪制更加復(fù)雜的時(shí)候就會(huì)出現(xiàn)問題了??焖俳壎ê线m的緩沖區(qū)對象和配置所有的頂點(diǎn)屬性變成一個(gè)龐雜的過程。要是能有一個(gè)對象將我們配置的所有的狀態(tài)都記錄下來,只要在使用的時(shí)候綁定這個(gè)對象就好了。這種對象就是下文要講到的頂點(diǎn)數(shù)組對象(Vertex Array Object,簡稱VAO)。##頂點(diǎn)數(shù)組對象 Vertex Array Object 頂點(diǎn)數(shù)組對象(VAO)可以像VBO類似方式綁定,隨后的對數(shù)組對象的調(diào)用都將被存儲(chǔ)到頂點(diǎn)數(shù)組對象中。這樣的好處是,在進(jìn)行頂點(diǎn)屬性指針配置的時(shí)候只需要調(diào)用一次必要的函數(shù),再次使用的時(shí)候,只需要綁定相關(guān)的VAO就可以了,因?yàn)閂AO已經(jīng)將這個(gè)配置全部記錄下來。這樣的話,在不同的對象繪制之間就簡化了配置的過程。因?yàn)槲覀冊O(shè)置要繪制對象的狀態(tài)設(shè)置都已經(jīng)存儲(chǔ)到了VAO中。OpenGL的core-profile模式要求我們使用VAO,這樣的話它能夠知道對我們的頂點(diǎn)輸入的具體操作。如果我們綁定VAO失敗,OpenGL很有可能停止運(yùn)行。一個(gè)頂點(diǎn)數(shù)組對象(VAO)存儲(chǔ)以下信息:對glEnableVertexAttribArray或者glDisableVertexAttribArray調(diào)用對頂點(diǎn)屬性的配置,即對glVertexAttribPointer的調(diào)用通過調(diào)用glVertexAttribPointer與頂點(diǎn)屬性關(guān)聯(lián)的VBO![ ](http://learnopengl.com/img/getting-started/vertex_array_objects.png)創(chuàng)建VAO的過程和創(chuàng)建VBO類似: GLuint VAO; glGenVertexArrays(1, &VAO);

使用VAO時(shí)唯一要做的就是使用glBindVertexArray函數(shù)來綁定VAO。綁定之后我們應(yīng)該綁定或者配置相關(guān)的VBO和屬性指針,然后解綁這個(gè)VAO留作后用。在我們想要繪制一個(gè)對象的時(shí)候,我們只需要將包含我們想要的設(shè)置的VAO在繪制之前再次綁定就可以了。這個(gè)過程大概如下所示: // ..:: Initialization code (done once (unless your object frequently changes)) :: .. // 1. Bind Vertex Array Object glBindVertexArray(VAO);// 2. Copy our vertices array in a buffer for OpenGL to useglBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// 3. Then set our vertex attributes pointersglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);glEnableVertexAttribArray(0); //4. Unbind the VAO glBindVertexArray(0);[...]// ..:: Drawing code (in Game loop) :: .. // 5. Draw the object glUseProgram(shaderProgram); glBindVertexArray(VAO); someOpenGLFunctionThatDrawsOurTriangle(); glBindVertexArray(0);

>通常在每次配置之后將對象解綁是一個(gè)比較好的做法,因?yàn)檫@樣可以防止在其它地方對其無意之間的綁定。終于,所有的東西都已經(jīng)準(zhǔn)備好了,實(shí)際上在VAO講解之前就已經(jīng)好了,只不過我們對自己的要求比較高,要用更規(guī)范的方式來進(jìn)行我們圖形的繪制。實(shí)際上利用VAO的方式也的確方便我們后面的學(xué)習(xí)和理解。而且當(dāng)我們有很對對象或者很多VBO或者很多配置需要時(shí)常切換的時(shí)候,我們利用VAO可以大大提高工作效率。嗯,這是值得的!##期待已久的三角形!我們通過OpenGL提供的圖元繪制函數(shù)glDrawArrays(實(shí)際上還有其他,我們現(xiàn)在先選擇glDrawArrays)來繪制我們的對象。相關(guān)的VAO,VBO就是前面花了這么長時(shí)間準(zhǔn)備的: glUseProgram(shaderProgram); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0);

glDrawArrays函數(shù)的第一個(gè)參數(shù)是OpenGL支持繪制的圖元類型的宏定義。GL_TRIANGLES代表三角形。 第二個(gè)參數(shù)指定了開始繪制的頂點(diǎn)數(shù)組下標(biāo),我們就讓它為0。最后一個(gè)參數(shù)指定了我們要繪制多少個(gè)點(diǎn),我們只有三個(gè)點(diǎn)?,F(xiàn)在試著編譯我們的程序并且運(yùn)行吧,我已經(jīng)迫不及待了。我的運(yùn)行的結(jié)果是:

到目前為止,全部的代碼在這兒。

##元素緩沖對象 Element Buffer Objects除了上面介紹的利用glDrawArrays函數(shù)進(jìn)行圖形渲染的方式,實(shí)際上還有一種渲染方式,就是借助glDrawElements進(jìn)行圖形渲染。它和元素緩沖對象(Element Buffer Objects,簡稱EBO)是聯(lián)系在一起的。解釋元素緩沖對象(EBO)是如何工作的最好方式是給出一個(gè)例子:假設(shè)我們想要繪制一個(gè)矩形而不是三角形。我們可以利用兩個(gè)三角形(OpenGL主要是利用基本圖元三角形來完成復(fù)雜對象的繪制)來繪制一個(gè)矩形。按照上面講過的流程,首先是數(shù)據(jù)的產(chǎn)生: GLfloat vertices[] = {// First triangle0.5f, 0.5f, 0.0f, // Top Right0.5f, -0.5f, 0.0f, // Bottom Right-0.5f, 0.5f, 0.0f, // Top Left // Second triangle0.5f, -0.5f, 0.0f, // Bottom Right-0.5f, -0.5f, 0.0f, // Bottom Left-0.5f, 0.5f, 0.0f // Top Left };

如你所見,兩個(gè)三角形之間是有所重合的:左上角和右下角的點(diǎn)被指定了兩次。相對于一個(gè)矩形的四個(gè)頂點(diǎn)來說,我們指定了六個(gè)點(diǎn)(其中有兩個(gè)是重合的),這相當(dāng)于多做了50%的工作!當(dāng)我們要繪制更為復(fù)雜的模型的時(shí)候這種情況還會(huì)更糟,因?yàn)樗鼈兛赡苡懈嗟闹睾?。是不是能有一種方法只需要存儲(chǔ)(矩形)模型的不同的點(diǎn),在繪制的時(shí)候只需要指定特定的繪制順序就能夠得到我們想要的圖形呢?在這種情況下,我們只需要存儲(chǔ)矩形的四個(gè)頂點(diǎn)(右上,右下,左上,左下),且每個(gè)頂點(diǎn)存儲(chǔ)一次,而且只需要在繪制的時(shí)候指定先繪制右上–右下–左上一個(gè)三角形,在繪制右下–左下–左上一個(gè)三角形就可以了。OpenGL會(huì)提供給我們這種方便的方式嗎?幸運(yùn)的是,元素緩沖對象(EBO)就是干這個(gè)事的!EBO是一個(gè)像VBO一樣的緩存區(qū),但是它存儲(chǔ)的是OpenGL需要繪制的頂點(diǎn)的索引(而不是坐標(biāo))。這種稱作為索引繪制的方法解決了上述的重復(fù)的問題。為了使用這種方法,我們需要首先設(shè)定頂點(diǎn)的坐標(biāo)值和我們期望OpenGL在繪制的時(shí)候的索引值,它們是兩個(gè)數(shù)組,如下所示: GLfloat vertices[] = {0.5f, 0.5f, 0.0f, // Top Right0.5f, -0.5f, 0.0f, // Bottom Right-0.5f, -0.5f, 0.0f, // Bottom Left-0.5f, 0.5f, 0.0f // Top Left }; GLuint indices[] = { // Note that we start from 0!0, 1, 3, // First Triangle1, 2, 3 // Second Triangle };

如代碼所示,我們僅僅在頂點(diǎn)坐標(biāo)的數(shù)組中指定了我們想要繪制的矩形的四個(gè)頂點(diǎn),而在索引數(shù)組中指定了在繪制每個(gè)三角形時(shí)使用的點(diǎn)。接下來我們來創(chuàng)建元素緩沖對象: GLuint EBO; glGenBuffers(1, &EBO);

創(chuàng)建過程和VBO的創(chuàng)建過程是一致的,因?yàn)槎弑举|(zhì)上就是一塊緩存區(qū)。同樣像VBO一樣,可以使用glBindBuffer來指定EBO的緩沖區(qū)類型,可以使用glBufferData將索引數(shù)組的數(shù)據(jù)復(fù)制到這塊緩沖區(qū)中。同樣,和VBO綁定到GL_ARRAY_BUFFER目標(biāo)類似,我們將EBO綁定到GL_ELEMENT_ARRAY_BUFFER目標(biāo),以保證調(diào)用相關(guān)的函數(shù)的時(shí)候操作的是我們現(xiàn)在生成的這個(gè)索引數(shù)組: glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

接下來,我們需要調(diào)用另一個(gè)繪制函數(shù)glDrawElements來完成這個(gè)矩形的繪制。調(diào)用glDrawElements表明我們想要按照我們當(dāng)前綁定的EBO中的索引值來繪制我們的圖形。如下所示: glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

glDrawElements函數(shù)的第一個(gè)參數(shù)指定了我們想要繪制的圖元類型,這里指定為GL_TRIANGLES,第二個(gè)參數(shù)是要繪制的元素個(gè)數(shù)。這里設(shè)置為6因?yàn)槲覀円L制兩個(gè)三角形(2*3=6個(gè)頂點(diǎn),就是索引數(shù)組中的六個(gè)頂點(diǎn))。第三個(gè)參數(shù)指定了索引的數(shù)據(jù)類型,這里設(shè)置的是無符號整型GL_UNSIGNED_INT,最后一個(gè)參數(shù)允許我們指定EBO中的一個(gè)偏移(或者在不用EBO的時(shí)候這個(gè)參數(shù)直接給一個(gè)索引數(shù)據(jù)名),這里我們給定的值是0。glDrawElements函數(shù)從當(dāng)前綁定到GL_ELEMENT_ARRAY_BUFFER目標(biāo)的EBO中取得索引值。這意味著我們在每次繪制對象的時(shí)候都需要綁定相應(yīng)的EBO到GL_ELEMENT_ARRAY_BUFFER,這看上去似乎又有些繁雜。恰好之前介紹過的VAO也同樣能夠幫助我們解決這個(gè)問題。一個(gè)頂點(diǎn)數(shù)組對象(VAO)也可以保留EBO的綁定信息(和VBO類似)。所以如果在綁定VAO之后進(jìn)行了EBO的綁定也會(huì)被VAO記錄下來,等到再次綁定VAO的時(shí)候,同樣相應(yīng)的EBO也就被綁定到了相應(yīng)的GL_ELEMENT_ARRAY_BUFFER。如下圖所示: ![](http://learnopengl.com/img/getting-started/vertex_array_objects_ebo.png)>VAO在綁定目標(biāo)是GL_ELEMENT_ARRAY_BUFFER存儲(chǔ)glBindBuffer調(diào)用。這意味著它也存儲(chǔ)它的解綁調(diào)用,以確保你在解綁VAO之前不會(huì)解綁EBO,否則,它就沒有EBO來進(jìn)行配置了。利用EBO、VAO和glDrawElements的初始化和繪制代碼基本流程如下所示: // ..:: Initialization code :: .. // 1. Bind Vertex Array Object glBindVertexArray(VAO);// 2. Copy our vertices array in a vertex buffer for OpenGL to useglBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// 3. Copy our index array in a element buffer for OpenGL to useglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);// 3. Then set the vertex attributes pointersglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);glEnableVertexAttribArray(0); // 4. Unbind VAO (NOT the EBO) glBindVertexArray(0);[...]// ..:: Drawing code (in Game loop) :: .. glUseProgram(shaderProgram); glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0) glBindVertexArray(0);

運(yùn)行上面的程序應(yīng)該得到如下所示的畫面。左邊的圖形看上去應(yīng)該是比較熟悉的填充模式,右邊的方式是用線框模式繪制的。線框的三角形顯示出這個(gè)矩形確實(shí)是由兩個(gè)三角形組成的。

線框模式和填充模式

以線框模式繪制三角形(或者其它圖元),需要利用狀態(tài)設(shè)置函數(shù)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)來完成,其中第一個(gè)參數(shù)指定對要繪制的圖元的兩個(gè)面(OpenGL中的繪制對象都是有兩個(gè)面的,正面和反面,后面應(yīng)該會(huì)講到怎么區(qū)分這兩個(gè)面)都采用同樣的繪制模式,第二個(gè)參數(shù)指定以線框來繪制圖元。隨后的繪制命令都會(huì)以設(shè)定的線框模式來繪制圖形,知道我們將繪制模式再次通過glPolygonMode函數(shù)將繪制模式指定為填充模式。

錯(cuò)誤是不可避免的,如果有錯(cuò)誤,說明前面的某一步可能出問題了。同時(shí),也代表理解上可能有點(diǎn)問題,當(dāng)然也有可能是我表述不清。。。??梢曰剡^頭來檢查一下,到目前為止的多有代碼都在這兒。值得注意的是,代碼中為了和glDrawArrays繪制方式區(qū)別,以索引繪制的方式為其創(chuàng)建了另一份對應(yīng)的VBO,EBO和VAO,所以有多個(gè)VBO和VAO,這樣在切換的時(shí)候可以體會(huì)利用VAO進(jìn)行狀態(tài)設(shè)置保存的好處。

如果你按照上面的過程成功繪制了三角形或者矩形。你已經(jīng)挺過了學(xué)習(xí)現(xiàn)代OpenGL幾乎是最艱難的一段:繪制一個(gè)簡單的三角形。萬事開頭難嘛。實(shí)際上,這其中包含了很多相關(guān)的知識,如果沒有學(xué)過圖形學(xué)相關(guān)的內(nèi)容,看起來還是比較吃力的。如果有相關(guān)的圖形學(xué)基礎(chǔ),可以發(fā)現(xiàn),本次教程是對理論知識的一次小小實(shí)踐。充分地理解這個(gè)過程是十分必要的,也是后面繼續(xù)學(xué)習(xí)的基礎(chǔ)。一旦對這些概念和過程有了充分的了解,后面的內(nèi)容應(yīng)該就相對簡單一些了。

總結(jié)

以上是生活随笔為你收集整理的【Modern OpenGL】第一个三角形的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

日本黄色免费在线 | 激情xxxx | 欧美色图p| 欧美一级艳片视频免费观看 | 国产手机视频在线播放 | 久久精品视频网站 | 国产精品一区二区美女视频免费看 | 天天天天色射综合 | 色综合久久久久久中文网 | 亚洲视频专区在线 | 在线观看www视频 | 国产综合婷婷 | 亚洲激情小视频 | 亚洲国产69| 免费男女羞羞的视频网站中文字幕 | 亚洲欧洲av| 免费观看一级特黄欧美大片 | 国产激情小视频在线观看 | 亚洲va韩国va欧美va精四季 | 国产精品精品国产婷婷这里av | 在线观看免费高清视频大全追剧 | 91中文在线 | 欧美成人基地 | 欧美 日韩 久久 | 天天色图 | 米奇影视7777 | 色天堂在线视频 | 国产精品美女免费看 | 免费在线观看91 | 成人h视频在线播放 | 毛片美女网站 | 91精品办公室少妇高潮对白 | 婷婷六月激情 | 久久免费一级片 | 天天摸夜夜添 | 久草在线观看视频免费 | 国产精品九九久久99视频 | 成人免费视频视频在线观看 免费 | 91福利专区| 六月丁香婷婷在线 | 超碰国产在线观看 | 国产成a人亚洲精v品在线观看 | 在线观看网站你懂的 | 久久久国产精品网站 | 最近中文字幕免费视频 | 中文字字幕在线 | 欧美精品一级视频 | 日韩av播放在线 | 一本一本久久a久久精品综合 | 国产免费美女 | 欧美大片www | 国产视频一区二区在线播放 | 亚洲专区路线二 | 国产精品亚 | 成人一区二区三区在线 | 丝袜美腿在线播放 | 欧美色道| 久久免费视频2 | 97超碰人人 | 五月婷婷,六月丁香 | 色视频网站在线观看一=区 a视频免费在线观看 | 国产精品中文在线 | 激情在线五月天 | 久久久久久久久久网站 | 国产精品综合av一区二区国产馆 | 婷婷五月在线视频 | 欧美精品一区二区三区一线天视频 | 高清不卡毛片 | 麻豆视频免费网站 | 中文字幕一区二区三区四区久久 | 久精品视频在线观看 | 久久人人爽爽人人爽人人片av | 国产黄色片久久久 | 欧美日韩不卡一区二区三区 | 超薄丝袜一二三区 | 久久久久久久久久久久av | 亚洲精品国产日韩 | 日韩在线免费播放 | 最新超碰在线 | 亚洲成人影音 | 99久久这里只有精品 | 国内精品在线一区 | 色哟哟国产精品 | 日本免费久久高清视频 | 97电影手机版 | 日韩精品久久久免费观看夜色 | 五月婷婷婷婷婷 | 精品一区二区在线免费观看 | 日本久久高清视频 | 婷婷精品在线视频 | 色噜噜日韩精品欧美一区二区 | 国产一区欧美在线 | 日日干夜夜骑 | 天堂中文在线播放 | 91亚洲精品久久久中文字幕 | 精品a在线| 久久少妇免费视频 | 国产xxxx做受性欧美88 | 在线观看91精品国产网站 | 天天综合网在线观看 | 深爱激情久久 | 在线观看日韩视频 | 婷婷网五月天 | 免费看黄在线网站 | 久久综合婷婷国产二区高清 | 久久er99热精品一区二区三区 | 午夜av电影 | 久久久久久久久久亚洲精品 | 欧美精品黑人性xxxx | 激情av在线资源 | 色综合久久综合中文综合网 | 欧美另类老妇 | 播五月综合 | 九九久久成人 | 狠狠干中文字幕 | 亚洲精选在线观看 | 啪啪免费观看网站 | 91视频链接 | 成人在线播放免费观看 | 国产男女免费完整视频 | a电影在线观看 | 久久免费视频在线观看 | 免费观看一区 | 99久久精品国产免费看不卡 | 成人av地址| 狠狠操狠狠干天天操 | 亚洲精品国产精品乱码在线观看 | 亚洲精品一区二区在线观看 | 成人精品久久久 | 国产视频手机在线 | 日韩精品免费专区 | 亚洲视频1区2区 | 日韩中出在线 | 在线国产一区二区三区 | 免费在线观看成人 | 精品亚洲视频在线观看 | 亚洲欧美日韩在线一区二区 | 国产精品99免视看9 国产精品毛片一区视频 | 96精品视频 | 精品国产欧美一区二区三区不卡 | 国产婷婷一区二区 | 99久久电影| 99热手机在线观看 | 黄色资源网站 | 天天色天天干天天 | 国产午夜三级一区二区三 | 国产精品免费人成网站 | 国产精品一区在线观看你懂的 | 日日干影院 | 精品国产一区二区三区久久久蜜月 | 99精品系列 | 亚洲精品视频偷拍 | 国产成人精品一区二区三区福利 | 99久久精品久久亚洲精品 | 夜夜骑日日 | 一区二区精品久久 | 久久69精品久久久久久久电影好 | 91av视频 | 国产成人三级一区二区在线观看一 | 99综合久久 | 综合色久| 欧美一级免费高清 | 免费又黄又爽视频 | 午夜黄色 | 免费看久久久 | 国产欧美最新羞羞视频在线观看 | 狠狠色狠狠色终合网 | 日本一区二区免费在线观看 | 99久久999久久久精玫瑰 | 99视频在线 | 久久久久久高潮国产精品视 | 国产精品免费观看久久 | 亚洲va男人天堂 | 久久免费精彩视频 | 亚洲天堂网在线观看视频 | 久久人人爽人人人人片 | 精品国产一区二区三区四区在线观看 | 国产99久久九九精品免费 | 日日夜夜精品免费视频 | 日韩av电影手机在线观看 | 天天操操操操操操 | 欧美黄色高清 | 久久国产视频网站 | 久久在草 | 91精品国产一区 | 91成人在线观看喷潮 | 国产美女精品视频免费观看 | 久久歪歪 | 国产一级在线免费观看 | 亚洲精品国产精品乱码不99热 | 日韩激情久久 | 在线播放一区二区三区 | 四虎在线观看视频 | 国产一区二区三区网站 | 免费看搞黄视频网站 | 欧美日本一区 | 91豆花在线观看 | 免费av福利 | 欧美资源 | 又色又爽又激情的59视频 | 玖玖精品视频 | 人人爽人人干 | 在线观看精品视频 | 免费成人在线观看视频 | 日躁夜躁狠狠躁2001 | 亚洲美女精品 | 免费视频一二三 | 国产精品一区二区三区久久久 | 一区二区伦理电影 | www.黄色在线 | 免费av网站观看 | 日韩精品高清视频 | 国产高清久久 | 日韩理论电影在线 | 久久免费高清视频 | 五月天婷婷视频 | 91免费在线看片 | 欧美日韩不卡一区二区三区 | 色婷婷国产精品一区在线观看 | 亚洲a资源 | 黄色成人91 | 精品视频成人 | 亚洲精品动漫成人3d无尽在线 | 欧洲精品亚洲精品 | 9在线观看免费高清完整版 玖玖爱免费视频 | 视频成人永久免费视频 | 成人免费看视频 | 精品成人在线 | 97品白浆高清久久久久久 | 日日干干夜夜 | 精品黄色在线观看 | 国产在线观看a | 欧美在一区 | 中文字幕在线国产精品 | a在线视频v视频 | 成人免费一级 | 欧美日韩中文在线视频 | 欧美美女一级片 | a级国产片 | 亚洲第一色 | 欧美在线视频免费 | 91大神免费视频 | 亚洲 成人 一区 | 久久精品视频观看 | 中字幕视频在线永久在线观看免费 | 色噜噜噜噜 | 免费精品在线观看 | 日韩91av | www夜夜| 国产精品一区二区免费在线观看 | 丁香激情综合久久伊人久久 | 国产婷婷在线观看 | 国产在线精品视频 | 97视频资源 | 欧美十八 | 欧美在线视频精品 | 久久久96 | 夜夜干夜夜| 欧美在线视频精品 | 成人动漫一区二区 | avav片| 一区二区三区免费在线 | 免费视频一级片 | 狠狠色噜噜狠狠狠狠 | 91香蕉久久| 亚洲一区精品人人爽人人躁 | 色伊人网 | 亚洲成人精品在线 | 狠狠操电影网 | 成人福利在线 | 久久精品一二区 | 99精品欧美一区二区蜜桃免费 | 中文字幕av影院 | 成人h动漫在线看 | 人人射人人射 | 99热精品在线观看 | www亚洲国产 | 国产a级免费| 国产免费久久 | 久久午夜剧场 | 五月天天色 | 精品国产精品久久 | 国产美女在线观看 | 久久久久久久久爱 | 国产伦精品一区二区三区无广告 | 九九色在线 | 欧美日韩视频 | 久久国产精品免费看 | 日韩av高潮 | 性色av香蕉一区二区 | 亚洲一级片免费观看 | 天天碰天天操 | 欧美亚洲三级 | av高清网站在线观看 | 91正在播放 | 日韩精品久久一区二区 | 日韩精品一区二区三区不卡 | 亚洲视频h | 成人在线视频免费看 | 欧美在线视频一区二区三区 | 日韩在线视频一区二区三区 | avv天堂| 久久久久久久久久久综合 | 欧美在线free | 国产精品久久久久久久久久白浆 | 亚洲精品视频久久 | 中文字幕在线观看亚洲 | 亚洲另类视频在线观看 | 亚洲视频免费在线观看 | 国产一级黄色免费看 | 十八岁免进欧美 | 中文字幕在线播放第一页 | 日韩欧美国产激情在线播放 | 69精品在线 | 91人人澡 | 五月开心婷婷 | 欧美中文字幕久久 | 黄色动态图xx | 国产精品国产三级国产aⅴ9色 | 日韩在线电影一区 | 激情综合久久 | 亚洲国产中文字幕在线观看 | 日日日视频 | 五月黄色 | 亚洲理论电影 | 国产成人av片 | 99精品在线视频观看 | 精品欧美在线视频 | www视频在线观看 | 一区中文字幕电影 | 黄色成年网站 | 午夜国产影院 | 午夜视频播放 | 精品三级av | 最新久久免费视频 | 亚洲精品视频在线观看免费 | 久久天堂网站 | 免费a一级 | 久久夜视频 | 国产美女无遮挡永久免费 | 免费观看视频的网站 | 欧美精品久久久久久久久久丰满 | 成人网中文字幕 | 国产精品爽爽久久久久久蜜臀 | 在线观看一区二区视频 | 欧美日韩精品在线 | 中文字幕一区二区三区精华液 | 在线欧美a | 江苏妇搡bbbb搡bbbb | 在线成人免费av | 福利视频导航网址 | 日韩字幕 | 中文字幕人成不卡一区 | 超碰在线94 | 91探花系列在线播放 | 亚洲女同videos| 成人免费色| 亚洲成av| 最近日本mv字幕免费观看 | 欧美一区二区三区免费看 | 亚洲精品在线观看的 | 天天综合日日夜夜 | www久草| 日韩理论电影在线 | 亚洲国产小视频在线观看 | 国内丰满少妇猛烈精品播放 | 嫩草av影院 | 中文字幕在线观看视频网站 | av天天干| 成人在线观看资源 | 久久性生活片 | 九九热免费视频在线观看 | 99久久影院| 91一区啪爱嗯打偷拍欧美 | 成人黄色大片在线观看 | 亚洲精品动漫成人3d无尽在线 | 美女久久99 | 国产91aaa | 亚洲国产三级在线观看 | 丁香五婷 | 97精产国品一二三产区在线 | 亚洲 欧美变态 另类 综合 | 国产高清在线永久 | 婷婷av资源| 国产精品久久久久久久久费观看 | 丁香色婷婷 | 狠狠色综合欧美激情 | 国产香蕉久久精品综合网 | 成年人在线观看视频免费 | 久久精品综合一区 | 天堂av在线中文在线 | 久久亚洲在线 | 精品在线亚洲视频 | 国产免费又爽又刺激在线观看 | 精品中文字幕视频 | 日韩系列在线 | 国产精品第一视频 | 国产亚洲在线 | 西西444www大胆高清视频 | 精品国产三级a∨在线欧美 免费一级片在线观看 | 欧美热久久 | 97免费中文视频在线观看 | 特级黄色视频毛片 | 一区视频在线 | 成人在线免费视频 | 国产护士hd高朝护士1 | 午夜久久影视 | 有码中文字幕 | 国产精品99久久久久久有的能看 | 五月婷婷视频在线 | 国产第一福利 | 色综合在 | jizzjizzjizz亚洲| 欧美日韩亚洲在线 | 日本在线视频网址 | 久久久久久久久久久久久9999 | 国产成人精品久 | 黄色国产成人 | 国产精品免费久久 | 人人舔人人爱 | 免费av福利| 欧美久久久久久久久久 | 午夜精品久久久久 | 91亚洲精品久久久蜜桃网站 | 69av在线播放| 久久99久久久久久 | 色综合久久中文综合久久牛 | 免费成人av | 超碰在线网 | 欧美黑人xxxx猛性大交 | 国产精品久久久久婷婷 | 不卡精品视频 | 国产精品福利无圣光在线一区 | 精品久久五月天 | 欧美日韩视频一区二区三区 | 91成人短视频在线观看 | 精品美女在线视频 | 福利视频网站 | 中文av网 | 国产一区二区在线播放 | 亚洲综合色站 | 国产精品视频在线观看 | 日韩午夜av | 欧美少妇xxxxxx | 在线观看的a站 | 久久视频国产精品免费视频在线 | 精品国产一区二区三区久久久久久 | 日日夜夜天天射 | 91黄色小视频 | 国产精品理论片在线观看 | 日韩av网址在线 | 久久网页 | 有码中文在线 | 国产精品美 | 韩国一区二区在线观看 | 国产97av| 久插视频 | 西西www4444大胆在线 | 中文字幕在线观看完整 | 天天色天天操天天爽 | 欧美成人一区二区 | 国产精品一区二区白浆 | 九九热在线精品视频 | www.久久婷婷 | 精品国产一二三四区 | 香蕉看片| 亚洲视屏在线播放 | 日韩专区在线观看 | 九九免费精品视频在线观看 | 国产精品永久免费在线 | 成人在线网站观看 | 在线观看免费一区 | 草樱av | 欧美色综合久久 | 色先锋av资源中文字幕 | 激情久久影院 | 日本公妇色中文字幕 | 国产一线在线 | 高清不卡毛片 | 超碰国产在线播放 | 伊人成人激情 | 亚洲在线视频观看 | 国产一区二区在线免费视频 | 免费看亚洲毛片 | 黄色国产在线观看 | 亚洲激情视频在线 | 免费亚洲黄色 | 国产精品免费不卡 | 国产精品久久久久久久久婷婷 | 国内精品久久影院 | 欧美日本高清视频 | 国产亚洲精品日韩在线tv黄 | av资源在线观看 | 国产中文自拍 | 在线 影视 一区 | 91视频下载 | 国产一区二区在线免费观看 | 国产一级电影免费观看 | 男女啪啪网站 | 久久精品1区2区 | 一区二区精品在线 | 亚洲欧洲精品一区二区 | 久久婷婷国产色一区二区三区 | 人人添人人 | 精品国产99国产精品 | 国产色婷婷在线 | 在线91av| 天天操天天射天天爽 | 日韩一区二区三区免费电影 | 国产丝袜 | 特级西西人体444是什么意思 | 日本精品久久久一区二区三区 | 国产丝袜在线 | 日韩av网站在线播放 | 97免费在线观看 | 久久久午夜视频 | 丁香激情五月婷婷 | 91av播放 | 天天拍天天操 | 日日操天天操夜夜操 | 日韩在线观看的 | 日韩动态视频 | 欧美最猛性xxxxx免费 | 亚洲成人av片在线观看 | 亚洲精品中文字幕在线 | 久久成视频 | av在线日韩 | 麻花豆传媒mv在线观看 | 久久久.com| 国产一区欧美一区 | 国产精品久久久久9999吃药 | 国产精品久久久久久婷婷天堂 | 99久久久久成人国产免费 | 91麻豆高清视频 | 色综合久久综合中文综合网 | 久久久久久久久久久久国产精品 | 色亚洲网 | 免费在线观看国产黄 | 久久免费资源 | 国产91影视| 久久精国产 | 婷婷播播网 | 国产精品久久久久久久久费观看 | 伊人天天操 | 欧美在线观看视频免费 | 久久久久国产精品免费免费搜索 | 中文字幕高清有码 | 天天干天天射天天操 | 中文字幕乱视频 | 少妇bbbb搡bbbb桶 | 黄色网址中文字幕 | 五月婷婷一区二区三区 | 免费v片| 久久96国产精品久久99软件 | 狠狠色丁香婷婷综合久小说久 | sm免费xx网站 | 中文字幕久久精品一区 | 国产尤物在线视频 | 国产精品99久久久久久人免费 | 少妇性aaaaaaaaa视频 | 玖操| 亚洲欧美国产精品 | 婷婷国产一区二区三区 | 一级一片免费看 | 91精品一区二区三区蜜臀 | 精品久久久久_ | 久久九九精品 | 玖玖在线视频观看 | 日韩高清毛片 | 国产精品刺激对白麻豆99 | 亚洲精品99 | 久久婷婷亚洲 | av在线网站免费观看 | 日日操操操 | 97国产精品免费 | 91精品国产福利在线观看 | 国产视频精品视频 | 精品一区二区免费 | 亚洲欧洲精品一区二区精品久久久 | 欧美午夜精品久久久久久浪潮 | 九九热国产视频 | 日日夜夜精品 | 日韩一区二区免费在线观看 | 天天操天天干天天操天天干 | 91在线91| 看片的网址 | 在线а√天堂中文官网 | 国产精品毛片一区视频 | 在线播放精品一区二区三区 | 麻豆精品在线视频 | 亚州免费视频 | 国产色婷婷精品综合在线手机播放 | 美女黄视频免费 | 婷婷久操 | 夜夜操天天 | 草久久久| 亚洲欧洲在线视频 | 亚洲精品久久久久999中文字幕 | 国产黄视频在线观看 | 日韩簧片在线观看 | 日日综合网 | 天天爱天天 | 在线观看亚洲国产 | 日韩视频免费观看高清完整版在线 | 中文字幕韩在线第一页 | 国产不卡在线视频 | 成人动漫视频在线 | 国产精品久久久久久久久久久久午夜片 | 日韩一区二区三区高清在线观看 | 日韩在线免费电影 | 成人黄色大片在线观看 | 99精品国产免费久久 | 成人黄色国产 | 99免费在线观看视频 | 国产成人久久 | 亚洲高清免费在线 | 欧美日韩免费网站 | 999视频精品 | 久久国产精品99久久久久 | 日日夜夜精品免费观看 | 亚洲国产人午在线一二区 | 久热av | 国产免费一区二区三区网站免费 | 成人精品视频久久久久 | 黄色av成人在线 | www最近高清中文国语在线观看 | 久久久久久久综合色一本 | 免费高清在线观看成人 | 亚洲精品中文在线资源 | 久久夜视频 | 国产 字幕 制服 中文 在线 | 九色91在线视频 | 日韩电影久久 | 欧美性极品xxxx娇小 | 99久久精品免费看国产免费软件 | 日韩xxxbbb| 99视频精品全部免费 在线 | 亚洲国产影院av久久久久 | 久久久天天操 | 欧美另类成人 | 成人黄色免费在线观看 | 免费色视频| 免费看一级黄色 | 欧洲激情综合 | 色综合久久五月 | 久久午夜国产精品 | 国产一级精品视频 | 日日婷婷夜日日天干 | 色99久久 | 91福利在线观看 | 色婷婷av一区二 | 99久久精品免费看国产一区二区三区 | 一区二区久久久久 | 国产精品久久久精品 | 91精品国产网站 | 97人人人人 | 国产小视频在线 | 国产一线二线三线在线观看 | 一区二区三区精品在线 | 丁香影院在线 | 日日久视频 | 国产日韩欧美在线一区 | 久久精品www人人爽人人 | 69精品视频 | av福利在线| 日日操日日插 | 精品1区2区3区 | 亚洲综合视频在线播放 | 久久久久亚洲a | h网站免费在线观看 | 国产高清免费视频 | 樱空桃av | 国产综合在线视频 | 久久黄视频 | 免费aa大片 | 麻豆国产精品va在线观看不卡 | 国产91精品久久久久久 | 日韩视频在线观看视频 | 午夜国产福利在线 | 久综合网 | 色网免费观看 | 国产精品原创av片国产免费 | 国产999精品久久久影片官网 | 色综合中文综合网 | 亚洲九九爱 | 国产最顶级的黄色片在线免费观看 | 色狠狠一区二区 | 超碰com| 中文在线亚洲 | 黄色激情网址 | wwwav视频 | 国产精品久久久久久超碰 | 丁香花在线观看免费完整版视频 | 国产色视频一区二区三区qq号 | 国色天香在线观看 | 久久国产欧美日韩 | 最近中文字幕免费大全 | 亚洲精品乱码久久久久久蜜桃91 | 中文字幕在线观看免费高清电影 | av在线播放网址 | 国产日产av | 久艹视频在线免费观看 | 在线观看视频免费播放 | 蜜臀aⅴ精品一区二区三区 久久视屏网 | av大片免费看 | 久久久国产精品一区二区中文 | 少妇bbbb揉bbbb日本 | 国产尤物在线视频 | 国产在线专区 | 日本高清dvd | 91精品国产乱码在线观看 | 久久精国产 | 国产精品中文字幕在线播放 | 一区二区av | 久操视频在线观看 | 天堂在线成人 | 国产色啪 | 国产精品永久在线观看 | 久久高清 | 国产精品久久久久四虎 | 国产在线一区二区 | 免费网站在线观看人 | 久久久影院一区二区三区 | 欧美老少交 | 国产高清在线一区 | 久久99久久久久久 | 亚洲 欧洲av | 91精品久久久久久 | 日韩在线理论 | 久久夜夜爽 | 免费在线一区二区 | 欧美日韩中文视频 | 操操操人人人 | 久久久久黄 | 免费av片在线 | 91九色性视频 | 四虎国产 | 国产一区av在线 | 国产99久久精品一区二区300 | 天天曰天天| 激情五月伊人 | 91九色最新地址 | 96亚洲精品久久 | 9992tv成人免费看片 | 色丁香婷婷 | 五月天婷婷丁香花 | 欧美性色网站 | 麻豆影视在线播放 | 在线观看av黄色 | 亚洲综合在线视频 | 免费一级日韩欧美性大片 | 色全色在线资源网 | 久久热亚洲 | 五月激情电影 | 日韩在线大片 | 91精选在线 | 91资源在线观看 | 日韩免费在线视频 | 91视频啪 | 四虎国产永久在线精品 | av高清在线观看 | 成年人免费av | 欧美性色综合网站 | 在线视频 91 | 91传媒视频在线观看 | 久色婷婷| 中文乱幕日产无线码1区 | av在线电影免费观看 | 亚州国产精品视频 | 天堂中文在线播放 | 人人爱人人舔 | 日韩大片免费在线观看 | 亚洲综合在线播放 | 久久精品波多野结衣 | 韩国精品一区二区三区六区色诱 | 国产手机在线精品 | 伊人va | 亚洲黄色av网址 | 手机av看片 | 成人a视频片观看免费 | 精品久久福利 | 日本精品久久久久中文字幕5 | 亚洲欧美日韩精品久久奇米一区 | 国产经典三级 | 亚洲日韩中文字幕在线播放 | 麻豆国产露脸在线观看 | 色资源网免费观看视频 | 精品一区二区免费 | 日韩久久午夜一级啪啪 | 国产精品久久久久久久久久久杏吧 | 一区在线观看 | 欧美另类xxx | 欧美十八| 最近日韩中文字幕中文 | 日韩v在线91成人自拍 | 99视频精品全部免费 在线 | 国产在线观看中文字幕 | 国产精品24小时在线观看 | 久久ww| 一区二区三区中文字幕在线观看 | 97在线观| 成片视频免费观看 | www.888av | 国产精品视频区 | 成人一级片免费看 | 免费观看黄 | 亚洲不卡av一区二区三区 | 国产一区二区免费在线观看 | 久久亚洲免费 | 黄色网www | 国产精品久久久久久久久久久不卡 | 在线免费观看视频 | 麻花豆传媒mv在线观看 | 日韩av午夜在线观看 | 免费性网站 | 久久久国产视频 | 国产精品高清免费在线观看 | 一区免费观看 | www.com在线观看| 97超碰伊人 | 特级毛片网 | av永久网址 | 色午夜| 欧美国产在线看 | 精品美女久久久久久免费 | 视频一区二区视频 | 成人一区二区三区中文字幕 | 日韩欧美一区二区三区在线 | 丁香六月婷婷开心 | 国产一级片在线播放 | 亚洲视频一区二区三区在线观看 | 中文日韩在线视频 | 久久激情视频网 | 91在线免费看片 | 色婷婷在线播放 | 7777xxxx | 久久综合婷婷 | 黄色小视频在线观看免费 | 免费视频久久久久 | 在线观看色网 | 亚洲 欧美 精品 | www夜夜 | 日韩videos高潮hd | 亚洲欧洲精品在线 | 国产h在线播放 | 国产日韩欧美在线看 | 24小时日本在线www免费的 | 日日干精品 | 一级理论片在线观看 | 黄色小说在线免费观看 | 永久免费的啪啪网站免费观看浪潮 | 久久综合色影院 | 手机看片99 | 天天插天天狠天天透 | 欧美性生交大片免网 | 免费电影一区二区三区 | 在线观看完整版免费 | 在线观看第一页 | 超碰在线97国产 | 欧美日韩国产二区三区 | 91麻豆精品国产91久久久久 | 国产午夜一区二区 | 国产免费精彩视频 | 日韩欧美精品在线视频 | 久久久在线 | 不卡的av片 | 久久成视频 | 日韩69av| 日韩在线免费看 | 久久国产成人午夜av影院宅 | 亚洲欧美日韩一二三区 | 国产亚洲精品久久久网站好莱 | 91完整版在线观看 | 久久久久久久久久久免费视频 | 国产视频在线看 | 国产高清久久久久 | 色婷婷激情五月 | 成人h视频在线播放 | 午夜精品福利一区二区三区蜜桃 | 欧美一级黄大片 | 一级a性色生活片久久毛片波多野 | 九九在线视频 | 欧美精品在线一区 | 国产97视频| 在线视频欧美亚洲 | 亚洲国产一区av | 国产精品一区二区你懂的 | 国产精品黄 | 免费日韩精品 | 久久影视一区二区 | 国产一区二区手机在线观看 | 中文在线字幕观看电影 | 色综合天天综合 | 久久国产精品第一页 | 99精品国产aⅴ | 日韩精品综合在线 | 天天射狠狠干 | 国产精品欧美激情在线观看 | 国产成人久久av免费高清密臂 | 97超碰在线资源 | 欧美a视频在线观看 | 成年人网站免费在线观看 | 免费高清男女打扑克视频 | 日本aaaa级毛片在线看 | 免费网站黄 | 亚洲人人爱 | 在线观看亚洲国产 | 成人免费在线电影 | 国产福利中文字幕 | 精品久久精品久久 | 欧美日韩精品在线一区二区 | 97超级碰碰碰视频在线观看 | 91av在线免费 | 伊人六月 | 在线观看国产一区二区 | 在线观看成人福利 | 一区二区三区播放 | 久草视频免费在线播放 | 麻豆视频91 | 成人av网址大全 | 夜夜摸夜夜爽 | 丁香5月婷婷久久 | 国产色在线视频 | 在线观看免费福利 | 视频一区视频二区在线观看 | 国产精品一区二区久久精品爱微奶 | 久久香蕉电影网 | 美女国产在线 | 亚洲精品一区二区三区高潮 | 欧美一级免费黄色片 | 偷拍福利视频一区二区三区 | 色婷婷激情综合 | 欧美成年黄网站色视频 | 色婷婷88av视频一二三区 | 精品国内自产拍在线观看视频 | 亚洲午夜小视频 | 九九九在线观看 | 久久成人国产 | 91精品久久久久久综合乱菊 | 中文久草 | 免费在线一区二区三区 | 天天干,天天干 | 黄色国产精品 | 国产精品嫩草在线 | 久久综合婷婷综合 | 成人四虎影院 | 91最新网址 | 日韩精品高清视频 | 天天色天天骑天天射 | 99精品国产99久久久久久97 | 手机av在线免费观看 | 一区三区视频在线观看 | 黄在线免费看 | 亚洲日本欧美 | 久久国产精品免费观看 | 91网在线看| 91精品视频观看 | 午夜久久精品 | 国内久久久 | 色五月色开心色婷婷色丁香 | 国内精品久久久精品电影院 | 欧美精品在线视频观看 | 亚洲欧洲国产视频 | 午夜影院一级片 | 久久视频这里有精品 | 欧美日韩一级久久久久久免费看 | 久久伊人精品一区二区三区 | 国产网红在线 | 在线国产高清 | 天天综合人人 | 小草av在线播放 | 麻豆91网站| 色就是色综合 | 婷婷丁香九月 | 日本黄色免费观看 | 六月激情丁香 | 人人射人人插 | 国产亚洲字幕 | 日韩一级片观看 | 久久久久久国产精品免费 | 在线观看91精品视频 | 偷拍区另类综合在线 | 五月婷婷六月综合 | 韩国一区二区三区视频 | 国产精品免费观看久久 | 午夜日b视频 | 超碰97人人射妻 | 色五月成人 | 亚洲高清精品在线 | 国产亚州精品视频 | 亚洲另类久久 | 狠狠色丁香婷婷综合基地 | jizzjizzjizz亚洲| 亚州中文av | 丁香久久五月 | 91在线观| 久久五月婷婷丁香 | 久久久高清一区二区三区 |