溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Tessellation(細(xì)分曲面)

發(fā)布時(shí)間:2020-08-06 14:27:19 來源:網(wǎng)絡(luò) 閱讀:601 作者:萌谷王 欄目:游戲開發(fā)

Tessellation is the process of breaking a high-order primitive (which is known as a patch in OpenGL) into many smaller(Tessellation就是把很多高階的圖元變成很多小圖元的過程), simpler primitives such as triangles for rendering(比如說三角形這種簡單的圖元). OpenGL includes a fixed-function, configurable tessellation engine that is able to break up quadrilaterals, triangles, and lines into a potentially large number of smaller points, lines, or triangles that can be directly consumed by the normal rasterization hardware further down the pipeline(OpenGL的固定功能部分,可以通過配置tessellation引擎,能夠?qū)⒁恍┧倪呅?、三角形、線變成大量的硬件光柵化時(shí)可以支持處理的小的點(diǎn)、線和三角形). Logically, the tessellation phase sits directly after the vertex shading stage in the OpenGL pipeline(邏輯上來說,tessellation階段是緊接著vertex shader階段的) and is made up of three parts: the tessellation control shader, the fixed-function tessellation engine, and the tessellation evaluation shader( 并且tessellation階段由三個(gè)部分組成:the tessellation control shader, the fixed-function tessellation engine, and the tessellation evaluation shader)

Tessellation Control Shaders

The first of the three tessellation phases is the tessellation control shader (TCS;sometimes known as simply the control shader). (tessellation shader的第一部分叫tessellation control shader) This shader takes its input from the vertex shader and is primarily responsible for two things(它的輸入數(shù)據(jù)是由vertex shader給的,它主要干兩件事): the determination of the level of tessellation that will be sent to the tessellation engine(第一件是確定發(fā)送給tessellation引擎的tessellation的級別), and the generation of data that will be sent to the tessellation evaluation shader that is run after tessellation has occurred(以及生成將會被在tessellation發(fā)生后,tessellation evaluation shader使用的數(shù)據(jù))

Tessellation in OpenGL works by breaking down high-order surfaces known as patches into points, lines, or triangles.(在OpenGL中,Tessellation主要是把高階的patch圖形變成點(diǎn)、線、三角形) Each patch is formed from a number of control points.(每一個(gè)patch的數(shù)據(jù)是從一堆控制點(diǎn)鐘獲取的) The number of control points per patch is configurable and set by calling glPatchParameteri() with pname set to GL_PATCH_VERTICES and value set to the number of control points that will be used to construct each patch(控制點(diǎn)的數(shù)量是可以通過glPatchParameteri來設(shè)置的,pname參數(shù)傳GL_PATCH_VERTICES,value參數(shù)設(shè)置每個(gè)patch的控制點(diǎn)個(gè)數(shù)). The prototype of glPatchParameteri() is(這個(gè)API的定義如下)

void glPatchParameteri(GLenum pname,GLint value);

By default, the number of control points per patch is three(缺省情況下,每個(gè)patch的控制點(diǎn)數(shù)量是3). Thus, if this is what you want(as in our example application), you don’t need to call it at all(如果你的 patch就是由三個(gè)點(diǎn)組成的話,你就不用調(diào)用這個(gè)API). The maximum number of control points that can be used to form a single patch is implementation defined(每個(gè)patch的控制點(diǎn)的上線個(gè)數(shù)會因?yàn)橛布灰粯佣灰粯?, but is guaranteed to be at least 32(但至少這個(gè)數(shù)目會有32個(gè))

When tessellation is active, the vertex shader runs once per control point(當(dāng)激活tessellation的時(shí)候,vertex shader是每個(gè)點(diǎn)會執(zhí)行一次), while the tessellation control shader runs in batches on groups of control points where the size of each batch is the same as the number of vertices per patch(而tessellation control shader是按照patch執(zhí)行的,每個(gè)patch中點(diǎn)數(shù)數(shù)目是用API去設(shè)置好的). That is, vertices are used as control points (也就是說,點(diǎn)是被當(dāng)做控制點(diǎn)來使用的)and the result of the vertex shader is passed in batches to the tessellation control shader as its input(并且vertex shader的執(zhí)行結(jié)果就是tessellation control shader的輸入). The number of control points per patch can be changed such that the number of control points that is output by the tessellation control shader can differ from the number of control points that it consumes(控制點(diǎn)的個(gè)數(shù)是可以被修改的,意味著輸入tessellation control shader的點(diǎn)的個(gè)數(shù)不一定和該shader的輸出點(diǎn)的個(gè)數(shù)相等). The number of control points produced by the control shader is set using an output layout qualifier in the control shader’s source code(tessellation control shader產(chǎn)生的點(diǎn)的個(gè)數(shù)是在tessellation control shader里使用output layout修飾符修飾的). Such a layout qualifier looks like this(舉個(gè)例子):

layout (vertices = N) out;

