中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

微網(wǎng)站建設(shè)報(bào)價(jià)方案模板個(gè)人網(wǎng)頁(yè)制作成品

微網(wǎng)站建設(shè)報(bào)價(jià)方案模板,個(gè)人網(wǎng)頁(yè)制作成品,apk開(kāi)發(fā),教師企業(yè)頂崗日記網(wǎng)站開(kāi)發(fā)細(xì)分曲面著色器(Tessellation Shader)處于頂點(diǎn)著色器階段的下一個(gè)階段,我們可以看以下鏈接的OpenGL渲染流水線的圖:Rendering Pipeline Overview。它是由ATI在2001年率先設(shè)計(jì)出來(lái)的。 目錄 細(xì)分曲面著色器細(xì)分曲面Patch細(xì)分曲面控…

細(xì)分曲面著色器(Tessellation Shader)處于頂點(diǎn)著色器階段的下一個(gè)階段,我們可以看以下鏈接的OpenGL渲染流水線的圖:Rendering Pipeline Overview。它是由ATI在2001年率先設(shè)計(jì)出來(lái)的。


目錄

  • 細(xì)分曲面著色器
  • 細(xì)分曲面Patch
  • 細(xì)分曲面控制著色器
    • 生成輸出patch頂點(diǎn)
    • 細(xì)分曲面控制著色器變量
  • 控制細(xì)分曲面
    • 四邊形細(xì)分曲面
    • 等值線細(xì)分曲面
  • 旁通細(xì)分曲面控制著色器
  • 細(xì)分曲面圖元生成
    • 抽象patch
  • 細(xì)分曲面計(jì)算著色器
    • 指定圖元生成域
    • 指定生成圖元的面部朝向
    • 指定細(xì)分曲面坐標(biāo)的空間
    • 額外的細(xì)分曲面計(jì)算著色器layout選項(xiàng)
    • 指定一個(gè)頂點(diǎn)的位置
    • 細(xì)分曲面計(jì)算著色器變量
  • 參考資料
  • 完整工程項(xiàng)目代碼

細(xì)分曲面著色器

直到這個(gè)階段,對(duì)于操作幾何圖元而言,只有頂點(diǎn)著色器對(duì)我們可用。盡管使用頂點(diǎn)著色器可以使用不少圖形技術(shù),不過(guò)頂點(diǎn)著色器也確實(shí)存在一些限制。一個(gè)就是它們?cè)趫?zhí)行過(guò)程中無(wú)法創(chuàng)建額外的幾何圖形。它們僅僅更新與它們當(dāng)前所處理的頂點(diǎn)相關(guān)的數(shù)據(jù)。而且,它們甚至無(wú)法訪問(wèn)在當(dāng)前圖元中其它頂點(diǎn)的數(shù)據(jù)。

為了解決那些問(wèn)題,OpenGL流水線含有幾個(gè)其它著色器階段來(lái)打破這些限制。我們這里所要介紹的細(xì)分曲面著色器可以使用一個(gè)新的幾何圖元類(lèi)型,稱(chēng)為 patch(斑點(diǎn)、碎片),來(lái)生成一個(gè)三角形網(wǎng)格。

細(xì)分曲面著色器在OpenGL流水線中增添了兩個(gè)著色器階段來(lái)生成一個(gè)幾何圖元的網(wǎng)格。比起在使用頂點(diǎn)著色器時(shí)不得不指定所有線與三角形來(lái)形成自己的模型,在使用細(xì)分曲面時(shí),一開(kāi)始指定一個(gè) patch,它是一列排好序的頂點(diǎn)。當(dāng)一個(gè) patch 被渲染時(shí),細(xì)分曲面控制著色器Tessellation Control Shader) 先執(zhí)行,對(duì) patch 頂點(diǎn)進(jìn)行操作,并指定從 patch 中應(yīng)該生成多少幾何圖形。細(xì)分曲面控制著色器是可選的,我們后面會(huì)看到,如果不用它的話需要使用哪些條件。在細(xì)分曲面控制著色器完成之后,第二個(gè)著色器——細(xì)分曲面計(jì)算著色器Tessellation Evaluation Shader)使用細(xì)分曲面坐標(biāo)來(lái)放置所生成的頂點(diǎn),并且將它們發(fā)送到光柵化器,或發(fā)送到幾何著色器做進(jìn)一步處理。


細(xì)分曲面Patch

細(xì)分曲面過(guò)程并不對(duì)OpenGL典型的幾何圖元(點(diǎn)、線和三角形)進(jìn)行操作,而是使用一個(gè)新的圖元(在OpenGL 4.0版本中新增的),稱(chēng)為 patch。patch 由流水線中所有活動(dòng)的著色階段處理。相比起來(lái),其它圖元類(lèi)型僅僅被頂點(diǎn)、片段和幾何著色器處理,而旁通細(xì)分曲面階段。實(shí)際上,如果有任一細(xì)分曲面著色器是活躍的,那么傳遞任何其它幾何類(lèi)型會(huì)產(chǎn)生一個(gè) GL_INVALID_OPERATION 錯(cuò)誤。相反地,如果企圖渲染一個(gè) patch 而沒(méi)有任何細(xì)分曲面著色器(明確地說(shuō),是一個(gè)細(xì)分曲面計(jì)算著色器;我們會(huì)看到細(xì)分曲面控制著色器是可選的),那么將也會(huì)得到一個(gè) GL_INVALID_OPERATION 錯(cuò)誤。

