Good judgement comes from experiences, and the experience comes from bad judgement. --Fred Brooks
* 원문링크 :
http://oss.sgi.com/projects/ogl-sample/registry/ARB/vertex_buffer_object.txt
http://oss.sgi.com/projects/ogl-sample/registry/ARB/vertex_buffer_object.txt
- DX9의 깔끔한 정점 배열 관리 함수들이 부러웠는데, GL도 이렇게 통합작업을 거쳐서 정리를 하는군요. ATI와 nvidia가 그래픽 표준을 이끌고 간다는 생각이 문득 들고 있습니다.
3 공헌자 목록 #
Ben Ashbaugh, Bob Beretta, Pat Brown, Cass Everitt, John Kessenich, Dale Kirkland, Jon Leech, Bill Licea-Kane, Barthold Lichtenbelt, Bimal Poddar, Thomas Roell, Ian Romanick, Jeremy Sandmel, Jon Paul Schelter, John Stauffer, Nick Triantos, Daniel Vogel
4 협력해주신 분들 #
Rick Hammerstone, ATI 연구소(rhammers 'at' ati.com), Matt Craighead, NVIDIA (mcraighead 'at' nvidia.com), Kurt Akeley, NVIDIA (kakeley 'at' nvidia.com)
8 다른 extension과의 의존성 #
- opengl 1.4에 실린 용어에 기초하여 작성되어있습니다.
- 이 extension에 영향을 준 extension 목록 : GL_ARB_vertex_blend, GL_ARB_vertex_program, GL_EXT_vertex_shader
9 개요 #
This extension defines an interface that allows various types of data (especially vertex array data) to be cached in high-performance graphics memory on the server, thereby increasing the rate of data transfers.
Chunks of data are encapsulated within "buffer objects", which conceptually are nothing more than arrays of bytes, just like any chunk of memory. An API is provided whereby applications can read from or write to buffers, either via the GL itself (glBufferData, glBufferSubData, glGetBufferSubData) or via a pointer to the memory.
The latter technique is known as "mapping" a buffer. When an application maps a buffer, it is given a pointer to the memory. When the application finishes reading from or writing to the memory, it is required to "unmap" the buffer before it is once again permitted to use that buffer as a GL data source or sink. Mapping often allows applications to eliminate an extra data copy otherwise required to access the buffer, thereby enhancing performance. In addition, requiring that applications unmap the buffer to use it as a data source or sink ensures that certain classes of latent synchronization bugs cannot occur.
Although this extension only defines hooks for buffer objects to be used with OpenGL's vertex array APIs, the API defined in this extension permits buffer objects to be used as either data sources or sinks for any GL command that takes a pointer as an argument. Normally, in the absence of this extension, a pointer passed into the GL is simply a pointer to the user's data. This extension defines a mechanism whereby this pointer is used not as a pointer to the data itself, but as an offset into a currently bound buffer object. The buffer object ID zero is reserved, and when buffer object zero is bound to a given target, the commands affected by that buffer binding behave normally. When a nonzero buffer ID is bound, then the pointer represents an offset.
In the case of vertex arrays, this extension defines not merely one binding for all attributes, but a separate binding for each individual attribute. As a result, applications can source their attributes from multiple buffers. An application might, for example, have a model with constant texture coordinates and variable geometry. The texture coordinates might be retrieved from a buffer object with the usage mode "STATIC_DRAW", indicating to the GL that the application does not expect to update the contents of the buffer frequently or even at all, while the vertices might be retrieved from a buffer object with the usage mode "STREAM_DRAW", indicating that the vertices will be updated on a regular basis.
In addition, a binding is defined by which applications can source index data (as used by DrawElements, DrawRangeElements, and MultiDrawElements) from a buffer object. On some platforms, this enables very large models to be rendered with no more than a few small commands to the graphics device.
It is expected that a future extension will allow sourcing pixel data from and writing pixel data to a buffer object.
11 새로 추가된 함수들 #
void BindBufferARB(enum target, uint buffer); void DeleteBuffersARB(sizei n, const uint *buffers); void GenBuffersARB(sizei n, uint *buffers); boolean IsBufferARB(uint buffer); void BufferDataARB(enum target, sizeiptrARB size, const void *data, enum usage); void BufferSubDataARB(enum target, intptrARB offset, sizeiptrARB size, const void *data); void GetBufferSubDataARB(enum target, intptrARB offset, sizeiptrARB size, void *data); void *MapBufferARB(enum target, enum access); boolean UnmapBufferARB(enum target); void GetBufferParameterivARB(enum target, enum pname, int *params); void GetBufferPointervARB(enum target, enum pname, void **params);
12 신규 토큰 #
Accepted by the <target> parameters of BindBufferARB, BufferDataARB, BufferSubDataARB, MapBufferARB, UnmapBufferARB, GetBufferSubDataARB, GetBufferParameterivARB, and GetBufferPointervARB:
ARRAY_BUFFER_ARB 0x8892
ELEMENT_ARRAY_BUFFER_ARB 0x8893
Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev:
ARRAY_BUFFER_BINDING_ARB 0x8894
ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
Accepted by the <pname> parameter of GetVertexAttribivARB:
VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889FAccepted by the <usage> parameter of BufferDataARB:
STREAM_DRAW_ARB 0x88E0
STREAM_READ_ARB 0x88E1
STREAM_COPY_ARB 0x88E2
STATIC_DRAW_ARB 0x88E4
STATIC_READ_ARB 0x88E5
STATIC_COPY_ARB 0x88E6
DYNAMIC_DRAW_ARB 0x88E8
DYNAMIC_READ_ARB 0x88E9
DYNAMIC_COPY_ARB 0x88EA
Accepted by the <access> parameter of MapBufferARB:
READ_ONLY_ARB 0x88B8
WRITE_ONLY_ARB 0x88B9
READ_WRITE_ARB 0x88BA
Accepted by the <pname> parameter of GetBufferParameterivARB:
BUFFER_SIZE_ARB 0x8764
BUFFER_USAGE_ARB 0x8765
BUFFER_ACCESS_ARB 0x88BB
BUFFER_MAPPED_ARB 0x88BC
Accepted by the <pname> parameter of GetBufferPointervARB:
BUFFER_MAP_POINTER_ARB 0x88BD
13.1 표 2.2에 다음을 추가한다 #
"GL Type Minimum Description Bit Width ----------------------------------------------------------------- intptrARB <ptrbits> signed 2's complement binary integer sizeiptrARB <ptrbits> Non-negative binary integer size"
13.2 표 2.2아래 단락에 다음을 추가한다 #
"<ptrbits> is the number of bits required to represent a pointer type; in other words, types intptrARB and sizeiptrARB must be sufficiently large as to store any address."
13.3.1 2.8A Buffer Objects #
The vertex data arrays described in section 2.8 are stored in client memory. It is sometimes desirable to store frequently used client data, such as vertex array data, in high-performance server memory. GL buffer objects provide a mechanism that clients can use to allocate, initialize, and render from such memory.
The name space for buffer objects is the unsigned integers, with zero reserved for the GL. A buffer object is created by binding an unused name to ARRAY_BUFFER_ARB. The binding is effected by calling
void BindBufferARB(enum target, uint buffer);with <target> set to ARRAY_BUFFER_ARB and <buffer> set to the unused name. The resulting buffer object is a new state vector, initialized with a zero-sized memory buffer, and comprising the state values listed in Table BufObj1.
| Name | Type | Initial Value | Legal Values |
| BUFFER_SIZE_ARB | integer | 0 | any non-negative integer |
| BUFFER_USAGE_ARB | enum | STATIC_DRAW_ARB | STREAM_DRAW_ARB, STREAM_READ_ARB, STREAM_COPY_ARB, STATIC_DRAW_ARB, STATIC_READ_ARB, STATIC_COPY_ARB, DYNAMIC_DRAW_ARB, DYNAMIC_READ_ARB, DYNAMIC_COPY_ARB |
| BUFFER_ACCESS_ARB | enum | READ_WRITE_ARB | READ_ONLY_ARB, WRITE_ONLY_ARB, READ_WRITE_ARB |
| BUFFER_MAPPED_ARB | boolean | FALSE | TRUE, FALSE |
| BUFFER_MAP_POINTER_ARB | void* | NULL | address |
표 BufObj1: 버퍼 객체 매개변수와 해당하는 값들
BindBufferARB may also be used to bind an existing buffer object. If the bind is successful no change is made to the state of the newly bound buffer object, and any previous binding to <target> is broken.
While a buffer object is bound, GL operations on the target to which it is bound affect the bound buffer object, and queries of the target to which a buffer object is bound return state from the bound object.
In the initial state the GL-reserved name zero is bound to ARRAY_BUFFER_ARB. There is no buffer object corresponding to the name zero, so client attempts to modify or query buffer object state for the target ARRAY_BUFFER_ARB while zero is bound will generate GL errors.
Buffer objects are deleted by calling
void DeleteBuffersARB(sizei n, const uint *buffers);
<buffers> contains <n> names of buffer objects to be deleted. After a buffer object is deleted it has no contents, and its name is again unused. Unused names in <buffers> are silently ignored, as is the value zero.
The command
void GenBuffersARB(sizei n, uint *buffers);returns <n> previously unused buffer object names in <buffers>. These names are marked as used, for the purposes of GenBuffersARB only, but they acquire buffer state only when they are first bound, just as if they were unused.
While a buffer object is bound, any GL operations on that object affect any other bindings of that object. If a buffer object is deleted while it is bound, all bindings to that object in the current context (i.e. in the thread that called DeleteBuffers) are reset to bindings to buffer zero. Bindings to that buffer in other contexts and other threads are not affected, but attempting to use a deleted buffer in another thread produces undefined results, including but not limited to possible GL errors and rendering corruption. Using a deleted buffer in another context or thread may not, however, result in program termination.
The data store of a buffer object is created and initialized by calling
void BufferDataARB(enum target, sizeiptrARB size, const void *data, enum usage);with <target> set to ARRAY_BUFFER_ARB, <size> set to the size of the data store in basic machine units, and <data> pointing to the source data in client memory. If <data> is non-null, then the source data is copied to the buffer object's data store. If <data> is null, then the contents of the buffer object's data store are undefined.
<usage> is specified as one of nine enumerated values, indicating the expected application usage pattern of the data store. The values are:
| STREAM_DRAW_ARB | The data store contents will be specified once by the application, and used at most a few times as the source of a GL (drawing) command. |
| STREAM_READ_ARB | The data store contents will be specified once by reading data from the GL, and queried at most a few times by the application. |
| STREAM_COPY_ARB | The data store contents will be specified once by reading data from the GL, and used at most a few times as the source of a GL (drawing) command. |
| STATIC_DRAW_ARB | The data store contents will be specified once by the application, and used many times as the source for GL (drawing) commands. |
| STATIC_READ_ARB | The data store contents will be specified once by reading data from the GL, and queried many times by the application. |
| STATIC_COPY_ARB | The data store contents will be specified once by reading data from the GL, and used many times as the source for GL (drawing) commands. |
| DYNAMIC_DRAW_ARB | The data store contents will be respecified repeatedly by the application, and used many times as the source for GL (drawing) commands. |
| DYNAMIC_READ_ARB | The data store contents will be respecified repeatedly by reading data from the GL, and queried many times by the application. |
| DYNAMIC_COPY_ARB | The data store contents will be respecified repeatedly by reading data from the GL, and used many times as the source for GL (drawing) commands. |
<usage> is provided as a performance hint only. The specified usage value does not constrain the actual usage pattern of the data store.
BufferDataARB deletes any existing data store, and sets the values of the buffer object's state variables to:
| Name | Value |
| BUFFER_SIZE_ARB | |
| BUFFER_USAGE_ARB | |
| BUFFER_ACCESS_ARB | READ_WRITE_ARB |
| BUFFER_MAPPED_ARB | FALSE |
| BUFFER_MAP_POINTER_ARB | NULL |
Clients must align data elements consistent with the requirements of the client platform, with an additional base-level requirement that an offset within a buffer to a datum comprising N basic machine units be a multiple of N.
If the GL is unable to create a data store of the requested size, the error OUT_OF_MEMORY is generated.
To modify some or all of the data contained in a buffer object's data store, the client may use the command
void BufferSubDataARB(enum target, intptrARB offset, sizeiptrARB size, const void *data);
with <target> set to ARRAY_BUFFER_ARB. <offset> and <size> indicate the range of data in the buffer object that is to be replaced, in terms of basic machine units. <data> specifies a region of client memory <size> basic machine units in length, containing the data that replace the specified buffer range. An error is generated if <offset> or <size> is less than zero, or if <offset> + <size> is greater than the value of BUFFER_SIZE_ARB.
The entire data store of a buffer object can be mapped into the client's address space by calling
void *MapBufferARB(enum target, enum access);with <target> set to ARRAY_BUFFER_ARB. If the GL is able to map the buffer object's data store into the client's address space, MapBufferARB returns the pointer value to the data store. Otherwise MapBufferARB returns NULL, and the error OUT_OF_MEMORY is generated. <access> is specified as one of READ_ONLY_ARB, WRITE_ONLY_ARB, or READ_WRITE_ARB, indicating the operations that the client may perform on the data store through the pointer while the data store is mapped.
MapBufferARB sets the following buffer object state values:
| Name | Value |
| BUFFER_ACCESS_ARB | |
| BUFFER_MAPPED_ARB | TRUE |
| BUFFER_MAP_POINTER_ARB | pointer to the data store |
It is an INVALID_OPERATION error to map a buffer data store that is in the mapped state.
Non-null pointers returned by MapBufferARB may be used by the client to modify and query buffer object data, consistent with the access rules of the mapping, while the mapping remains valid. No GL error is generated if the pointer is used to attempt to modify a READ_ONLY_ARB data store, or to attempt to read from a WRITE_ONLY_ARB data store, but operation may be slow and system errors (possibly including program termination) may result. Pointer values returned by MapBufferARB may not be passed as parameter values to GL commands. For example, they may not be used to specify array pointers, or to specify or query pixel or texture image data; such actions produce undefined results, although implementations may not check for such behavior for performance reasons.
It is an INVALID_OPERATION error to call BufferSubDataARB to modify the data store of a mapped buffer.
Mappings to the data stores of buffer objects may have nonstandard performance characteristics. For example, such mappings may be marked as uncacheable regions of memory, and in such cases reading from them may be very slow. To ensure optimal performance, the client should use the mapping in a fashion consistent with the values of BUFFER_USAGE_ARB and BUFFER_ACCESS_ARB. Using a mapping in a fashion inconsistent with these values is liable to be multiple orders of magnitude slower than using normal memory.
After the client has specified the contents of a mapped data store, and before the data in that store are dereferenced by any GL commands, the mapping must be relinquished by calling
boolean UnmapBufferARB(enum target);
with <target> set to ARRAY_BUFFER_ARB. Unmapping a mapped buffer object invalidates the pointers to its data store and sets the object's BUFFER_MAPPED_ARB state to FALSE and its BUFFER_MAP_POINTER_ARB state to NULL.
UnmapBufferARB returns TRUE unless data values in the buffer's data store have become corrupted during the period that the buffer was mapped. Such corruption can be the result of a screen resolution change or other window-system-dependent event that causes system heaps such as those for high-performance graphics memory to be discarded. GL implementations must guarantee that such corruption can occur only during the periods that a buffer's data store is mapped. If such corruption has occurred, UnmapBufferARB returns FALSE, and the contents of the buffer's data store become undefined.
It is an INVALID_OPERATION error to explicitly unmap a buffer data store that is in the unmapped state. Unmapping that occurs as a side effect of buffer deletion or reinitialization is not an error, however.
13.3.2 2.8A.1 버퍼 객체내의 정점 배열 #
Blocks of vertex array data may be stored in buffer objects with the same format and layout options supported for client-side vertex arrays. However, it is expected that GL implementations will (at minimum) be optimized for data with all components represented as floats, as well as for color data with components represented as either floats or unsigned bytes.
A buffer object binding point is added to the client state associated with each vertex array type. The client does not directly specify the bindings to with these new binding points. Instead, the commands that specify the locations and organizations of vertex arrays copy the buffer object name that is bound to ARRAY_BUFFER_ARB to the binding point corresponding to the vertex array of the type being specified. For example, the NormalPointer command copies the value of ARRAY_BUFFER_BINDING_ARB (the queriable name of the buffer binding corresponding to the target ARRAY_BUFFER_ARB) to the client state variable NORMAL_ARRAY_BUFFER_BINDING_ARB.
If EXT_vertex_shader is defined, then the command VariantArrayEXT(uint id, ...) copies the value of ARRAY_BUFFER_BINDING_ARB to the buffer object binding point corresponding to variant array <id>.
If ARB_vertex_program is defined, then the command VertexAttribPointerARB(int attrib, ...) copies the value of ARRAY_BUFFER_BINDING_ARB to the buffer object binding point corresponding to vertex attrib array <attrib>.
If ARB_vertex_blend is defined, then the command WeightPointerARB copies the value of ARRAY_BUFFER_BINDING_ARB to WEIGHT_ARRAY_BUFFER_BINDING_ARB.
Rendering commands ArrayElement, DrawArrays, DrawElements, DrawRangeElements, MultiDrawArrays, and MultiDrawElements operate as previously defined, except that data for enabled vertex, variant, and attrib arrays are sourced from buffers if the array's buffer binding is non-zero. When an array is sourced from a buffer object, the pointer value of that array is used to compute an offset, in basic machine units, into the data store of the buffer object. This offset is computed by subtracting a null pointer from the pointer value, where both pointers are treated as pointers to basic machine units.
It is acceptable for vertex, variant, or attrib arrays to be sourced from any combination of client memory and various buffer objects during a single rendering operation.
It is an INVALID_OPERATION error to source data from a buffer object that is currently mapped.
13.3.3 2.8B.1 버퍼 객체내의 배열 인덱스 #
Blocks of array indices may be stored in buffer objects with the same format options that are supported for client-side index arrays. Initially zero is bound to ELEMENT_ARRAY_BUFFER_ARB, indicating that DrawElements and DrawRangeElements are to source their indices from arrays passed as their <indices> parameters, and that MultiDrawElements is to source its indices from the array of pointers to arrays passed in as its <indices> parameter.
A buffer object is bound to ELEMENT_ARRAY_BUFFER_ARB by calling
void BindBufferARB(enum target, uint buffer);with <target> set to ELEMENT_ARRAY_BUFFER_ARB, and <buffer> set to the name of the buffer object. If no corresponding buffer object exists, one is initialized as defined in Section 2.8A.
The commands BufferDataARB, BufferSubDataARB, MapBufferARB, and UnmapBufferARB may all be used with <target> set to ELEMENT_ARRAY_BUFFER_ARB. In such event, these commands operate in the same fashion as described in section 2.8A, but on the buffer currently bound to the ELEMENT_ARRAY_BUFFER_ARB target.
While a non-zero buffer object name is bound to ELEMENT_ARRAY_BUFFER_ARB, DrawElements and DrawRangeElements source their indices from that buffer object, using their <indices> parameters as offsets into the buffer object in the same fashion as described in section 2.8A1. MultiDrawElements also sources its indices from that buffer object, using its <indices> parameter as a pointer to an array of pointers that represent offsets into the buffer object.
Buffer objects created by binding an unused name to ARRAY_BUFFER_ARB and to ELEMENT_ARRAY_BUFFER_ARB are formally equivalent, but the GL may make different choices about storage implementation based on the initial binding. In some cases performance will be optimized by storing indices and array data in separate buffer objects, and by creating those buffer objects with the corresponding binding points.
13.4 5.4장의 디스플레이 리스트에 컴파일되는 명령을 논의하는 부분에 추가될 부분 #
Commands that are used to create, manage, and query buffer objects are not included in display lists, but are executed immediately. These commands are BindBufferARB, DeleteBuffersARB, GenBuffersARB, IsBufferARB, BufferDataARB, BufferSubDataARB, MapBufferARB, UnmapBufferARB, GetBufferParameterivARB, GetBufferSubDataARB, and GetBufferPointervARB.
GL commands that source data from buffer objects dereference the buffer object data in question at display list compile time, rather than encoding the buffer ID and buffer offset into the display list. Only GL commands that are executed immediately, rather than being compiled into a display list, are permitted to use a buffer object as a data sink.
14 사용 예제 #
These examples illustrate various usages. In all cases a rendering loop is included, and array parameters are initialized inside the loop as would be required if multiple array rendering operations were performed in the loops. (Though only one operation is shown.)
Convenient macro definition for specifying buffer offsets:
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
전통적인 정점 배열:
// Create system memory buffer data = malloc(320); // Fill system memory buffer ... // Frame rendering loop while (...) { // Define arrays VertexPointer(4, FLOAT, 0, data); ColorPointer(4, UNSIGNED_BYTE, 0, data+256); // Enable arrays EnableClientState(VERTEX_ARRAY); EnableClientState(COLOR_ARRAY); // Draw arrays DrawArrays(TRIANGLE_STRIP, 0, 16); // Disable arrays DisableClientState(VERTEX_ARRAY); DisableClientState(COLOR_ARRAY); // Other rendering commands ... } // Free system memory buffer free(data);
버퍼 객체를 사용한 정점 배열:
// Create system memory buffer data = malloc(320); // Fill system memory buffer ... // Create buffer object BindBufferARB(ARRAY_BUFFER_ARB, 1); // Initialize data store of buffer object BufferDataARB(ARRAY_BUFFER_ARB, 320, data, STATIC_DRAW_ARB); // Free system memory buffer free(data); // Frame rendering loop while (...) { // Define arrays BindBufferARB(ARRAY_BUFFER_ARB, 1); VertexPointer(4, FLOAT, 0, BUFFER_OFFSET(0)); ColorPointer(4, UNSIGNED_BYTE, 0, BUFFER_OFFSET(256)); // Enable arrays EnableClientState(VERTEX_ARRAY); EnableClientState(COLOR_ARRAY); // Draw arrays DrawArrays(TRIANGLE_STRIP, 0, 16); // Disable arrays DisableClientState(VERTEX_ARRAY); DisableClientState(COLOR_ARRAY); // Other rendering commands ... } // Delete buffer object int buffer[1] = {1}; DeleteBuffersARB(1, buffer);
버퍼 객체 사용여부를 선택할 수 있는 코드예제:
// Create system memory buffer data = malloc(320); // Fill system memory buffer ... // Initialize buffer object, and null the data pointer #ifdef USE_BUFFER_OBJECTS BindBufferARB(ARRAY_BUFFER_ARB, 1); BufferDataARB(ARRAY_BUFFER_ARB, 320, data, STATIC_DRAW_ARB); free(data); data = NULL; #endif // Frame rendering loop while (...) { // Define arrays #ifdef USE_BUFFER_OBJECTS BindBufferARB(ARRAY_BUFFER_ARB, 1); #endif VertexPointer(4, FLOAT, 0, data); ColorPointer(4, UNSIGNED_BYTE, 0, data+256); // Enable arrays EnableClientState(VERTEX_ARRAY); EnableClientState(COLOR_ARRAY); // Draw arrays DrawArrays(TRIANGLE_STRIP, 0, 16); // Disable arrays DisableClientState(VERTEX_ARRAY); DisableClientState(COLOR_ARRAY); // Other rendering commands ... } // Delete buffer object #ifdef USE_BUFFER_OBJECTS int buffer[1] = {1}; DeleteBuffersARB(1, buffer); #else // Free system memory buffer free(data); #endif
매핑된 버퍼객체를 사용한 정점 배열:
// Frame rendering loop while (...) { // Define arrays (and create buffer object in first pass) BindBufferARB(ARRAY_BUFFER_ARB, 1); VertexPointer(4, FLOAT, 0, BUFFER_OFFSET(0)); ColorPointer(4, UNSIGNED_BYTE, 0, BUFFER_OFFSET(256)); // Enable arrays EnableClientState(VERTEX_ARRAY); EnableClientState(COLOR_ARRAY); // Initialize data store of buffer object BufferDataARB(ARRAY_BUFFER_ARB, 320, NULL, STREAM_DRAW_ARB); // Map the buffer object float *p = MapBufferARB(ARRAY_BUFFER_ARB, WRITE_ONLY); // Compute and store data in mapped buffer object ... // Unmap buffer object and draw arrays if (UnmapBufferARB(ARRAY_BUFFER_ARB)) { DrawArrays(TRIANGLE_STRIP, 0, 16); } // Disable arrays DisableClientState(VERTEX_ARRAY); DisableClientState(COLOR_ARRAY); // Other rendering commands ... } // Delete buffer object int buffer[1] = {1}; DeleteBuffersARB(1, buffer);
Vertex arrays using a mapped buffer object for array data and an unmapped buffer object for indices:
// Create system memory buffer for indices indexdata = malloc(400); // Fill system memory buffer with 100 indices ... // Create index buffer object BindBufferARB(ELEMENT_ARRAY_BUFFER_ARB, 2); BufferDataARB(ELEMENT_ARRAY_BUFFER_ARB, 400, indexdata, STATIC_DRAW_ARB); // Free system memory buffer free(indexdata); // Frame rendering loop while (...) { // Define arrays (and create buffer object in first pass) BindBufferARB(ARRAY_BUFFER_ARB, 1); VertexPointer(4, FLOAT, 0, BUFFER_OFFSET(0)); ColorPointer(4, UNSIGNED_BYTE, 0, BUFFER_OFFSET(256)); BindBufferARB(ELEMENT_ARRAY_BUFFER_ARB, 2); // Enable arrays EnableClientState(VERTEX_ARRAY); EnableClientState(COLOR_ARRAY); // Initialize data store of buffer object BufferDataARB(ARRAY_BUFFER_ARB, 320, NULL, STREAM_DRAW_ARB); // Map the buffer object float *p = MapBufferARB(ARRAY_BUFFER_ARB, WRITE_ONLY); // Compute and store data in mapped buffer object ... // Unmap buffer object and draw arrays if (UnmapBufferARB(ARRAY_BUFFER_ARB)) { DrawElements(TRIANGLE_STRIP, 100, UNSIGNED_INT, BUFFER_OFFSET(0)); } // Disable arrays DisableClientState(VERTEX_ARRAY); DisableClientState(COLOR_ARRAY); // Other rendering commands ... } // Delete buffer objects int buffers[2] = {1, 2}; DeleteBuffersARB(1, buffers);
동시에 여러 버퍼를 매핑하기:
// Map buffers BindBuffer(ARRAY_BUFFER_ARB, 1); float *a = MapBuffer(ARRAY_BUFFER_ARB, WRITE_ONLY); BindBuffer(ARRAY_BUFFER_ARB, 2); float *b = MapBuffer(ARRAY_BUFFER_ARB, WRITE_ONLY); // Fill buffers ... // Unmap buffers BindBuffer(ARRAY_BUFFER_ARB, 1); if (!UnmapBufferARB(ARRAY_BUFFER_ARB)) { // Handle error case } BindBuffer(ARRAY_BUFFER_ARB, 2); if (!UnmapBufferARB(ARRAY_BUFFER_ARB)) { // Handle error case }








