您好,登錄后才能下訂單哦!
周一到周五,每天一篇,北京時(shí)間早上7點(diǎn)準(zhǔn)時(shí)更新~
What You’ll Learn in This Chapter(你將會(huì)在本章學(xué)到啥)
How to create buffers and textures that you can use to store data that your program can access
How to get OpenGL to supply the values of your vertex attributes automatically
How to access textures and buffers from your shaders
如何創(chuàng)建緩沖區(qū)和紋理貼圖
如何讓OpenGL自動(dòng)設(shè)置你的頂點(diǎn)的數(shù)據(jù)
如何從shader中訪問(wèn)緩沖區(qū)和紋理
In the examples you’ve seen so far, either we have used hard-coded data directly in our shaders, or we have passed values to shaders one at a time. While sufficient to demonstrate the configuration of the OpenGL pipeline, this is hardly representative of modern graphics programming. Recent graphics processors are designed as streaming processors that consume and produce huge amounts of data. Passing a few values to OpenGL at a time is extremely inefficient. To allow data to be stored and accessed by OpenGL, we include two main forms of data storage—buffers and textures. In this chapter, we first introduce buffers, which are linear blocks of untyped data and can be seen as generic memory allocations. Next, we introduce textures, which are normally used to store multidimensional data, such as images or other data types
到現(xiàn)在為止,我們展示的那些硬編碼的數(shù)據(jù)也好,從C語(yǔ)言里向shader中傳數(shù)據(jù)也好,盡管說(shuō)明了OpenGL的玩法,但是它實(shí)際上僅僅是教學(xué)需要。 我們接下來(lái)要學(xué)習(xí)的才是高效的使用OpenGL的方式。在OpenGL中主要有兩種形式的數(shù)據(jù):存儲(chǔ)一般數(shù)據(jù)用的緩沖區(qū)和紋理緩沖區(qū)。在本章節(jié)中,我們 首先來(lái)看看存儲(chǔ)一般數(shù)據(jù)的緩沖區(qū),它是線性的無(wú)類型的數(shù)據(jù)塊。緊接著我們來(lái)介紹紋理,你可以在里面存儲(chǔ)多維的數(shù)據(jù)比如圖片或者什么的。
Buffers(緩沖區(qū))
In OpenGL, buffers are linear allocations of memory that can be used for a number of purposes. They are represented by names, which are essentially opaque handles that OpenGL uses to identify them. Before you can start using buffers, you have to ask OpenGL to reserve some names for you and then use them to allocate memory and put data into that memory. The memory allocated for a buffer object is called its data store. The data store of the buffer is where OpenGL stores its data. You can put data into the buffer using OpenGL commands, or you can map the buffer object, which means that you can get a pointer that your application can use to write directly into (or read directly out of) the buffer
在OpenGL中,緩沖區(qū)是線性存儲(chǔ)的內(nèi)存塊,它們有各自的名字,這個(gè)名字基本上就是一個(gè)OpenGL用于區(qū)分它們的標(biāo)記。在你開(kāi)始使用緩沖區(qū)之前, 你需要讓OpenGL給你分配一些名字,這樣一來(lái)你就可以為這些名字對(duì)應(yīng)的緩沖區(qū)分配內(nèi)存并操作它們。你可以通過(guò)OpenGL的API給這些緩沖區(qū)里塞數(shù)據(jù), 你也可以直接獲取到這些緩沖區(qū)的地址,然后往里面寫(xiě)數(shù)據(jù)或者從里面讀數(shù)據(jù)。
Once you have the name of a buffer, you can attach it to the OpenGL context by binding it to a buffer binding point. Binding points are sometimes referred to as targets; these terms may be used interchangeably. There are a large number of buffer binding points in OpenGL and each has a different use, although the buffers you bind to them are the same. For example, you can use the contents of a buffer to automatically supply the inputs of a vertex shader, to store the values of variables that will be used by your shaders, or as a place for shaders to store the data they produce. You can even use the same buffer for multiple purposes at the same time
當(dāng)你有了緩沖區(qū)對(duì)象了之后,你就可以將它綁定到當(dāng)前的OpenGL上下文。這些綁定節(jié)點(diǎn)有時(shí)候我們也叫它目標(biāo)。OpenGL里面有很多綁定節(jié)點(diǎn),盡管你綁定上去的緩沖區(qū)都一樣,但每種節(jié)點(diǎn)有不同的用處。 比如說(shuō),你可以用緩沖區(qū)去提供shader的頂點(diǎn)數(shù)據(jù),或者是用緩沖區(qū)去存儲(chǔ)shader產(chǎn)生的輸出數(shù)據(jù)。你甚至可以在同一時(shí)間將同一個(gè)緩沖區(qū)用于多個(gè)目的。
Creating Buffers and Allocating Memory(創(chuàng)建緩沖區(qū)并分配內(nèi)存)
Before you can ask OpenGL to allocate memory, you need to create a buffer object to represent that allocation. Like most objects in OpenGL, buffer objects are represented by a GLuint variable, which is generally called its name. One or more buffer objects can be created using the glCreateBuffers() function, whose prototype is
在你為緩沖區(qū)對(duì)象分配內(nèi)存前,你需要先創(chuàng)建這樣一個(gè)緩沖區(qū)。跟大部分的OpenGL里的對(duì)象一樣,緩沖區(qū)物體的標(biāo)記是一個(gè)GLuint類型的,這就是它的名字。 你可以使用glCreateBuffers一次性去創(chuàng)建1個(gè)或者多個(gè)緩沖區(qū)對(duì)象
void glCreateBuffers(GLsizei n, GLuint* buffers);
The first parameter to glCreateBuffers(), n, is the number of buffer objects to create. The second parameter, buffers, is the address of the variable or variables that will be used to store the names of the buffer objects. If you need to create only one buffer object, set n to 1 and set buffers to the address of a single GLuint variable. If you need to create more than one buffer at a time, simply set n to that number and point buffers to the beginning of an array of at least n GLuint variables. OpenGL will just trust that the array is big enough and will write that many buffer names to the pointer that you specify
第一個(gè)參數(shù)是你需要?jiǎng)?chuàng)建多少個(gè)緩沖區(qū)對(duì)象,第二個(gè)參數(shù)是用于存儲(chǔ)緩沖區(qū)對(duì)象的地址。需要注意的是,第二個(gè)參數(shù)需要有足夠多的空間去存儲(chǔ)對(duì)象的名字,比如你如果要10個(gè)緩沖區(qū)對(duì)象, 那么第二個(gè)參數(shù)指向的地址必須要至少可以放10個(gè)GLuint。
Each of the names you get back from glCreateBuffers() represents a single buffer object. You can bind the buffer objects to the current OpenGL context by calling glBindBuffer(), the prototype of which is
創(chuàng)建好了緩沖區(qū)對(duì)象之后,你就可以使用glBindBuffer去將某個(gè)緩沖區(qū)對(duì)象綁定到當(dāng)前的OpenGL的上下文了
void glBindBuffer(GLenum target, GLuint buffer);
Before you can actually use the buffer objects, you need to allocate their data stores, which is another term for the memory represented by the buffer object. The functions that are used to allocate memory using a buffer object are glBufferStorage() and glNamedBufferStorage(). Their prototypes are
完成了上面的操作后,你就可以為你的緩沖區(qū)對(duì)象分配內(nèi)存了,使用glBufferStoerage和glNamedBufferStorage來(lái)分配
void glBufferStorage(GLenum target,
GLsizeiptr size,
const void data,
GLbitfield flags);
void glNamedBufferStorage(GLuint buffer,
GLsizeiptr size,
const void data,
GLbtifield flags);
The first function affects the buffer object bound to the binding point specified by target; the second function directly affects the buffer specified by buffer. The remainder of the parameters serve the same purpose in both functions. The size parameter specifies how big the storage region is to be, in bytes. The data parameteris used to pass a pointer to any data that you want to initialize the buffer with. If this is NULL, then the storage associated with the buffer object will at first be uninitialized. The final parameter, flags, is used to tell OpenGL how you’re planning to use the buffer object.
第一個(gè)函數(shù)會(huì)影響綁定在target節(jié)點(diǎn)上的緩沖區(qū)對(duì)象。第二個(gè)函數(shù)直接影響buffer指定的那個(gè)緩沖區(qū)對(duì)象。倆函數(shù)剩余的參數(shù)的含義是一樣的。 size表示的是緩沖區(qū)對(duì)象的內(nèi)存有多少字節(jié),data表示的數(shù)據(jù),如果data是空,則緩沖區(qū)僅分配內(nèi)存,不會(huì)寫(xiě)入數(shù)據(jù),如果data有數(shù)據(jù),則會(huì)把data上的數(shù)據(jù)拷貝到緩沖區(qū)對(duì)象里去。 最后的一個(gè)參數(shù)是一個(gè)標(biāo)志位,用來(lái)告訴OpenGL,我們的程序后面會(huì)如何去使用這個(gè)緩沖區(qū)對(duì)象。
Once storage has been allocated for a buffer object using either glBufferStorage() or glNamedBufferStorage(), it cannot be reallocated or respecified, but is considered immutable. To be clear, the contents of the buffer object’s data store can be changed, but its size or usage flags may not. If you need to resize a buffer, you need to delete it, create a new one, and set up new storage for that
當(dāng)你為緩沖區(qū)對(duì)象分配好了內(nèi)存后,你可以改變緩沖區(qū)對(duì)象里的內(nèi)容,但是你不可以改變它的大小,如果你非得這么做,你只能先刪除當(dāng)前的緩沖區(qū)對(duì)象,然后重新創(chuàng)建一個(gè)新的。
The most interesting parameter to these two functions is the flags parameter. This should give OpenGL enough information to allocate memory suitable for your intended purpose and allow it to make an informed decision about the storage requirements of the buffer. flags is a GLbitfield type, which means that it’s a combination of one or more bits. The flags that you can set are shown in Table 5.1
最搞笑的參數(shù)是最后的那個(gè)參數(shù),那個(gè)參數(shù)會(huì)告訴OpenGL你將如何使用這些緩沖區(qū)對(duì)象,這樣OpenGL才能將這些緩沖區(qū)分配到合適的內(nèi)存上,最后的參數(shù)可以是表5.1中的多個(gè)標(biāo)志位采用位運(yùn)算來(lái)進(jìn)行組合
The flags listed in Table 5.1 may seem a little terse and probably deserve more explanation. In particular, the absence of certain flags can mean something to OpenGL, some flags may be used only in combination with others, and the specification of these flags can have an effect on what you’re allowed to do with the buffer later. We’ll provide a brief explanation of each of these flags here and then dive deeper into some of their meanings as we cover further functionality
表5.1里的這些標(biāo)志位可能需要更多的說(shuō)明才行,特別是,某些標(biāo)志對(duì)OpenGL有著特殊的意義,有的標(biāo)志只能與特定的標(biāo)志進(jìn)行結(jié)合使用。我們先來(lái)進(jìn)行一些簡(jiǎn)短的說(shuō)明, 后面我們用到那些功能的時(shí)候再進(jìn)行深入講解
First, the GL_DYNAMIC_STORAGE_BIT flag is used to tell OpenGL that you mean to update the contents of the buffer directly—perhaps once for every time that you use thedata. If this flag is not set, OpenGL will assume that you’re not likely to need to change the contents of the buffer and might put the data somewhere that is less accessible. If you don’t set this bit, you won’t be able to use commands like glBufferSubData() to update the buffer content, although you will be able to write into it directly from the GPU using other OpenGL commands
首先是GL_DYNAMIC_STORAGE_BIT,這個(gè)標(biāo)記告訴OpenGL,你需要頻繁的去更新緩沖區(qū)對(duì)象,如果這個(gè)標(biāo)記沒(méi)有被設(shè)置的話,OpenGL為你的緩沖區(qū)對(duì)象分配的內(nèi)存可以在遙遠(yuǎn)的山區(qū), 你訪問(wèn)這樣的緩沖區(qū)可能會(huì)造成內(nèi)分泌失調(diào)等,甚至大小便失禁。如果你不設(shè)置這個(gè)東西,你可能無(wú)法使用glBufferSubData去更新緩沖區(qū)的數(shù)據(jù),盡管你可以通過(guò)其他的OpenGL指令直接從GPU里往里面寫(xiě)數(shù)據(jù)
The mapping flags GL_MAP_READ_BIT, GL_MAP_WRITE_BIT, GL_MAP_PERSISTENT_BIT, and GL_MAP_COHERENT_BIT tell OpenGL if and how you’re planning to map the buffer’s data store. Mapping is the process of getting a pointer that you can use from your application that represents the underlying data store of the buffer. For example, you may map the buffer for read or write access only if you specify the GL_MAP_READ_BIT or GL_MAP_WRITE_BIT flags, respectively. Of course, you can specify both if you wish to map the buffer for both reading and writing. If you specify GL_MAP_PERSISTENT_BIT, then this flag tells OpenGL that you wish to map the buffer and then leave it mapped while you call other drawing comands. If you don’t set this bit, then OpenGL requires that you don’t have the buffers mapped while you’re using it from drawing commands. Supporting peristent maps might come at the expense of some performance, so it’s best not to set this bit unless you really need to. The final bit, GL_MAP_COHERENT_BIT, goes further and tells OpenGL that you want to be able to share data quite tightly with the GPU. If you don’t set this bit, you need to tell OpenGL when you’ve written data into the buffer, even if you don’t unmap it.
GL_MAP_READ_BIT、GL_MAP_WRITE_BIT、GL_MAP_PERSISTENT_BIT和GL_MAP_COHERENT_BIT告訴OpenGL你將如何操作緩沖區(qū)的數(shù)據(jù)。 比如只有你設(shè)置了GL_MAP_READ_BIT或者GL_MAP_WRITE_BIT的時(shí)候,你才可以通過(guò)mapping的方式去讀或者寫(xiě)數(shù)據(jù)。你可以對(duì)緩沖區(qū)對(duì)象同時(shí)使用讀和寫(xiě)兩種標(biāo)志。 GL_MAP_PERSISTENT_BIT標(biāo)志告訴OpenGL,你在調(diào)用繪制指令的時(shí)候,不會(huì)取消mapping狀態(tài),如果你沒(méi)有使用這個(gè)標(biāo)志位,那么你在繪圖的時(shí)候,必須要取消緩沖區(qū)對(duì)象的mapping狀態(tài)。 GL_MAP_PERSISTENT_BIT這個(gè)標(biāo)志位實(shí)際上會(huì)帶來(lái)很大的系統(tǒng)負(fù)擔(dān), 所以最好還是不要用的比較好哦,除非你真的需要。GL_MAP_COHERENT_BIT這個(gè)標(biāo)志告訴OpenGL你希望能夠 與GPU共享緊湊的數(shù)據(jù),如果你不去設(shè)置這個(gè)標(biāo)志位,即使你不去unmap,你也需要告訴OpenGL,你啥時(shí)候把數(shù)據(jù)寫(xiě)入緩沖區(qū)了。
// The type used for names in OpenGL is GLuint
GLuint buffer;
// Create a buffer
glCreateBuffers(1, &buffer);
// Specify the data store parameters for the buffer
glNamedBufferStorage(
buffer, // Name of the buffer
1024 * 1024, // 1 MiB of space
NULL, // No initial data
GL_MAP_WRITE_BIT); // Allow map for writing
// Now bind it to the context using the GL_ARRAY_BUFFER binding point
glBindBuffer(GL_ARRAY_BUFFER, buffer);
Listing 5.1: Creating and initializing a buffer
清單5.1:創(chuàng)建和初始化一個(gè)緩沖區(qū)對(duì)象
After the code in Listing 5.1 has executed, buffer contains the name of a buffer object that has been initialized to represent one megabyte of storage for whatever data we choose. Using the GL_ARRAY_BUFFER target to refer to the buffer object suggests to OpenGL that we’re planning to use this buffer to store vertex data, but we’ll still be able to take that buffer and bind it to some other target later. There are a handful of ways to get data into the buffer object. You may have noticed the NULL pointer that we pass as the third argument to glNamedBufferStorage() in Listing 5.1. Had we instead supplied a pointer to some data, that data would have been used to initialize the buffer object. Using this pointer, however, allows us to set only the initial data to be stored in the buffer.
清單5.1的代碼執(zhí)行完畢后,你就拿到了一個(gè)大小為1MB的緩沖區(qū)對(duì)象了。GL_ARRAY_BUFFER告訴OpenGL,我們將使用這個(gè)緩沖區(qū)對(duì)象存儲(chǔ)頂點(diǎn)數(shù)據(jù),但是我們依然可以在后面 把它用作其他用途。我們有很多種方法給緩沖區(qū)對(duì)象里面塞數(shù)據(jù),注意到清單5.1的第三個(gè)參數(shù),我們給它傳了個(gè)NULL,表示我們只申請(qǐng)內(nèi)存,而不傳數(shù)據(jù)。如果這里第三個(gè)參數(shù)是有數(shù)據(jù)的,那么這些 數(shù)據(jù)將會(huì)被傳遞到緩沖區(qū)對(duì)象的內(nèi)存上去
Another way get data into a buffer is to give the buffer to OpenGL and tell it to copy data there. This allows you to dynamically update the content of a buffer after it has already been initialized. To do this, we call either glBufferSubData() or glNamedBufferSubData(), passing the size of the data we want to put into the buffer, the offset in the buffer where we want it to go, and a pointer to the data in memory that should be put into the buffer. glBufferSubData() and glNamedBufferSubData() are declared as follows:
另一個(gè)寫(xiě)數(shù)據(jù)的方法就是在創(chuàng)建緩沖區(qū)之后,使用glBufferSubData或者是glNamedBufferSubData函數(shù),這些API讓你可以動(dòng)態(tài)的去更新緩沖區(qū)對(duì)象的內(nèi)容。offset是寫(xiě)入數(shù)據(jù)位置的偏移, size是數(shù)據(jù)的大小,data是我們要寫(xiě)入的數(shù)據(jù)
void glBufferSubData(GLenum target,
GLintptr offset,
GLsizeiptr size,
const GLvoid data);
void glNamedBufferSubData(GLuint buffer,
GLintptr offset,
GLsizeiptr size,
const void data);
To update a buffer object using glBufferSubData(), you must have told OpenGL that you want to put data into it that way. To do this, include GL_DYNAMIC_STORAGE_BIT in the flags parameter to glBufferStorage() or glNamedBufferStorage(). Like glBufferStorage() and glNamedBufferStorage(), glBufferSubData() affects the buffer bound to the binding point specified by target, and glNamedBufferSubData() affects the buffer object specified by buffer. Listing 5.2 shows how we can put the data originally used in Listing 3.1 into a buffer object, which is the first step in automatically feeding a vertex shader with data.
為了使用glBufferSubData更新緩沖區(qū)對(duì)象的內(nèi)容,你需要在創(chuàng)建它的時(shí)候使用GL_DYNAMIC_STORAGE_BIT。 glBufferSubData會(huì)影響到綁定節(jié)點(diǎn)的緩沖區(qū)對(duì)象,glNamedBufferSubData會(huì)影響由buffer指定的緩沖區(qū)對(duì)象的數(shù)據(jù)內(nèi)容。清單5.2展示了我們?nèi)绾伟亚鍐?.1中的數(shù)據(jù)用今天學(xué)的方式傳給緩沖區(qū)對(duì)象
// This is the data that we will place into the buffer object
static const float data[] =
{
0.25, -0.25, 0.5, 1.0,
-0.25, -0.25, 0.5, 1.0,
0.25, 0.25, 0.5, 1.0
};// Put the data into the buffer at offset zero
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(data), data);
Listing 5.2: Updating the content of a buffer with glBufferSubData()
清單5.2,使用glBufferSubData更新緩沖區(qū)對(duì)象的內(nèi)容
Another method for getting data into a buffer object is to ask OpenGL for a pointer to the memory that the buffer object represents and then copy the data there yourself. This is known as mapping the buffer. Listing 5.3 shows how to do this using the glMapNamedBuffer() function
另一個(gè)往緩沖區(qū)對(duì)象里寫(xiě)數(shù)據(jù)的方法是使用mapping方法,如下所示
// This is the data that we will place into the buffer object
static const float data[] =
{
0.25, -0.25, 0.5, 1.0,
-0.25, -0.25, 0.5, 1.0,
0.25, 0.25, 0.5, 1.0
};
// Get a pointer to the buffer's data store
void * ptr = glMapNamedBuffer(buffer, GL_WRITE_ONLY);
// Copy our data into it...
memcpy(ptr, data, sizeof(data));
// Tell OpenGL that we're done with the pointer
glUnmapNamedBuffer(GL_ARRAY_BUFFER);
Listing 5.3: Mapping a buffer’s data store with glMapNamedBuffer()
As with many other buffer functions in OpenGL, there are two versions—one that affects the buffer bound to one of the targets of the current context, and one that operates directly on a buffer whose name you specify. Their prototypes are
跟其他眾多的緩沖區(qū)操作函數(shù)一樣,mapping方法有兩個(gè)版本,如下所示
void glMapBuffer(GLenum target,
GLenum usage);
void glMapNamedBuffer(GLuint buffer,
GLenum usage);
To unmap the buffer, we call either glUnmapBuffer() or glUnmapNamedBuffer(), as shown in Listing 5.3. Their prototypes are
unmapping操作使用對(duì)應(yīng)的glUnmapBuffer或者glUnmapNamedBuffer
void glUnmapBuffer(GLenum target);
void glUnmapNamedBuffer(GLuint buffer);
Mapping a buffer is useful if you don’t have all the data handy when you call the function. For example, you might be about to generate the data, or to read it from a file. If you wanted to use glBufferSubData() (or the initial pointer passed to glBufferData()), you’d have to generate or read the data into temporary memory and then get OpenGL to make another copy of the data into the buffer object. If you map a buffer, you can simply read the contents of the file directly into the mapped buffer. When you unmap it, if OpenGL can avoid making a copy of the data, it will. Regardless of whether we used glBufferSubData() or glMapBuffer() and an explicit copy to get data into our buffer object, it now contains a copy of data[] and we can use it as a source of data to feed our vertex shader
mapping的好處在于,你不必要在C語(yǔ)言中保存一份數(shù)據(jù)的拷貝,你可以直接去操作GPU上的數(shù)據(jù)。比如,如果你從文件中讀入數(shù)據(jù),去更新緩沖區(qū)對(duì)象的內(nèi)容, 如果使用glBufferSubData的方式,你必須先從文件里把內(nèi)容讀到內(nèi)存,然后再使用glBufferSubData更新數(shù)據(jù),如果你使用mapping的方式,那么 你可以直接從文件中讀入數(shù)據(jù)到緩沖區(qū)對(duì)象中。
The glMapBuffer() and glMapNamedBuffer() functions can sometimes be a little heavy handed. They map the entire buffer, and do not provide any information about the type of mapping operation to be performed besides the usage parameter. Even that serves only as a hint. A more surgical approach can be taken by calling either glMapBufferRange() or glMapNamedBufferRange(), whose prototypes are
使用glMapBuffer和glMapNamedBuffer有時(shí)候會(huì)太暴力了,因?yàn)樗黰apping了整個(gè)緩沖區(qū),另一個(gè)更推薦的方式是glMapBufferRange和glMapNamedBufferRange
void glMapBufferRange(GLenum target,
GLintptr offset,
GLsizeiptr length,
GLbitfield access);
void glMapNamedBufferRange(GLuint buffer,
GLintptr offset,
GLsizeiptr length,
GLbitfield access);
As with the glMapBuffer() and glMapNamedBuffer() functions, there are two versions of these functions—one that affects a currently bound buffer and one that affects a directly specified buffer object. These functions, rather than mapping the entire buffer object, map only a specific range of the buffer object. This range is given using the offset and length parameters. The parameter contains flags that tell OpenGL how the mapping should be performed. These flags can be a combination of any of the bits listed in Table 5.2.
跟glMapBuffer和glMapNamedBuffer一樣,有兩個(gè)版本-一個(gè)影響當(dāng)前綁定節(jié)點(diǎn)的緩沖區(qū)對(duì)象,一個(gè)影響由第一個(gè)參數(shù)指定的緩沖區(qū)對(duì)象。 比起mapping整個(gè)緩沖區(qū),這倆函數(shù)只mapping了一部分。offset指出從哪個(gè)偏移地址開(kāi)始mapping,length表示要mapping多大的數(shù)據(jù)塊。 最后的標(biāo)志位如表5.2所示。
As with the bits that you can pass to glBufferStorage(), these bits can control some advanced functionality of OpenGL and, in some cases, their correct usage depends on other OpenGL functionality. However, these bits are not hints and OpenGL will enforce their correct usage. You should set GL_MAP_READ_BIT if you plan to read from the buffer and GL_MAP_WRITE_BIT if you plan to write to it. Reading or writing into the mapped range without setting the appropriate bits is an error. The GL_MAP_PERSISTENT_BIT and GL_MAP_COHERENT_BIT flags have similar meanings to their identically named counterparts in glBufferStorage(). All four of these bits are required to match between when you specify storage and when you request a mapping. That is, if you want to map a buffer for reading using the GL_MAP_READ_BIT flag, then you must also specify the GL_MAP_READ_BIT flag when you call glBufferStorage()
與創(chuàng)建緩沖區(qū)時(shí)那些標(biāo)志不同的是,這里的標(biāo)志位設(shè)置不是提示,而是強(qiáng)制設(shè)置,也就是說(shuō),如果你mapping的時(shí)候設(shè)置了讀的標(biāo)志位,那么后面卻往里面寫(xiě)數(shù)據(jù),就會(huì)出錯(cuò)。 還有一點(diǎn)需要注意的是,為了這里能夠?qū)崿F(xiàn)讀寫(xiě)操作,你需要在創(chuàng)建該緩沖區(qū)對(duì)象的時(shí)候,就設(shè)置相應(yīng)的標(biāo)志位
We’ll dig deeper into the remaining flags when we cover synchronization primitives a little later in the book. However, because of the additional control and stronger contract provided by glMapBufferRange() and glMapNamedBufferRange(), it isgenerally preferred to call these functions rather than glMapNamedBuffer() (or glMapBuffer()). You should get into the habbit of using these functions even if you’re not using any of their more advanced features
我們將在后面的內(nèi)容中更加深入的聊其他的那些標(biāo)志位。你應(yīng)該更多的使用glMapBufferRange的API而不是glMapBuffer,因?yàn)檫@樣你能獲得更多的性能方面的提升。
本日的翻譯就到這里,明天見(jiàn),拜拜~~
第一時(shí)間獲取最新橋段,請(qǐng)關(guān)注東漢書(shū)院以及圖形之心公眾號(hào)
東漢書(shū)院,等你來(lái)玩哦
免責(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)容。