patch 僅僅是傳入到OpenGL的一列頂點(diǎn)列表,該列表在處理期間保存它們的次序。當(dāng)用細(xì)分曲面與 patch 進(jìn)行渲染時(shí),使用像 glDrawArrays() 這樣的渲染命令,并指定從綁定的頂點(diǎn)緩存對(duì)象(VBO)將被讀出的頂點(diǎn)的總數(shù),然后為該繪制調(diào)用進(jìn)行處理。當(dāng)用其它的OpenGL圖元進(jìn)行渲染時(shí),OpenGL基于在繪制調(diào)用中所指定的圖元類(lèi)型而隱式地知道要使用多少頂點(diǎn),比如使用三個(gè)頂點(diǎn)來(lái)繪制一個(gè)三角形。然后,當(dāng)使用一個(gè) patch 時(shí),需要告訴OpenGL頂點(diǎn)數(shù)組中要使用多少個(gè)頂點(diǎn)來(lái)組成一個(gè) patch,而這可以通過(guò)使用 glPatchParameteri() 進(jìn)行指定。由同一個(gè)繪制調(diào)用(drawcall)所處理的所有指定的 patch,它們的尺寸(即每個(gè)patch的頂點(diǎn)個(gè)數(shù))將是相同的。

void glPatchParameteri(GLenum pname, GLint value);
/*** 使用value來(lái)指定一個(gè)patch中的頂點(diǎn)個(gè)數(shù)。pname必須設(shè)置為GL_PATCH_VERTICES。* 如果value小于零或大于GL_MAX_PATCH_VERTICES,將會(huì)產(chǎn)一個(gè)GL_INVALID_ENUM的錯(cuò)誤。* 一個(gè)patch的默認(rèn)頂點(diǎn)個(gè)數(shù)是三。如果一個(gè)patch的頂點(diǎn)個(gè)數(shù)小于參數(shù)value值,那么該patch將被忽略,從而不會(huì)有幾何圖形產(chǎn)生。
*/

要指定一個(gè) patch,使用類(lèi)型 GL_PATCHES 輸入到任一OpenGL繪制命令。以下代碼描述了發(fā)射兩個(gè) patch,每個(gè) patch 含有四個(gè)頂點(diǎn),然后通過(guò) glDrawArrays 繪制命令進(jìn)行渲染。

GLfloat vertices[][2] = {{-0.75f, -0.25f}, {-0.25f, -0.25f}, {-0.25f, 0.25f}, {-0.75f, 0.25f},{0.25f, -0.25f}, {0.75f, -0.25f}, {0.75f, -0.25f}, {0.75f, 0.25f}, {0.25f, 0.25f}
};glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(vPos, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glPatchParameteri(GL_PATCH_VERTICES, 4);
glDrawArrays(GL_PATCHES, 0, 8);

每個(gè) patch 的頂點(diǎn)首先由當(dāng)前綁定的頂點(diǎn)著色器處理,然后用于初始化數(shù)組 gl_in,這個(gè)變量在細(xì)分曲面控制著色器中被隱式地聲明。gl_in 中的元素個(gè)數(shù)與由 glPatchParameteri() 所指定的 patch 大小相同。在一個(gè)細(xì)分曲面著色器內(nèi)部,變量 gl_PatchVerticesIn 提供了 gl_in 中的元素個(gè)數(shù)(就好比使用 sizeof(gl_in) / sizeof(gl_in[0]) 進(jìn)行查詢(xún))。


細(xì)分曲面控制著色器

一旦應(yīng)用發(fā)射了一個(gè) patch,細(xì)分曲面控制著色器就會(huì)被調(diào)用(如果有所綁定的話)并且負(fù)責(zé)完成以下行動(dòng):

  • 生成細(xì)分曲面輸出 patch 頂點(diǎn),傳遞到細(xì)分曲面計(jì)算著色器,以及更新任一每個(gè)頂點(diǎn)的,或每個(gè) patch 的屬性值,若有必要的話。
  • 指定細(xì)分曲面程度因子,控制圖元生成器的操作。這些是特殊的細(xì)分曲面控制著色器變量,稱(chēng)為 gl_TessLevelInnergl_TessLevelOuter,并在細(xì)分曲面控制著色器中隱式聲明。

我們將依次討論這些行動(dòng)的每一個(gè)。


生成輸出patch頂點(diǎn)

細(xì)分曲面控制器使用由應(yīng)用所指定的頂點(diǎn)——這些頂點(diǎn)我們稱(chēng)為輸入 patch 頂點(diǎn)(作為頂點(diǎn)著色器的輸出)——來(lái)生成一組新的頂點(diǎn),這些新的頂點(diǎn)為輸出 patch 頂點(diǎn)。它們存放在細(xì)分曲面控制著色器的 gl_out 數(shù)組中。細(xì)分曲面控制著色器在產(chǎn)出輸出** patch** 頂點(diǎn)時(shí),可以修改傳遞自應(yīng)用的值(比如頂點(diǎn)屬性),也可以創(chuàng)建或移除來(lái)自輸入 patch 頂點(diǎn)中的頂點(diǎn)。

使用一個(gè) layout 構(gòu)造在細(xì)分曲面控制著色器中指定輸出 patch 頂點(diǎn)的個(gè)數(shù)。下面語(yǔ)句描述了設(shè)置輸出 patch 頂點(diǎn)的個(gè)數(shù)為16。

layout (vertices = 16) out;

layout 指示符中的 vertices 參數(shù)所設(shè)置的值做了兩件事情:它設(shè)置了輸出 patch 頂點(diǎn) gl_out 的大小;并且指定了細(xì)分曲面控制著色器將被執(zhí)行多少次:對(duì)每個(gè)輸出 patch 頂點(diǎn)執(zhí)行一次。

為了確定正在處理哪個(gè)輸出頂點(diǎn),細(xì)分曲面控制著色器可以使用 gl_InvocationID 變量。該變量最經(jīng)常被用作為 gl_out 數(shù)組的一個(gè)索引。當(dāng)一個(gè)細(xì)分曲面控制著色器在執(zhí)行時(shí),它具有對(duì)所有 patch 頂點(diǎn)數(shù)據(jù)的訪問(wèn),包括輸入頂點(diǎn)和輸出頂點(diǎn)。這可能會(huì)導(dǎo)致發(fā)射一次著色器調(diào)用,該調(diào)用需要使用來(lái)自另一個(gè)著色器調(diào)用的數(shù)據(jù)值,但是那個(gè)著色器調(diào)用尚未發(fā)生。細(xì)分曲面控制著色器可以使用GLSL的 barrier() 函數(shù),該函數(shù)使得對(duì)一個(gè)輸入 patch 的所有控制著色器的執(zhí)行,并等待所有這些著色器的執(zhí)行到達(dá)那個(gè)函數(shù)的調(diào)用點(diǎn),從而確保了可能要設(shè)置的所有數(shù)據(jù)值將被計(jì)算。

細(xì)分曲面控制著色器的一個(gè)普遍的習(xí)慣用法僅僅是將輸入 patch 頂點(diǎn)輸出到此著色器的外面。下面的例子描述了帶有四個(gè)頂點(diǎn)的一個(gè)輸出 patch。

#version 410 corelayout (vertices = 4) out;void main(void)
{gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;// 下面設(shè)置細(xì)分曲面程度
}

細(xì)分曲面控制著色器變量

gl_in 數(shù)組實(shí)際上是一個(gè)結(jié)構(gòu)體的數(shù)組,每個(gè)元素被定義為:

in gl_PerVertex {vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];}gl_in[gl_PatchVerticesIn];

并且對(duì)于每個(gè)需要向下一個(gè)階段傳遞的值(比如,向下傳遞到細(xì)分曲面計(jì)算著色器),需要進(jìn)行相應(yīng)地賦值。如上述代碼片段所述,傳遞了 gl_Position 變量。

gl_out 數(shù)組具有相同的結(jié)構(gòu)體成員,不過(guò)數(shù)組大小與 gl_in 不同,它是由 gl_PatchVerticesOut 來(lái)指定的。而這個(gè)值則是在細(xì)分曲面控制器中的 out 這一 layout 限定符中設(shè)置。此外,以下標(biāo)量值用于確定正在被著色的圖元和輸出頂點(diǎn):

  • gl_InvocationID:當(dāng)前細(xì)分曲面著色器的輸出頂點(diǎn)的調(diào)用索引
  • gl_PrimitiveID:當(dāng)前輸入 patch 的圖元索引
  • gl_PatchVerticesIn:輸入patch中的頂點(diǎn)個(gè)數(shù),它作為 gl_in 數(shù)組變量中的元素個(gè)數(shù)
  • gl_PatchVerticesOut:輸出 patch 中的頂點(diǎn)個(gè)數(shù),它作為 gl_out 數(shù)組變量中的元素個(gè)數(shù)

如果我們需要額外的基于每個(gè)頂點(diǎn)的屬性值,或?yàn)檩斎牖驗(yàn)檩敵?#xff0c;那么這需要在我們的細(xì)分曲面控制著色器中將它們聲明為 inout 數(shù)組。一個(gè)輸入數(shù)組的大小需要與輸入 patch 大小相同,或者可以被聲明為缺省大小的,這樣OpenGL將會(huì)為其所有值適當(dāng)?shù)胤峙淇臻g。類(lèi)似地,每個(gè)頂點(diǎn)的輸出屬性需要與輸出 patch 中的頂點(diǎn)個(gè)數(shù)相一致,也可以為輸出屬性聲明為缺省大小的。輸出屬性值將會(huì)被傳遞到細(xì)分曲面計(jì)算著色器,作為其輸入屬性值。

比如:

#version 410 corelayout (vertices = 4) out;in vec4 vertexCoeffs1[4];    // 我們假定指定一個(gè)輸入patch含有4個(gè)頂點(diǎn)
in vec4 vertexCoeffs2[];     // 這里使用缺省大小的數(shù)組變量,OpenGL將會(huì)自動(dòng)為其分配大小out vec2 vertexTexCoord1[4];    // 這里需要用上面out的layout (vertices)值一致
out vec2 vertexTexCoord2[];     // 這里使用缺省大小的數(shù)組變量,OpenGL將會(huì)自動(dòng)為其分配大小void main(void)
{// Do something here
}

上面給出的是基于逐個(gè)頂點(diǎn)的屬性值,它們可以用 gl_InvocationID 作為索引,不過(guò)要注意的是,gl_InvocationID 標(biāo)識(shí)的是當(dāng)前細(xì)分曲面著色器的輸出頂點(diǎn)的調(diào)用索引。我們可以使用 patch 限定符來(lái)聲明每個(gè) patch 的輸出變量。每個(gè) patch 的變量不是以數(shù)組方式定義而是以普通單實(shí)例變量的方式來(lái)定義。當(dāng)然,我們也可以將它們定義為數(shù)組。所有細(xì)分曲面控制著色器的調(diào)用看到的都是同一個(gè) patch 變量。比如:

#version 410 corepatch out vec4 data;layout (vertices = 4) out;void main(void)
{// Do something heredata = vec4(1.0, 0.0, 0.0, 1.0);
}

這里,我們定義了一個(gè)標(biāo)識(shí)符為 data 的 patch 輸出變量。對(duì)于每次細(xì)分曲面控制著色器的調(diào)用,data 的值都被寫(xiě)為 vec4(1.0, 0.0, 0.0, 1.0)。因此,任一細(xì)分曲面控制著色器可以寫(xiě)基于每個(gè) patch 的輸出變量;實(shí)際上,所有細(xì)分曲面控制著色器的調(diào)用一般都將寫(xiě)到一個(gè)基于每個(gè) patch 的變量。只要它們都寫(xiě)相同的值,那么一切都是良好的。


控制細(xì)分曲面

一個(gè)細(xì)分曲面控制著色器的另一個(gè)功能是指定對(duì)輸出 patch 細(xì)分多少。然而我們還沒(méi)詳細(xì)地討論細(xì)分曲面計(jì)算著色器,它們控制用于渲染的輸出 patch 的類(lèi)型,結(jié)果也就是細(xì)分曲面所發(fā)生的域。OpenGL支持三種細(xì)分曲面域:四邊形,三角形,和等值線集合。這些通過(guò)細(xì)分曲面計(jì)算著色器中的 inlayout 進(jìn)行指定。

細(xì)分曲面的數(shù)量通過(guò)指定兩組值:內(nèi)部和外部細(xì)分曲面程度來(lái)控制的。外部細(xì)分曲面的值控制域的周邊是如何劃分的,然后存放在一個(gè)隱式聲明的名為 gl_TessLevelOuter 的含有四個(gè)元素的數(shù)組中。而內(nèi)部細(xì)分曲面程度指定了域的內(nèi)部如何進(jìn)行劃分,然后存放在一個(gè)名為 gl_TessLevelInner 的含有兩個(gè)元素的數(shù)組中。所有細(xì)分曲面程度因子是浮點(diǎn)值,并且我們將會(huì)看到浮點(diǎn)值在細(xì)分曲面上以一個(gè)比特的效果。最后一點(diǎn)是,盡管隱式聲明的細(xì)分曲面程度因子數(shù)組的維度是固定的,不過(guò)從那些數(shù)組所使用的值的個(gè)數(shù)依賴(lài)于細(xì)分曲面域的類(lèi)型。下面來(lái)看看這兩個(gè)OpenGL內(nèi)建的細(xì)分曲面輸出 patch 變量的聲明:

patch out float gl_TessLevelOuter[4];
patch out float gl_TessLevelInner[2];

理解外部與內(nèi)部細(xì)分曲面程度如何操作是讓細(xì)分曲面做我們想要做的事情的關(guān)鍵。每個(gè)細(xì)分曲面程度因子指定了對(duì)一個(gè)區(qū)域劃分多少條“線段”,以及生成多少細(xì)分曲面坐標(biāo)與幾何圖元。這種劃分如何完成根據(jù)不同域類(lèi)型而有所不同。我們將依次討論域的每種類(lèi)型。