Here, N is the number of control points per patch(這里的N就是每個(gè)patch輸出的點(diǎn)的個(gè)數(shù)). The control shader is responsible for calculating the values of the output control points(control shader需要計(jì)算輸出的控制點(diǎn)的值) and for setting the tessellation factors for the resulting patch that will be sent to the fixed-function tessellation engine(這些值將會被tessellation引擎使用,并成為最終進(jìn)行曲面細(xì)分時(shí)的決定因素). The output tessellation factors are written to the gl_TessLevelInner and gl_TessLevelOuter built-in output variables(曲面細(xì)分的影響因素要寫在兩個(gè)內(nèi)置輸出變量上,一個(gè)是gl_TessLevelInner一個(gè)是gl_TessLevelOuter), whereas any other data that is passed down the pipeline is written to user-defined output variables(這倆變量就跟你自己寫的輸出變量一樣) (those declared using the out keyword, or the special built-in gl_out array) as normal

Listing 3.7 shows a simple tessellation control shader(Listing3.7顯示了一個(gè)簡單的tessellation control shader). It sets the number of output control points to three (它使用layout (vertices = 3) out設(shè)置了輸出的數(shù)據(jù)個(gè)數(shù)是3)(the same as the default number of input control points(就跟缺省的control shader的輸入數(shù)據(jù)個(gè)數(shù)一樣)) using the layout (vertices = 3) out; layout qualifier, copies its input to its output (using the built-in variables gl_in and gl_out) (layout修飾符會使用內(nèi)置的gl_in和gl_out,拷貝它的輸入到它的輸出里去), and sets the inner and outer tessellation level to 5(并且設(shè)置inner和outer的tessellation級別為5). Higher numbers would produce a more densely tessellated output(細(xì)分級別越高,產(chǎn)生的曲面的小面片就越多), and lower numbers would yield a more coarsely tessellated output(細(xì)分級別越小,產(chǎn)生的結(jié)果的面片數(shù)就越少). Setting the tessellation factor to 0 will cause the whole patch to be thrown away(設(shè)置tessellation因子為0將會使得整個(gè)patch被丟棄)

The built-in input variable gl_InvocationID is used as an index into the gl_in and gl_out arrays. This variable contains the zero-based index of the control point within the patch being processed by the current invocation of the tessellation control shader

#version 450 core
layout (vertices = 3) out;
void main(void)
{
// Only if I am invocation 0 ...
if (gl_InvocationID == 0)
{
gl_TessLevelInner[0] = 5.0;
gl_TessLevelOuter[0] = 5.0;
gl_TessLevelOuter[1] = 5.0;
gl_TessLevelOuter[2] = 5.0;
}/
/ Everybody copies their input to their output
gl_out[gl_InvocationID].gl_Position =
gl_in[gl_InvocationID].gl_Position;
}
Listing 3.7: Our first tessellation control shader

By using the shader of Listing 2.8, we can assign a different position to each of the vertices based on its value of gl_VertexID(我們可以根據(jù)gl_VertexID給每個(gè)頂點(diǎn)賦值一個(gè)位置). The points in the array vertices form a triangle(那些點(diǎn)是以三角形的方式進(jìn)行組織的), and if we modify our rendering function to pass GL_TRIANGLES to glDrawArrays() instead of GL_POINTS(并且我們修改glDrawArrays的參數(shù),從GL_POINTS變成GL_TRIANGLES,如Listing2.9所示), as shown in Listing 2.9, then we obtain the image shown in Figure 2.4(這樣一來,我們應(yīng)該會得到如圖2.4的運(yùn)行結(jié)果).

// Our rendering function
void render(double currentTime)
{
const GLfloat color[] = { 0.0f, 0.2f, 0.0f, 1.0f };glClearBufferfv(GL_COLOR, 0, color);
// Use the program object we created earlier for rendering
glUseProgram(rendering_program);
// Draw one triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
}
Listing 2.9: Rendering a single triangle

The Tessellation Engine

The tessellation engine is a fixed-function part of the OpenGL pipeline that takes highorder surfaces represented as patches and breaks them down into simpler primitives such as points, lines, or triangles(Tessellation引擎是OpenGL固定功能的一部分,它會把高階的patch打碎成點(diǎn)、線、三角形). Before the tessellation engine receives a patch, the tessellation control shader processes the incoming control points and sets tessellation factors that are used to break down the patch(在tessellation引擎收到patch之前,tessellation control shader會處理輸入的控制點(diǎn),并且設(shè)置一些用于打碎patch的一些參數(shù)). After the tessellation engine produces the output primitives, the vertices representing them are picked up by the tessellation evaluation shader(當(dāng)tessellation引擎輸出了圖元之后,這些點(diǎn)會被tessellation evaluation shader處理). The tessellation engine is responsible for producing the parameters that are fed to the invocations of the tessellation evaluation shader (tessellation引擎負(fù)責(zé)設(shè)置在調(diào)用tessellation evaluation shader時(shí)需要的參數(shù)), which it then uses to transform the resulting primitives and get them ready for rasterization(evaluation shader處理完畢之后,得到的結(jié)果就可以被用于進(jìn)行光柵化處理了)

Tessellation Evaluation Shaders

