溫馨提示×

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

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

Passing Data from Stage to Stage(在渲染管線各個(gè)階段之間傳遞數(shù)據(jù))

發(fā)布時(shí)間:2020-05-21 21:25:34 來源:網(wǎng)絡(luò) 閱讀:428 作者:萌谷王 欄目:游戲開發(fā)

So far, you have seen how to pass data into a vertex shader by creating a vertex attribute using the in keyword(到現(xiàn)在為止,你已經(jīng)看到了如何通過vertex attribute給vertex shader傳遞數(shù)據(jù)了), how to communicate with fixed-function blocks by reading and writing built-in variables such as gl_VertexID and gl_Position,(如何利用固定功能通過讀寫內(nèi)置的諸如gl_VertexID和gl_Position進(jìn)行通信呢?) and how to output data from the fragment shader using the out keyword(如何通過fragment shader使用out修飾符輸出數(shù)據(jù)呢). However, it’s also possible to send your own data from shader stage to shader stage using the same in and out keywords(當(dāng)然,你也可以使用in和out在渲染管線的各個(gè)階段之間傳遞自己的數(shù)據(jù)). Just as you used the out keyword in the fragment shader to create the output variable to which it writes its color values(就如同你之前使用過的,使用out關(guān)鍵字就能讓fragment shader輸出顏色), so you can also create an output variable in the vertex shader by using the out keyword(你也可以在vertex shader中使用out關(guān)鍵字讓vertex shader輸出數(shù)據(jù)). Anything you write to an output variable in one shader is sent to a similarly named variable declared with the in keyword in the subsequent stage(你在使用out修飾的輸出的變量中寫入的數(shù)據(jù),都會(huì)傳遞到渲染管線的下一個(gè)階段中同名的用in修飾的變量中). For example, if your vertex shader declares a variable called vs_color using the out keyword(比如,你用out修飾了一個(gè)叫vs_color的變量), it would match up with a variable named vs_color declared with the in keyword in the fragment shader stage(這將會(huì)與在fragment shader中使用in修飾的vs_color變量配對(duì)成功) (assuming no other stages were active in between(假設(shè)vertex shader和fragment shader之間沒有其他的shader))

If we modify our simple vertex shader as shown in Listing 3.3 to include vs_color as an output variable(如果我們按照Listing3.3所示修改我們的vertex shader,將vs_color作為我們的輸出數(shù)據(jù)), and correspondingly modify our simple fragment shader to includevs_color as an input variable as shown in Listing 3.4,(并且對(duì)應(yīng)的Listing3.4所示在fragment shader中申明變量vs_color作為輸入數(shù)據(jù)) we can pass a value from the vertex shader to the fragment shader(我們可以將一個(gè)變量從vertex shader傳遞到fragment shader). Then, rather than outputting a hard-coded value(相比于硬編碼一個(gè)數(shù)據(jù)),the fragment can simply output the color passed to it from the vertex shader(現(xiàn)在的fragment shader可以輸出一個(gè)從vertex shader那邊傳過來的顏色了)

#version 450 core
// 'offset' and 'color' are input vertex attributes
layout (location = 0) in vec4 offset;
layout (location = 1) in vec4 color;
// 'vs_color' is an output that will be sent to the next shader stage
out vec4 vs_color;
void main(void)
{
const vec4 vertices[3] = vec4[3](vec4(0.25, -0.25, 0.5, 1.0),
vec4(-0.25, -0.25, 0.5, 1.0),
vec4(0.25, 0.25, 0.5, 1.0));
// Add 'offset' to our hard-coded vertex position
gl_Position = vertices[gl_VertexID] + offset;
// Output a fixed value for vs_color
vs_color = color;
}
Listing 3.3: Vertex shader with an output

As you can see in Listing 3.3, we declare a second input to our vertex shader, color (this time at location 1), and write its value to the vs_output output. This is picked up by the fragment shader of Listing 3.4 and written to the framebuffer. This allows us to pass a color all the way from a vertex attribute that we can set with glVertexAttrib* () through the vertex shader, into the fragment shader, and out to the framebuffer. As a consequence, we can draw different-colored triangles!

#version 450 core
// Input from the vertex shader
in vec4 vs_color;
// Output to the framebuffer
out vec4 color;
void main(void)
{
// Simply assign the color we were given by the vertex shader to our output
color = vs_color;
}
Listing 3.4: Fragment shader with an input

Interface Blocks

