中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

Feeding Vertex Shaders from Buffers從緩沖區給shader輸入數據

發布時間:2020-08-10 13:27:31 來源:網絡 閱讀:403 作者:萌谷王 欄目:游戲開發

周一到周五,每天一篇,北京時間早上7點準時更新~

In Chapter 2, “Our First OpenGL Program,” you were briefly introduced to the vertex array object (VAO). During that discussion, we explained how the VAO represented the inputs to the vertex shader—though at the time, we didn’t use any real inputs to our vertex shaders and opted instead for hard-coded arrays of data. Then, in Chapter 3 we introduced the concept of vertex attributes, but we discussed only how to change their static values. Although the vertex array object stores these static attribute values for you, it can do a lot more. Before we can proceed, we need to create a vertex array object to store our vertex array state and bind it to our context so that we can use it:

在第二章中,我們已經接觸過VAO了,在那里,我們已經解釋過VAO如何給shader輸入數據了-雖然那時候我們沒有真的使用VAO而是使用了硬編碼的數據。 在第三章,我們介紹了頂點屬性的概念,但我們僅僅是討論了如何改變他們靜態的值。VAO不僅可以為你存儲那些靜態屬性,它還可以做更多事情。在我們開始之前,我們需要創建一個VAO的對象 去存儲我們頂點數組的狀態,并且把它綁定到我們的上下文中,這樣我們才能使用它

GLuint vao;
glCreateVertexArrays(1, &vao);
glBindVertexArray(vao);
Now that we have our VAO created and bound, we can start filling in its state. Rather than using hard-coded data in the vertex shader, we can instead rely entirely on the value of a vertex attribute and ask OpenGL to fill it automatically using the data stored in a buffer object that we supply. Each vertex attribute gets to fetch data from a buffer bound to one of several vertex buffer bindings. To set the binding that a vertex attribute uses to reference a buffer, call the glVertexArrayAttribBinding() function:

現在我們創建了VAO了,我們可以干大事了。這次我們使用緩沖區對象提供數據而不是使用硬編碼。每個頂點屬性都需要從緩沖區對象綁定到的節點上去獲取數據。 為了讓頂點屬性知道自己去哪里緩沖區的那個節點上拿數據,我們調用glVertexArrayAttribBinding去設置

void glVertexArrayAttribBinding(GLuint vaobj,GLuint attribindex,GLuint bindingindex);
The glVertexArrayAttribBinding() function tells OpenGL that when the vertex array object named vaobj is bound, the vertex attribute at the index specified in attribindex should source its data from the buffer bound at bindingindex. To tell OpenGL which buffer object our data is in and where in that buffer object the data resides, we use the glVertexArrayVertexBuffer() function to bind a buffer to one of the vertex buffer bindings. We use the glVertexArrayAttribFormat() function to describe the layout and format of the data, and finally we enable automatic filling of the attribute by calling glEnableVertexAttribArray(). The prototype of glVertexArrayVertexBuffer() is

這個函數就告訴OpenGL,當vaobj這個VAO被綁定到上下文的時候,在attribindex上的頂點屬性去緩沖區的那個bindingindex上拿數據。 為了告知OpenGL數據在哪個緩沖區里以及數據在那個緩沖區里的內存格局,我們使用glVertexArrayVertexBuffer去設置這些。我們使用glVertexArrayAttribFormat去描述數據的格式,也就是內存分布啦。 不清楚內存分布的同學可以看看我們的C++ Tricks課程,不講C++基礎語法,只通過一些小的例子來加深對C++的理解。并且最終,我們調用glEnableVertexAttribArray函數去啟動讓OpenGL 自動的去把緩沖區里的數據按照設置的模式發送給shader處理。glVertexArrayVertexBuffer的函數如下:

void glVertexArrayVertexBuffer(GLuint vaobj,
GLuint bindingindex,
GLuint buffer,
GLintptr offset,
GLsizei stride);
Here, the first parameter is the vertex array object whose state you’re modifying. The second parameter, bindingindex, is the index of the vertex buffer, which matches the parameter sent to glVertexArrayAttribBinding(). The buffer parameter specifies the name of the buffer object that we’re binding. The last two parameters, offset and stride, tell OpenGL where in the buffer object the attribute data lies. offset says where the first vertex’s data starts and stride says how far apart each vertex is. Both are measured in bytes. Next, we have glVertexArrayAttribFormat(), whose prototype is