四邊形細(xì)分曲面

使用四邊形域可能是最直觀的,因此我們先介紹這種類(lèi)型。當(dāng)輸入 patch 形狀為矩形時(shí),這很有用,當(dāng)我們可能使用二維的樣條曲面時(shí),比如 Bézier 曲面。四邊形域使用所有內(nèi)部和外部細(xì)分曲面程度來(lái)劃分單位正方形。比如,如果我們用以下代碼來(lái)設(shè)置細(xì)分曲面程度因子,那么OpenGL將會(huì)把四邊形域細(xì)分為如下圖所示的樣子。

#version 410 corelayout (vertices = 4) out;void main(void)
{gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;// 下面設(shè)置細(xì)分曲面程度gl_TessLevelInner[0] = 3.0;     // 內(nèi)部劃分3條垂直區(qū)域,即內(nèi)部新增2列頂點(diǎn)gl_TessLevelInner[1] = 4.0;     // 內(nèi)部劃分4條水平區(qū)域,即內(nèi)部新增3行頂點(diǎn)gl_TessLevelOuter[0] = 2.0;     // 左邊2條線段gl_TessLevelOuter[1] = 3.0;     // 下邊3條線段gl_TessLevelOuter[2] = 4.0;     // 右邊4條線段gl_TessLevelOuter[3] = 5.0;     // 上邊5條線段
}

下圖為上述細(xì)分曲面控制著色器可能會(huì)得到的幾何圖形樣子。

黃線垂直劃分綠線水平劃分最終完整
quad_yellowquad_greenquad_dst

上圖中,三條黃色線條表示三條垂直區(qū)域;四條綠色線條表示四條水平區(qū)域。

注意,外部細(xì)分曲面程度值對(duì)應(yīng)于圍繞周邊的每條邊的線段個(gè)數(shù),而內(nèi)部細(xì)分曲面程度指定了域的內(nèi)部空間中水平與垂直方向上有多少個(gè)“區(qū)域”。使用虛線則是將整個(gè)域用三角形進(jìn)行劃分。域的三角形劃分是依賴(lài)于實(shí)現(xiàn)的。實(shí)心圓點(diǎn)表示細(xì)分曲面坐標(biāo),每個(gè)坐標(biāo)都會(huì)提供給細(xì)分曲面計(jì)算著色器,作為其輸入。在四邊形域的情況下,細(xì)分曲面坐標(biāo)有兩個(gè)坐標(biāo)值 (u, v),兩者值的范圍都在 [0, 1] 范圍內(nèi),并且每個(gè)細(xì)分曲面坐標(biāo)將傳遞到細(xì)分曲面計(jì)算著色器中,作為它的一次調(diào)用。


等值線細(xì)分曲面

類(lèi)似于四邊形域,等值線域也生成 (u, v) 對(duì)作為給細(xì)分曲面計(jì)算著色器的細(xì)分曲面坐標(biāo)。然而,等值線僅僅使用外部細(xì)分曲面程度的兩個(gè)元素值來(lái)判定劃分量(這里沒(méi)有用到內(nèi)部細(xì)分曲面程度)。

下面是設(shè)置等值線域的細(xì)分曲面程度:

gl_TessLevelOuter[0] = 6;      // 6條等值線
gl_TessLevelOuter[1] = 8;      // 每條等值線被劃分為8條線段

下圖為可能的結(jié)果圖形:

patch_lines


旁通細(xì)分曲面控制著色器

正如我們所提到過(guò)的,細(xì)分曲面著色器往往只是一個(gè)直通著色器,將數(shù)據(jù)從輸入直接到輸出。在這種情況下,我們實(shí)際上可以使一個(gè)細(xì)分曲面著色器進(jìn)行旁通,僅僅使用主機(jī)端OpenGL API來(lái)設(shè)置細(xì)分曲面程度因子。使用 glPatchParameterfv() 函數(shù)來(lái)設(shè)置內(nèi)部與外部細(xì)分曲面程度。

void glPatchParameterfv(GLenum pname, const GLfloat *values);/*** 當(dāng)沒(méi)有細(xì)分曲面控制著色器時(shí),設(shè)置內(nèi)部與外部細(xì)分曲面程度。* 參數(shù)pname要么是GL_PATCH_DEFAULT_OUTER_LEVEL,要么是GL_PATCH_DEFAULT_INNER_LEVEL。* 當(dāng)pname是GL_PATCH_DEFAULT_OUTER_LEVEL時(shí),參數(shù)values必須是含有四個(gè)單精度浮點(diǎn)值的數(shù)組,指定四個(gè)外部細(xì)分曲面程度。* 類(lèi)似地,當(dāng)pname是GL_PATCH_DEFAULT_INNER_LEVEL時(shí),values必須是含有兩個(gè)單精度浮點(diǎn)值的數(shù)組,指定兩個(gè)內(nèi)部細(xì)分曲面程度。
*/

細(xì)分曲面圖元生成

圖元生成是一個(gè)固定功能階段,負(fù)責(zé)從輸入 patch 來(lái)創(chuàng)建一組新的圖元。此階段僅當(dāng)一個(gè)細(xì)分曲面計(jì)算著色器在當(dāng)前程序或程序流水線中活動(dòng)時(shí)才會(huì)執(zhí)行。圖元生成受以下因素影響:

  • 細(xì)分曲面程度
  • 被細(xì)分的頂點(diǎn)的空間劃分,這個(gè)由細(xì)分曲面計(jì)算著色器階段進(jìn)行定義。它可以是 equal_spacing、fractional_even_spacingfractional_odd_spacing
  • 由后續(xù)細(xì)分曲面著色器所定義的圖元類(lèi)型,即 triangles、quadsisolines。細(xì)分曲面計(jì)算著色器也可以迫使細(xì)分曲面的生成作為一系列的點(diǎn),而不是三角形或線。這個(gè)可以通過(guò) point_mode 來(lái)指定。
  • 由后續(xù)細(xì)分曲面計(jì)算著色器所定義的圖元生成次序,比如 cw(順時(shí)針)或 ccw(逆時(shí)針)。

抽象patch

注意,圖元生成不受細(xì)分曲面控制著色器中用戶(hù)定義的輸出影響(或當(dāng)沒(méi)有細(xì)分曲面控制著色器時(shí),也不受頂點(diǎn)著色器的影響),不受細(xì)分曲面控制著色器的輸出patch大小影響,也不受任一每個(gè) patch 的細(xì)分曲面控制著色器輸出的影響,而只受細(xì)分曲面程度的影響。細(xì)分曲面階段的圖元生成部分完全對(duì)實(shí)際的頂點(diǎn)坐標(biāo)與其它 patch 數(shù)據(jù)是不可見(jiàn)的。

圖元生成系統(tǒng)的目的是確定要生成多少個(gè)頂點(diǎn),用哪個(gè)次序來(lái)生成它們,以及用哪種圖元來(lái)構(gòu)造它們。實(shí)際為這些頂點(diǎn)的每個(gè)頂點(diǎn)的數(shù)據(jù),諸如位置、顏色等等,是通過(guò)細(xì)分曲面計(jì)算著色器來(lái)生成的,基于圖元生成器所提供的信息。

因?yàn)檫@種對(duì)分,圖元生成器對(duì)可以被認(rèn)為是一個(gè)“抽象patch”的東東進(jìn)行操作。它并不從細(xì)分曲面控制器的輸出來(lái)看patch;它僅考慮一個(gè)抽象四邊形、三角形或等值線塊的細(xì)分曲面。

依賴(lài)于抽象 patch 類(lèi)型,圖元生成器計(jì)算不同數(shù)量的細(xì)分曲面程度并應(yīng)用不同的細(xì)分曲面算法。每個(gè)所生成的頂點(diǎn)在一個(gè)抽象 patch 內(nèi)具有一個(gè)規(guī)格化的位置(即,坐標(biāo)范圍在 [0, 1] 之內(nèi))。這個(gè)位置具有兩個(gè)或三個(gè)分量,依賴(lài)于patch的類(lèi)型。這些坐標(biāo)通過(guò)內(nèi)建的

in vec3 gl_TessCoord;

輸入提供給細(xì)分曲面計(jì)算著色器。


細(xì)分曲面計(jì)算著色器

OpenGL細(xì)分曲面流水線的最后一個(gè)階段就是細(xì)分曲面計(jì)算著色器執(zhí)行。綁定的細(xì)分曲面計(jì)算著色器對(duì)圖元生成器發(fā)射的每個(gè)細(xì)分曲面坐標(biāo)逐個(gè)執(zhí)行,并負(fù)責(zé)確定從細(xì)分曲面坐標(biāo)所得到的頂點(diǎn)的位置。我們將看到,細(xì)分曲面計(jì)算著色器看上去與頂點(diǎn)著色器類(lèi)似,將頂點(diǎn)變換到屏幕位置(除非細(xì)分曲面著色器的數(shù)據(jù)將被進(jìn)一步由幾何著色器來(lái)處理)。

配置一個(gè)細(xì)分曲面計(jì)算著色器的第一步是配置圖元生成器,這通過(guò)使用一個(gè) layout 指示符來(lái)完成。其參數(shù)指定了細(xì)分曲面域與后續(xù)所生成的圖元的類(lèi)型;實(shí)體圖元的面部朝向(用于做面剔除);以及在圖元生成期間如何應(yīng)用細(xì)分曲面程度。


指定圖元生成域

我們現(xiàn)在將描述細(xì)分曲面計(jì)算著色器的 in 這個(gè) layout 的參數(shù)。首先,我們先談?wù)撝付?xì)分曲面域。我們之前已經(jīng)提及過(guò),一共有三種類(lèi)型的域來(lái)生成細(xì)分曲面坐標(biāo):

  • quads——單位正方形中的一個(gè)矩形域;域坐標(biāo):帶有范圍在 [0, 1] 內(nèi)的 u, v 值的一個(gè)個(gè)坐標(biāo)對(duì) (u, v)。
  • triangles——使用重心坐標(biāo)的一個(gè)三角形域;域坐標(biāo):帶有范圍在 [0, 1] 內(nèi)的a、b、c三個(gè)值的坐標(biāo) (a, b, c),這里 a + b + c = 1。
  • isolines——跨單位正方形的一組線;域坐標(biāo):u 值范圍在 [0, 1],v 值范圍在 [0, 1) 范圍的 (u, v) 坐標(biāo)對(duì)。

指定生成圖元的面部朝向

與OpenGL中任何填充的圖元一樣,所發(fā)射的頂點(diǎn)的次序決定了圖元的臉部朝向。由于我們?cè)谶@種情況下不直接發(fā)射頂點(diǎn),而只是讓圖元生成器為我們來(lái)做,不過(guò)我們需要告訴圖元生成器我們圖元的右手旋轉(zhuǎn)方向。在 layout 指示符中,指定 cw 為順時(shí)針旋轉(zhuǎn),ccw 為逆時(shí)針。


指定細(xì)分曲面坐標(biāo)的空間

此外,我們可以控制外部細(xì)分曲面程度的浮點(diǎn)值如何用在確定周邊的細(xì)分曲面坐標(biāo)生成上。(內(nèi)部細(xì)分曲面程度受這些選項(xiàng)影響。)

  • equal_spacing——細(xì)分曲面程度被裁減到 [1, max] 范圍內(nèi),然后取整到下一個(gè)最大整數(shù)值。
  • fractional_even_spacing——值被裁減到 [2, max] 范圍內(nèi),然后取整到下一個(gè)最大偶整數(shù)值n。邊然后被劃分為 n-2 條等長(zhǎng)部分,以及兩個(gè)剩余部分,每個(gè)在一端,剩余部分長(zhǎng)度可能比其它長(zhǎng)度要短。
  • fractional_odd_spacing——值被裁減到 [1, max-1] 范圍內(nèi),然后取整到下一個(gè)最大奇整數(shù)值n。邊然后被劃分為 n-2 條等長(zhǎng)部分,以及兩個(gè)剩余部分,每個(gè)在一端,剩余部分長(zhǎng)度可能比其它長(zhǎng)度要短。

額外的細(xì)分曲面計(jì)算著色器layout選項(xiàng)

最后,如果我們想輸出點(diǎn),而不是等值線或填充區(qū)域的話,我們可以應(yīng)用 point_mode 選項(xiàng)。該選項(xiàng)將為每個(gè)由細(xì)分曲面計(jì)算著色器所處理的頂點(diǎn)渲染一單個(gè)點(diǎn)。

layout 指示符內(nèi)的選項(xiàng)的次序不重要。下面例子描述的是一個(gè)生成三角形域的圖元,使用相等空間,逆時(shí)針?lè)较虻娜切?#xff0c;但只渲染點(diǎn),而不是互聯(lián)的圖元。

layout (triangles, equal_spacing, ccw, point_mode) in;

指定一個(gè)頂點(diǎn)的位置

從細(xì)分曲面控制著色器輸出的頂點(diǎn)(即,在 gl_out 數(shù)組中的 gl_Position 的值)在計(jì)算著色器中的 gl_in 變量中可用。當(dāng)它們與細(xì)分曲面坐標(biāo)相結(jié)合時(shí),可以用于生成輸出頂點(diǎn)的位置。

細(xì)分曲面坐標(biāo)在變量 gl_TessCoord 中提供給計(jì)算著色器。在下面例子中我們使用相等空間劃分的四邊形來(lái)渲染一個(gè)簡(jiǎn)單的 patch。在這個(gè)例子中,細(xì)分曲面坐標(biāo)用于對(duì)表面進(jìn)行上色,然后此例子也描述了如何計(jì)算頂點(diǎn)坐標(biāo)。我們這里要注意的是,gl_in 中的 gl_Position 相當(dāng)于原始的 patch 每個(gè)頂點(diǎn)的坐標(biāo),而 gl_TessCoord 則是經(jīng)過(guò)細(xì)分曲面之后的新增細(xì)分曲面頂點(diǎn),這些頂點(diǎn)的坐標(biāo)值是被規(guī)格化在 [0, 1] 范圍內(nèi)的。我們通過(guò)以原 patch 的頂點(diǎn)坐標(biāo)與當(dāng)前處理的細(xì)分曲面頂點(diǎn)坐標(biāo)做相應(yīng)的插值計(jì)算來(lái)獲得此細(xì)分曲面頂點(diǎn)最后輸出的坐標(biāo)值。我們?cè)诩?xì)分曲面計(jì)算著色器中可以訪問(wèn)所有 gl_in 數(shù)組的元素,即每次調(diào)用可以訪問(wèn)當(dāng)前 patch 所有輸入的頂點(diǎn)坐標(biāo)。