Declaring interface variables one at a time is possibly the simplest way to communicate data between shader stages(一次定義一個(gè)變量或許是最簡(jiǎn)單的渲染管線各階段通信的方式). However, in most nontrivial applications(然而在很多程序中), you will likely want to communicate a number of different pieces of data between stages(你會(huì)傳遞更多的數(shù)據(jù)); these may include arrays, structures, and other complex arrangements of variables(這些數(shù)據(jù)可能就包括數(shù)組、結(jié)構(gòu)體以及一些其他的復(fù)雜的數(shù)據(jù)). To achieve this, we can group together a number of variables into an interface block(為了實(shí)現(xiàn)這一目標(biāo),我們可以把很多個(gè)變量組織到一個(gè)數(shù)據(jù)塊中去). The declaration of an interface block looks a lot like a structure declaration(數(shù)據(jù)塊的申明跟結(jié)構(gòu)體的申明類似), except that it is declared using the in or out keyword depending on whether it is an input to or output from the shader(除了數(shù)據(jù)塊使用in和out關(guān)鍵字來區(qū)分?jǐn)?shù)據(jù)塊是輸入數(shù)據(jù)還是輸出數(shù)據(jù)這一點(diǎn)). An example interface block definition is shown in Listing 3.5(一個(gè)數(shù)據(jù)塊的例子就如同Listing3.5的代碼所示)

#version 450 core
// 'offset' is an input vertex attribute
layout (location = 0) in vec4 offset;
layout (location = 1) in vec4 color;
// Declare VS_OUT as an output interface block
out VS_OUT
{
vec4 color; // Send color to the next stage
} vs_out;
void main(void)
{
const vec4 vertices[3] = vec4[3](vec4(0.25, -0.25, 0.5, 1.0),
vec4(-0.25, -0.25, 0.5, 1.0),
vec4(0.25, 0.25, 0.5, 1.0));
// Add 'offset' to our hard-coded vertex position
gl_Position = vertices[gl_VertexID] + offset;
// Output a fixed value for vs_color
vs_out.color = color;
}
Listing 3.5: Vertex shader with an output interface block

Note that the interface block in Listing 3.5 has both a block name (VS_OUT, uppercase) and an instance name (vs_out, lowercase)(注意到Listing3.5的代碼中同時(shí)出現(xiàn)了數(shù)據(jù)塊的名字和它實(shí)例對(duì)象的名字). Interface blocks are matched between stages using the block name (VS_OUT in this case)(數(shù)據(jù)塊在渲染管線中傳遞的時(shí)候是用名字一一對(duì)應(yīng)的), but are referenced in shaders using the instance name(在使用的時(shí)候,卻引用的是數(shù)據(jù)塊實(shí)例的名字). Thus, modifying our fragment shader to use an interface block gives the code shown in Listing 3.6(所以,我們還要按照Listing3.6的那樣修改咱們的fragment shader的代碼).

#version 450 core // Declare VS_OUT as an input interface block in VS_OUT { vec4 color; // Send color to the next stage } fs_in; // Output to the framebuffer out vec4 color; void main(void) { // Simply assign the color we were given by the vertex shader to our output color = fs_in.color; }

Listing 3.6: Fragment shader with an input interface block

Matching interface blocks by block name but allowing block instances to have different names in each shader stage serves two important purposes(使用數(shù)據(jù)塊的名字做一一對(duì)應(yīng),但允許數(shù)據(jù)塊實(shí)例有不同的名字有倆目的). First, it allows the name by which you refer to the block to be different in each stage(第一個(gè)目的,它允許你在渲染管線引用的名字可以不一樣), thereby avoiding confusing things such as having to use vs_out in a fragment shader(這樣可以避免一些奇怪的東西,比如在fragment shader中使用vs_out這樣的名字). Second, it allows interfaces to go from being single items to arrays when crossing between certain shader stages(第二,它允許傳遞數(shù)據(jù)的時(shí)候從一個(gè)數(shù)據(jù)變成一組數(shù)據(jù)), such as the vertex and tessellation or geometry shader stages(比如vertex shader的數(shù)據(jù)傳遞給tessellation或者geometry shader的時(shí)候,我們很快就會(huì)見識(shí)到了), as we will see in a short while. Note that interface blocks are only for moving data from shader stage to shader stage(注意,數(shù)據(jù)塊只適用于shader各個(gè)階段間傳遞數(shù)據(jù))—you can’t use them to group together inputs to the vertex shader or outputs from the fragment shader(你不能使用數(shù)據(jù)塊對(duì)vertex shader傳入數(shù)據(jù)或者從fragment shader輸出數(shù)據(jù)).

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

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

東漢書院,等你來玩哦

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

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

AI