這里,第一個參數是VAO,第二個參數是緩沖區對象的索引,這個索引與glVertexArrayAttribBinding里面設置的那個一一對應。第三個參數是緩沖區對象。 最后倆參數offset和stride告訴OpenGL這些數據的內存格局,offset告訴OpenGL數據的起始位置,stride告訴OpenGL同一個屬性之間的數據間隔,大小都是字節。

void glVertexArrayAttribFormat(GLuint vaobj,
GLuint attribindex,
GLint size,
GLenum type,
GLboolean normalized,
GLuint relativeoffset);
For glVertexArrayAttribFormat(), the first parameter is again the vertex array whose state we’re modifying. attribindex is the index of the vertex attribute. You can define a large number of attributes as input to a vertex shader and then refer to them by their index, as explained in the “Vertex Attributes” section in Chapter 3. size is the number of components that are stored in the buffer for each vertex and type is the type of the data, which would normally be one of the types in Table 5.3.

glVertexArrayAttribFormat的第一個參數是VAO,attribindex是頂點屬性的索引。你可以定義很多屬性,然后試用索引來引用他們。 size參數是是指每一個頂點有多少個組成部分,類型指的是數據的類型,一般來說就是指表5.3里的那些。

The normalized parameter tells OpenGL whether the data in the buffer should be normalized (scaled between 0.0 and 1.0) before being passed to the vertex shader or if it should be left alone and passed as is. This parameter is ignored for floating-point data, but for integer data types, such as GL_UNSIGNED_BYTE or GL_INT, it is important. For example, if GL_UNSIGNED_BYTE data is normalized, it is divided by 255 (the maximum value representable by an unsigned byte) before being passed to a floating-point input to the vertex shader. The shader will therefore see values of the input attribute between 0.0 and 1.0. However, if the data is not normalized, it is simply cast to floating-point values and the shader will receive numbers between 0.0 and 255.0, even though the input to the vertex shader consists of floating-point data. The stride parameter tells OpenGL how many bytes are between the start of one vertex’s data and the start of the next, but you can set this parameter to 0 to let OpenGL calculate it for you based on the values of size and type. Finally, relative offset is the offset from the vertex’s data where the specific attribute’s data starts. This all seems pretty complex, but the pseudocode to compute the location in a buffer object is fairly simple:

normalized參數告訴OpenGL,數據是否需要在傳給shader前被縮放到0~1之間去。對于GL_FLOAT類型來說,這個參數會被OpenGL忽略,但是對于GL_UNSIGNED_BYTE或者GL_INT類型的數據來說,這個參數 很重要。對于GL_UNSIGNED_BYTE來說,如果你傳入的數據是255,如果這里告訴OpenGL需要縮放,那么shader里收到的數據是1.0,如果你告訴OpenGL不需要縮放,那么shader里收到的數據是255.0這樣一個浮點數。 stride參數告訴OpenGL數據間隔。最后相對偏移指示了某一個屬性數據的數據在頂點所有數據中的偏移位置。雖然這些概念看起來很復雜,但是計算偏移的偽代碼很簡單:

location = binding[attrib.binding].memory + // Start of data store in memory
binding[attrib.binding].offset + // Offset of vertex attribute in buffer
binding[attrib.binding].stride vertex.index + // Start of this* vertex
vertex.relative_offset; // Start of attribute relative to vertex
Finally, glEnableVertexAttribArray() and the converse glDisableVertexAttribArray() have the prototypes:

最后,使用glEnableVertexAttribArray和相反的操作glDisableVertexAttribArray有如下的函數申明:

void glEnableVertexAttribArray(GLuint index);
When a vertex attribute is enabled, OpenGL will feed data to the vertex shader based on the format and location information you’ve provided with glVertexArrayVertexBuffer() and glVertexArrayAttribFormat(). When the attribute is disabled, the vertex shader will be provided with the static information you provide with a call to glVertexAttrib(). Listing 5.4 shows how to use glVertexArrayVertexBuffer() and glVertexArrayAttribFormat() to configure a vertex attribute. Notice that we also call glEnableVertexArrayAttrib() after setting up the offset, stride, and format information. This tells OpenGL to use the data in the buffer to fill the vertex attribute rather than using data we provide through one of the glVertexAttrib() functions.

