OpenGL Data type #
OpenGL provides Buffer and Texture as storage for more efficient data streaming. (modern graphics processors are designed with streaming processor.)
Buffer
- glBindBuffer()
- glBufferData()
- glBufferSubData()
- glClearBufferSubData()
- glCopyBufferSubData()
- glGenBuffers()
- glMapBuffer() <– - glCreateBuffers –>
Vertex Attribute
- glVertexAttribPointer()
- glEnableVertexAttribArray()
- glDisableVertexAttribArray()
- glGetAttribLocation()
Uniform
- Default Block
- glUniform*()
- glUniformMatrix*()
- Uniform Block
- glGetUniformIndicies()
- glGetActiveUniforms()
- glGetUniformLocation()
Buffer #
need name for identify handle
memory space allocated for buffer object is called data storage.
two method to put data in buffer are ; using command ; mapping with pointer
can bind into context’s buffer binding point with buffer’s name.
binding point can be refered as target in most cases. (but target may have multiple binging point)
buffer binding process
glGenBuffers -> glBindBuffer -> glBufferData
- There’s many way to manipulate buffer object’s data
- using
data
parameter of glBufferData() - using glBufferSubData()
- using glMapBuffer()
- using
- glBindBuffer()
void glBindBuffer (GLenum target, GLuint buffer);
target
enum list- GL_ARRAY_BUFFER : Vertex attributes
- GL_ATOMIC_COUNTER_BUFFER : Atomic counter storage
- GL_COPY_READ_BUFFER : Buffer copy source
- GL_COPY_WRITE_BUFFER : Buffer copy destination
- GL_DISPATCH_INDIRECT_BUFFER : Indirect compute dispatch commands
- GL_DRAW_INDIRECT_BUFFER : Indirect command arguments
- GL_ELEMENT_ARRAY_BUFFER : Vertex array indices
- GL_PIXEL_PACK_BUFFER : Pixel read target
- GL_PIXEL_UNPACK_BUFFER : Texture data source
- GL_QUERY_BUFFER : Query result buffer
- GL_SHADER_STORAGE_BUFFER : Read-write storage for shaders
- GL_TEXTURE_BUFFER : Texture data buffer
- GL_TRANSFORM_FEEDBACK_BUFFER : Transform feedback buffer
- GL_UNIFORM_BUFFER : Uniform block storage
- glBufferData()
void glBufferData (GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
create ‘data store’(memory) for current buffer object of target
.
target
enum list- GL_ARRAY_BUFFER
- GL_ELEMENT_ARRAY_BUFFER
- GL_PIXEL_PACK_BUFFER
- GL_PIXEL_UNPACK_BUFFER
usage
enum list- GL_STREAM_DRAW : modified once by application, accessed rarely, used for drawing and imaging.
- GL_STREAM_READ : modified once by GL reading, accessed rarely, used for returning data for queries of application.
- GL_STREAM_COPY : modified once by GL reading, accessed rarely, used for drawing and imaging.
- GL_STATIC_DRAW : modified once by GL application, accessed often, used for drawing and imaging.
- GL_STATIC_READ : modified once by GL reading, accessed often, used for returning data for queries of application.
- GL_STATIC_COPY : modified once by GL reading, accessed often, used for drawing and imaging.
- GL_DYNAMIC_DRAW : modified multiple time by GL application, accessed often, used for drawing and imaging.
- GL_DYNAMIC_READ : modified multiple time by GL reading, accessed often, used for returning data for queries of application.
- GL_DYNAMIC_COPY : modified multiple time by GL reading, accessed often, used for drawing and imaging.
size
is size of data store.data
is pointer indicating where data storage copy initial data from.
can be setted as NULL and data store won’t be initalized.
- glBufferSubData()
void glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
target
enum list is same with glBindBuffer.offset
is position inside buffer to start inserting datasize
is byte size of inserting datadata
is pointer for data to insert in buffer
- glClearBufferSubData()
void glClearBufferSubData (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void * data);
format
enum list- GL_RED : 1 channel
- GL_RG : 2 channel
- GL_RGB : 3 channel
- GL_RGBA : 4 channel
type
basic types- GL_BYTE : GLchar
- GL_UNSIGNED_BYTE : GLuchar
- GL_SHORT : GLshort
- GL_UNSIGNED_SHORT : GLushort
- GL_INT : GLint
- GL_UNSINGED_INT : GLuint
- GL_FLOAT : GLfloat
- GL_DOUBLE. : GLdouble
target
is buffer to clear with constant valueinternalformat
is specific format to convertoffset
is offset byte to start clearsize
is bytes to continue clearformat
andtype
are method to adjust data indata
- glCopyBufferSubData()
vod glCopyBufferSubData (GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size);
this function use buffer binding points_
readtarget, writetarget
_. and this way of copying has unwanted sideeffects sometime.
so GL_COPY_READ_BUFFER and GL_COPY_WRITE_BUFFER are provided for dedicated binding point.
- glGenBuffers()
void glGenBuffers (GLsizei n, GLuint * buffers);
glGenBuffers generate
n
of buffers and insert their buffer names into GLuint arraybuffers
.
- glMapBuffer()
void* glMapBuffer (GLenum target, GLenum access);
access
enum list- GL_READ_ONLY : returned pointer will be used for reading buffer object’s data
- GL_WRITE_ONLY : returned pointer will be used for writing buffer object’s data
- GL_READ_WRITE : returned pointer will be used for both reading and writing
map data store of
target
buffer object into client’s address space and return its void* pointer address.target
enum list is same with glBindBuffer.
using returned pointer address for GL function parameter is nonstandard. it may occur unexpected result.
can unmap withglUnmapBuffer (_target_);
.
Vertex attribute #
- glVertexAttribPointer()
void glVertexAttribPointer (GLuint index,
GLint size = 0,
GLenum type = GL_FLOAT,
GLboolean normalized.
GLsizei stride = 0,
const GLvoid * pointer = 0 );
index
is index of vertex attribute inside “layout (location = index)” to insert.size
is number (1, 2, 3, 4) of components like ‘3 for vec3’ or ‘4 for vec4’.type
is data types like GL_FLOAT, GL_INT, GL_BYTE, etc.
since float is standard type for opengl vector, they will be converted into float, and it’s reason fornormalized
is important.
ifnormalized
is GL_TRUE, that means datas’ values need to be float with value between 0.0 to 1.0 for unsigned, -1.0 to 1.0 for signed.stride
indicates offset gap size between first attribute and second attribute. If this value is 0, it will besizeof(type) * size
.pointer
parameter seems like pointer, but it’s byte offset for where attribute starts inside of GL_ARRAY_BUFFER.
- glEnableVertexAttribArray()
void glEnableVertexAttribArray (GLuint index);
- glDisableVertexAttribArray()
void glDisableVertexAttribArray (GLuint index);
if vertex attrib array is disabled, vertex attributes will be modified with glVertexAttrib*() funcionts.
if vertex attrib array is abled, vertex attributes will be binded with glVertexAttribPointer() funtion.
- glGetAttribLocation()
GLint glGetAttribLocation (GLuint program, const GLchar * name);
if your put program that owning vertex shader in
program
and
name of vertex attribute’s name(identifier) inname
,
it will returnname
’s location number.
if there no attribute with name,name
, it will return -1.
Uniform #
While attributes contribute in per-vertex sahder values (like position of vertice),
uniform contirbute in same values to several vertex shaders (like transform matrix).Uniform can exist in all kind of shaders.
Uniform in shaders are always constant and cannot be assigned by shader.
uniform may disappear after compile if none of shader use that uniform.
variable names are case-sensitive.
Default block
- Default block uniforms are just like sending vertex attributes but use glUniform*() instead glVertexAttrib*().
- glUniform*()
//functions below are sample glUniform*(). void glUniform1f (GLint location, GLfloat v0); //glUniform1~4f void glUniform2i (GLint location, GLint v0, GLint v1); //glUniform1~4i void glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); //glUniform1~4ui //functions below are glUniform*v() that use pointer (i.e. array, vector) to store multiple uniform data. void glUniform1fv (GLint location, GLuint count, const GLfloat* value); //glUniform1~4fv void glUniform2iv (GLint location, GLuint count, const GLint* value); //glUniform1~4iv void glUniform4uiv (GLint location, GLuint count, const GLuint* value); //glUniform1~4uiv
put
value
orv*
into uniform with layout(location =location
).
boolean can be sent by any type of funtion like how C works.count
is length ofvalue
, array that contain arrays(i.e. vectors).
value is pointer (not pointer-pointer). and that means you dont need to put parametervalue
into form of array[][], instead just put array’s name (pointer). - glUniformMatrix*()
//matrix that store single-precision floating values glUniformMatrix2fv (GLint location, GLuint count, GLboolean transpose, const GLfloat *m); glUniformMatrix3fv (GLint location, GLuint count, GLboolean transpose, const GLfloat *m); glUniformMatrix4fv (GLint location, GLuint count, GLboolean transpose, const GLfloat *m); //matrix that store double-precition floating values glUniformMatrix2dv (GLint location, GLuint count, GLboolean transpose, const GLdouble *m); glUniformMatrix3dv (GLint location, GLuint count, GLboolean transpose, const GLdouble *m); glUniformMatrix4dv (GLint location, GLuint count, GLboolean transpose, const GLdouble *m);
shader matrices only stores single and double precision floating-point variety.
this function can store array of matrices by settingcount
into larger than 1.
OpenGL’s matrix is column-major. if sending matrix is not column-major, settranspose
into GL_TRUE.
so, usetranspose
parameter in handy if you use another graphic library that uses row-major matrix.
Uniform block (buffer)
- stored in buffer with interface form (UBO) just like vertex buffer.
- UBO is manipulated with functions like glBufferData() or glMapBuffer().
- two way to store data in buffer
- standard : store data with just same order as members of uniform block.
extensive and safe but not efficient for memory space usage.
since standard layout is not default, you need to putlayout (std140)
before uniform block declaration. - shared : opengl make proper structure itself. shared layout is default layout if there’s none specification.
most efficient for performance but need resource to let OpenGL manage them and application can be more complicated.
shaders and programs share layout of buffer once buffer layout is decided into shared layout.
- standard : store data with just same order as members of uniform block.
- standard layout
std140
or any standard layouts have certain offset boundary and field packing rule.- array or vector of GLSL types have boundary offset of
N*sizeof(vector)
. (e.g. vector of 2 floats has 4*2 byte boundary offset.) - but array or vector with 3, 4 elements have boundary offset of
N*4
bytes. (I think it’s for keeping binaric integrity.) - every arrays aligned( =packed) just like
vec4
in size. i.e. every arrays without vec4 and N*4 matricies - element arrays won’t be packed tightly. - so you need to keep in mind to bind application array with proper offsets.
- structure and structure array’s boundary offsets defined by its largest member. (ceiled into size of vec4.)
- all of these rules look complex, but this is the way how standard layout guarantee cross-platform layout.
- you can check more about this from
ARB_uniform_buffer_obect
extention’s specification.
- array or vector of GLSL types have boundary offset of
- shared layout
- shared layout may be more efficient than standard layout. but many people think it’s not worth to invest that much effort on it.
- you need to search block members’ size and location wih indices of them.
- you can get indices’ by using
glGetUniformIndices()
.void glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar **uniformNames, GLuint *uniformIndices);
program
: program that you will get uniform index from.uniformCount
: number of uniform indices you want to get.uniformNames
: array of GLchar array( =string) that contains uniforms’ name you want to get index of.uniformIndices
: this funtion will write indices of uniform you selected in this array. - after getting array contain indices, you can get location of uniform block elements by
glGetActiveUniformsiv()
.void glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
program
: program that you will getuniformCount
: number of strides or offsets you want to getuniformIndices
: array of indices you want to use for getting stride or offset.pname
: enum for data type that this function will get.params
: result of this function will be stored at here.pname
enum list- GL_UNIFORM_TYPE : data type of uniform block members
- GL_UNIFORM_SIZE : array’s size of member regardless of which GL_UNIFORM_TYPE gives. 1 will be stored if indexed member is not array.
- GL_UNIFORM_NAME_LENGTH : length of uniform block member’s name (character array’s length)
- GL_UNIFORM_BLOCK_INDEX : index of uniform block that member is located. (it’s not index of uniform block member. it’s useless since parameter include them!)
- GL_UNIFORM_OFFSET : offset of uniform block member
- GL_UNIFORM_ARRAY_STRIDE : byte stride of uniform block member array. if indexed member is not array, 0 will be stored.
- GL_UNIFORM_MATRIX_STRIDE : byte stride between uniform block member matrix’ column or row. if indexed member is not matrix, 0 will be stored.
- GL_UNIFORM_IS_ROW_MAJOR : 1 will be stored if indexed matrix is row-major. 0 will be stored if index matrix is column-major or even not matrix at all.
- with offset and stride informations, application need to set data in proper location of buffer to send data for shared layout shader.
- you can use stride and offset as parameter of buffer modification functions like
glBufferSubData()
. - if you used
glMapBuffer
, application need to take care with inputting data inside buffer.
- you can use stride and offset as parameter of buffer modification functions like
- glGetUniformLocation()
GLint glGetUniformLocation (GLuint program, const GLchar * name);
Used for finding location of uniform inside program. if you put program that owning vertex shader in
program
and
name of uniform’s name(identifier) inname
,
it will returnname
’s location number.
if there no attribute with name,name
, it will return -1.
- glUniformMatrix*()
//matrix that store single-precision floating values
glUniformMatrix2fv (GLint location, GLuint count, GLboolean transpose, const GLfloat *m);
glUniformMatrix3fv (GLint location, GLuint count, GLboolean transpose, const GLfloat *m);
glUniformMatrix4fv (GLint location, GLuint count, GLboolean transpose, const GLfloat *m);
//matrix that store double-precition floating values
glUniformMatrix2dv (GLint location, GLuint count, GLboolean transpose, const GLdouble *m);
glUniformMatrix3dv (GLint location, GLuint count, GLboolean transpose, const GLdouble *m);
glUniformMatrix4dv (GLint location, GLuint count, GLboolean transpose, const GLdouble *m);
shader matrices only stores single and double precision floating-point variety.
this function can store array of matrices by settingcount
into larger than 1.
OpenGL’s matrix is column-major. if sending matrix is not column-major, settranspose
into GL_TRUE.
so, usetranspose
parameter in handy if you use another graphic library that uses row-major matrix.
–>