#version 410 corelayout (quads, equal_spacing, ccw) in;out vec4 color;void main(void)
{float u = gl_TessCoord.x;float omu = 1 - u;    // omu為1減去"u"float v = gl_TessCoord.y;float omv = 1 - v;    // omv為1減去"v"color = gl_TessCoord; // color最后給到片段著色器時(shí),值為(gl_TessCoord.x, gl_TessCoord.y, 0.0, 1.0)gl_Position = omu * omv * gl_in[0].gl_Position +u * omv * gl_in[1].gl_Position +u * v * gl_in[2].gl_Position +omu * v * gl_in[3].gl_Position;
}

細(xì)分曲面計(jì)算著色器變量

與細(xì)分曲面控制著色器類(lèi)似,細(xì)分曲面計(jì)算著色器也有 gl_in 數(shù)組,它是一個(gè)結(jié)構(gòu)體數(shù)組,每個(gè)元素如下定義:

in gl_PerVertex {vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];
} gl_in[gl_PatchVerticesIn];

輸出頂點(diǎn)的數(shù)據(jù)被存放在一個(gè)接口塊中,如下定義:

out gl_PerVertex {vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];
};

參考資料

  • 《OpenGL Programming Guide Eighth Edition – The Official Guide tyo Learning OpenGL, Version 4.3》
  • Tessellation

完整工程項(xiàng)目代碼

OpenGL4.1 Tessellation Shader使用demo(基于macOS)

http://m.risenshineclean.com/news/65812.html

相關(guān)文章:

  • 網(wǎng)站建設(shè)用什么視頻播放器網(wǎng)絡(luò)推廣人員
  • 如何做jquery音樂(lè)網(wǎng)站自媒體營(yíng)銷(xiāo)方式有哪些
  • 蘭州網(wǎng)站建設(shè)尚美收錄網(wǎng)站有哪些
  • 高明專(zhuān)業(yè)網(wǎng)站建設(shè)報(bào)價(jià)谷歌seo優(yōu)化公司
  • 長(zhǎng)沙微網(wǎng)站開(kāi)發(fā)網(wǎng)絡(luò)公司網(wǎng)絡(luò)推廣
  • 做時(shí)時(shí)彩網(wǎng)站需要什么做電商如何起步
  • 美妝網(wǎng)站開(kāi)發(fā)背景整合網(wǎng)絡(luò)營(yíng)銷(xiāo)外包
  • 百度文庫(kù)怎么做網(wǎng)站排名培訓(xùn)心得總結(jié)
  • 織夢(mèng)網(wǎng)站專(zhuān)題模板推廣方式和推廣渠道
  • 南京推廣平臺(tái)有哪些seo 最新
  • 嘉善建設(shè)工程質(zhì)量監(jiān)督站網(wǎng)站瀏覽器2345網(wǎng)址導(dǎo)航下載安裝
  • 個(gè)人網(wǎng)站公安備案流程seo技巧是什么
  • 怎樣進(jìn)行公司網(wǎng)站建設(shè)企業(yè)網(wǎng)站模板源碼
  • 施工企業(yè)資質(zhì)包括哪些優(yōu)化大師手機(jī)版下載安裝app
  • 知名網(wǎng)站制作全包怎么建自己的網(wǎng)站?
  • 文化建設(shè)的具體措施seo是什么崗位簡(jiǎn)稱(chēng)
  • 重慶哪家在做網(wǎng)站建設(shè)競(jìng)價(jià)廣告
  • 網(wǎng)站在哪里搜索北京seo包年
  • 鎮(zhèn)江網(wǎng)站建設(shè)找思創(chuàng)網(wǎng)絡(luò)今日頭條熱榜
  • 南京越城建設(shè)集團(tuán)有限公司網(wǎng)站小紅書(shū)kol推廣
  • 佛山網(wǎng)站排名推廣有沒(méi)有永久免費(fèi)crm
  • 個(gè)人網(wǎng)站備案容易嗎最近最新新聞
  • 萬(wàn)網(wǎng)網(wǎng)站空間服務(wù)范圍及費(fèi)用seo的形式有哪些
  • 拉薩網(wǎng)站制作公司新余seo
  • 長(zhǎng)沙市網(wǎng)站推廣公司推廣計(jì)劃書(shū)范文
  • 網(wǎng)站抓取壓力高重慶排名優(yōu)化整站優(yōu)化
  • 全國(guó)哪個(gè)餐飲品牌的網(wǎng)站做的好處百度關(guān)鍵詞屏蔽
  • 國(guó)內(nèi)互聯(lián)網(wǎng)大廠有哪些合肥seo建站
  • 短視頻素材網(wǎng)站免費(fèi)大推薦短視頻seo營(yíng)銷(xiāo)系統(tǒng)
  • 學(xué)校網(wǎng)站建設(shè)方案模板下載表白網(wǎng)站制作