當一個頂點屬性啟用之后,OpenGL將會根據我們前面設置的那些來給shader發送參數.如果頂點屬性被禁用了,那么OpenGL則會給shader發送你使用glVertexAttrib那些函數設置的一些固定的數據。 清單5.4展示了如何使用glVertexArrayVertexBuffer和glVertexArrayAttribFormat去配置頂點屬性。注意到,我們同樣在設置offset、stride以及format的信息后調用了glEnableVertexArrayAttrib。 這是在告訴OpenGL,我們使用緩沖區里的數據作為shader輸入參數俄入世glVertexAttrib那些函數設置的東西。

// First, bind a vertex buffer to the VAO
glVertexArrayVertexBuffer(vao, // Vertex array object
0, // First vertex buffer
binding
buffer, // Buffer object
0, // Start from the beginning
sizeof(vmath::vec4)); // Each vertex is one vec4
// Now, describe the data to OpenGL, tell it where it is, and turn on automatic
// vertex fetching for the specified attribute
glVertexArrayAttribFormat(vao, // Vertex array object
0, // First attribute
4, // Four components
GL_FLOAT, // Floating-point data
GL_FALSE, // Normalized - ignored for floats
0); // First element of the vertex
glEnableVertexArrayAttrib(vao, 0);
Listing 5.4: Setting up a vertex attribute

After Listing 5.4 has been executed, OpenGL will automatically fill the first attribute in the vertex shader with data it has read from the buffer that was bound to the VAO by glVertexArrayVertexBuffer(). We can modify our vertex shader to use only its input vertex attribute rather than a hardcoded array. This updated shader is shown in Listing 5.5.

當清單5.4倍執行了之后,OpenGL將會自動使用glVertexArrayVertexBuffer綁定在VAO上的緩沖區的數據去填充shader里的第一個屬性。我們現在來修改shader,讓shader去使用這樣的輸入數據,而不是硬編碼數據。 清單5.5展示了我們最新版本的shader代碼該如何寫

#version 450 core
layout (location = 0) in vec4 position;
void main(void)
{
gl_Position = position;
}
Listing 5.5: Using an attribute in a vertex shader

As you can see, the shader of Listing 5.5 is greatly simplified over the original shader shown in Chapter 2. Gone is the hard-coded array of data. As an added bonus, this shader can be used with an arbitrary number of vertices. You can literally put millions of vertices’ worth of data into your buffer object and draw them all with a single command such as a call to glDrawArrays(). If you are done using data from a buffer object to fill a vertex attribute, you can disable that attribute again with a call to glDisableVertexAttribArray(), whose prototype is

如你所見,清單5.5比起以前那個shader簡單多了。刪除了硬編碼的數據。這個shader可以使用任意數量的頂點。可以說,你可以在緩沖區里放上百萬的數據,然后使用一個繪制指令就將他們畫出來。 如果你使用完畢了緩沖區里的頂點屬性,你可以使用glDisableVertexAttribArray禁用這個屬性。

void glDisableAttribArray(GLuint index);
Once you have disabled the vertex attribute, it goes back to being static and passing the value you specify with glVertexAttrib*() to the shader.

當你禁用了這個屬性后,未來調用shader的時候,傳給shader的數據又是那些使用glVertexAttrib*函數設置的數據了。

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

第一時間獲取最新橋段,請關注東漢書院以及圖形之心公眾號

東漢書院,等你來玩哦

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

章丘市| 金川县| 宜丰县| 龙南县| 大同县| 扎鲁特旗| 石柱| 内江市| 揭阳市| 特克斯县| 隆子县| 崇左市| 莲花县| 怀安县| 商洛市| 延寿县| 钦州市| 新乐市| 普陀区| 东安县| 陆川县| 汽车| 澳门| 泗水县| 凭祥市| 周口市| 德阳市| 丘北县| 信宜市| 禹城市| 双鸭山市| 河曲县| 固安县| 武威市| 泸定县| 保康县| 牡丹江市| 革吉县| 邹平县| 九台市| 泰顺县|