Once the fixed-function tessellation engine has run(當(dāng)tessellation引擎運(yùn)行之后,它會產(chǎn)生很多輸出的點(diǎn)), it produces a number of output vertices representing the primitives it has generated. These are passed to the tessellation evaluation shader(這些點(diǎn)會被傳遞給tessellation evaluation shader). The tessellation evaluation shader (TES; also called simply the evaluation shader) runs an invocation for each vertex produced by the tessellator (tessellation evaluation shader會每個(gè)點(diǎn)運(yùn)行一次). When the tessellation levels are high, the tessellation evaluation shader could run an extremely large number of times(當(dāng)細(xì)分的數(shù)目很多時(shí),TES會運(yùn)行很多次). For this reason, you should be careful with complex evaluation shaders and high tessellation levels(因此,你需要小心的處理那些細(xì)分很多,而TES很復(fù)雜的情況)

Listing 3.8 shows a tessellation evaluation shader that accepts input vertices produced by the tessellator as a result of running the control shader shown in Listing 3.7. (Listing3.8顯示了接收來自Listing3.7的TCS所產(chǎn)生的點(diǎn)的TES代碼) At the beginning of the shader is a layout qualifier that sets the tessellation mode(在一開始的時(shí)候設(shè)置tessellation的模式). In this case,we selected the mode to be triangles(這里我們設(shè)置成了三角形). Other qualifiers, equal_spacing and cw,(其他的一些設(shè)置,比如equal_spacing,cw) indicate that new vertices should be generated equally spaced along the tessellated polygon edges and that a clockwise vertex winding order should be used for the generated triangles(這些參數(shù)的意思是,在細(xì)分曲面的時(shí)候,在邊線上的分界點(diǎn)之間的間隔要相等,然后再產(chǎn)生圖元的時(shí)候,需要用順時(shí)針方向去組織三角形). We will cover the other possible choices in the “Tessellation” section in Chapter 8(我們將在第8章的時(shí)候,來講解其他的關(guān)于Tessellation的一些內(nèi)容).

The remainder of the shader assigns a value to gl_Position just like a vertex shader does(剩余的代碼也就是給gl_Position賦值,就如同vertex shader). It calculates this using the contents of two more built-in variables(同時(shí)它使用到了另外的兩個(gè)內(nèi)置變量). The first is gl_TessCoord, which is the barycentric coordinate of the vertex generated by the tessellator(其中一個(gè)是gl_TessCoord,它是由tessellator產(chǎn)生的重心坐標(biāo)). The second is the gl_Position member of the gl_in[] array of structures(第二個(gè)是gl_in數(shù)組,里面放著的是一堆gl_Position). This matches the gl_out structure written to in the tessellation control shader given in Listing 3.7(對應(yīng)的gl_out的結(jié)構(gòu)體和Listing3.7中的對應(yīng)). This shader essentially implements pass-through tessellation(這個(gè)shader就是一個(gè)基本的簡單的傳輸數(shù)據(jù)的tessellation). That is, the tessellated output patch is exactly the same shape as the original, incoming triangular patch(也就是最終輸出的圖形跟原來的patch代表的圖元一模一樣,沒什么改變)

#version 450 core
layout (triangles, equal_spacing, cw) in;
void main(void)
{
gl_Position = (gl_TessCoord.x gl_in[0].gl_Position +
gl_TessCoord.y
gl_in[1].gl_Position +
gl_TessCoord.z * gl_in[2].gl_Position);
}
Listing 3.8: Our first tessellation evaluation shader

To see the results of the tessellator, we need to tell OpenGL to draw only the outlines of the resulting triangles(為了顯示tessellation的結(jié)果,我們需要告訴OpenGL采用線框模式去繪制). To do this, we call glPolygonMode(), whose prototype is(這時(shí)候,我們需要使用glPolygonMode函數(shù),它的定義如下:)

void glPolygonMode(GLenum face, GLenum mode);

The face parameter specifies which type of polygons we want to affect(face參數(shù)需要設(shè)置我們希望哪個(gè)面被影響). Because we want to affect everything, we set it to GL_FRONT_AND_BACK(因?yàn)槲覀兿M绊懙剿袞|西,所以我們設(shè)置成GL_FRONT_AND_BACK). The other modes will be explained shortly(其他的模式稍后再解釋). mode says how we want our polygons to be rendered(模式設(shè)置的是你希望你的多邊形如何被渲染). As we want to render in wireframe mode (i.e., lines)(由于我們希望它被渲染成線框模式,我們設(shè)置這個(gè)參數(shù)為GL_LINE), we set this to GL_LINE. The result of rendering our one triangle example with tessellation enabled and the two shaders of Listing 3.7 and Listing 3.8 is shown in Figure 3.1(完事之后,剛才的Listing3.7和Listing3.8的代碼所渲染出來的結(jié)果就如同圖3.1所示)

Tessellation(細(xì)分曲面)

本日的翻譯就到這里,明天見,拜拜~~

第一時(shí)間獲取最新橋段,請關(guān)注東漢書院以及圖形之心公眾號

東漢書院,等你來玩哦

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI