細分曲面過程並不對OpenGL典型的幾何圖元(點、線和三角形)進行操作,而是使用一個新的圖元(在OpenGL 4.0版本中新增的),稱為patch。patch由流水線中所有活動的著色階段處理。相比起來,其它圖元型別僅僅被頂點、片段和幾何著色器處理,而旁通細分曲面階段。實際上,如果有任一細分曲面著色器是活躍的,那麼傳遞任何其它幾何型別會產生一個GL_INVALID_OPERATION錯誤。相反地,如果企圖渲染一個patch而沒有任何細分曲面著色器(明確地說是一個細分曲面計算著色器;我們會看到細分曲面控制著色器是可選的),那麼將也會得到一個GL_INVALID_OPERATION錯誤。
patch僅僅是傳入到OpenGL的一列頂點列表,該列表在處理期間儲存它們的次序。當用細分曲面與patch進行渲染時,使用像glDrawArrays()這樣的渲染命令,並指定從繫結的頂點快取物件(VBO)將被讀出的頂點的總數,然後為該繪製呼叫進行處理。當用其它的OpenGL圖元進行渲染時,OpenGL基於在繪製呼叫中所指定的圖元型別而隱式地知道要使用多少頂點,比如使用三個頂點來繪製一個三角形。然後,當使用一個patch時,需要告訴OpenGL頂點陣列中要使用多少個頂點來組成一個patch,而這可以透過使用glPatchParameteri()進行指定。由同一個繪製呼叫所處理的patch,它們的尺寸(即每個patch的頂點個數)將是相同的。
void glPatchParameteri(GLenum pname, GLint value);
/**
* 使用value來指定一個patch中的頂點個數。pname必須設定為GL_PATCH_VERTICES。
* 如果value小於零或大於GL_MAX_PATCH_VERTICES,將會產一個GL_INVALID_ENUM的錯誤。
* 一個patch的預設頂點個數是三。如果一個patch的頂點個數小於引數value值,那麼該patch將被忽略,從而不會有幾何圖形產生。
*/
要指定一個patch,使用型別GL_PATCHES輸入到任一OpenGL繪製命令。以下程式碼描述了發射兩個patch,每個patch含有四個頂點,然後透過glDrawArrays繪製命令進行渲染。
複製程式碼
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);
每個patch的頂點首先由當前繫結的頂點著色器處理,然後用於初始化陣列gl_in,這個變數在細分曲面控制著色器中被隱式地宣告。gl_in中的元素個數與由glPatchParameteri()所指定的patch大小相同。在一個細分曲面著色器內部,變數gl_PatchVerticesIn提供了gl_in中的元素個數(就好比使用sizeof(gl_in) / sizeof(gl_in[0])進行查詢)。
細分曲面過程並不對OpenGL典型的幾何圖元(點、線和三角形)進行操作,而是使用一個新的圖元(在OpenGL 4.0版本中新增的),稱為patch。patch由流水線中所有活動的著色階段處理。相比起來,其它圖元型別僅僅被頂點、片段和幾何著色器處理,而旁通細分曲面階段。實際上,如果有任一細分曲面著色器是活躍的,那麼傳遞任何其它幾何型別會產生一個GL_INVALID_OPERATION錯誤。相反地,如果企圖渲染一個patch而沒有任何細分曲面著色器(明確地說是一個細分曲面計算著色器;我們會看到細分曲面控制著色器是可選的),那麼將也會得到一個GL_INVALID_OPERATION錯誤。
patch僅僅是傳入到OpenGL的一列頂點列表,該列表在處理期間儲存它們的次序。當用細分曲面與patch進行渲染時,使用像glDrawArrays()這樣的渲染命令,並指定從繫結的頂點快取物件(VBO)將被讀出的頂點的總數,然後為該繪製呼叫進行處理。當用其它的OpenGL圖元進行渲染時,OpenGL基於在繪製呼叫中所指定的圖元型別而隱式地知道要使用多少頂點,比如使用三個頂點來繪製一個三角形。然後,當使用一個patch時,需要告訴OpenGL頂點陣列中要使用多少個頂點來組成一個patch,而這可以透過使用glPatchParameteri()進行指定。由同一個繪製呼叫所處理的patch,它們的尺寸(即每個patch的頂點個數)將是相同的。
void glPatchParameteri(GLenum pname, GLint value);
/**
* 使用value來指定一個patch中的頂點個數。pname必須設定為GL_PATCH_VERTICES。
* 如果value小於零或大於GL_MAX_PATCH_VERTICES,將會產一個GL_INVALID_ENUM的錯誤。
* 一個patch的預設頂點個數是三。如果一個patch的頂點個數小於引數value值,那麼該patch將被忽略,從而不會有幾何圖形產生。
*/
要指定一個patch,使用型別GL_PATCHES輸入到任一OpenGL繪製命令。以下程式碼描述了發射兩個patch,每個patch含有四個頂點,然後透過glDrawArrays繪製命令進行渲染。
複製程式碼
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);
每個patch的頂點首先由當前繫結的頂點著色器處理,然後用於初始化陣列gl_in,這個變數在細分曲面控制著色器中被隱式地宣告。gl_in中的元素個數與由glPatchParameteri()所指定的patch大小相同。在一個細分曲面著色器內部,變數gl_PatchVerticesIn提供了gl_in中的元素個數(就好比使用sizeof(gl_in) / sizeof(gl_in[0])進行查詢)。