OpenGL 4.0 GLSL 基础教程概览——VAO和VBO常用操作接口
(一) OpenGL 4.3 最新渲染管线图
从OpenGL 2.0 到 OpenGL 3.0变化非常大,但从OpenGL 3.0 到OpenGL 4.0 变化不是太大。
着色器程序直接运行在GPU上,并且是并行的,一个片元着色器可能一次执行所有象素。
deprecation model, 在OpenGL3.0 提出,为了保持向后兼容,兼容模式compatibility profile.和核心模式core profile的概念在OpenGL 3.2 中提出。
在Qt 4.7以后版本,可以通过下列方式选择核心模式:
QGLFormat format; format.setVersion(4,0); format.setProfile(QGLFormat::CoreProfile); QGLWidget *myWidget = new QGLWidget(format);
传送数据到GPU
1. 产生顶点数组对象(vertex-array object, VAO)的标识符glGenVertexArrays
2. 绑定(创建)顶点数组对象glBindVertexArray
3. 产生缓冲区对象的标识符glGenBuffers
4. 绑定(创建)缓冲区对象glBindBuffer
5. 为缓冲区对象分配存储空间,传送数据glBufferData
6. 更新缓冲区对象的数据glBufferSubData
(二) 顶点数组对象(VAO)
1. 顶点有多种属性值:位置, 颜色, 纹理坐标, 应用程序数据等. 顶点数组包含了这些数据.
2. OpenGL中用顶点数组对象打包了所有的顶点数据(位置、颜色等)
3. 生成顶点数组对象的标识符(或名字)然后绑定
产生顶点数组对象名
1. Void glGenVertexArrays(GLsizein,GLuint*arrays);
2. 返回n个当前未被使用的顶点数组对象名到数组arrays
3. 名字类似于C中的指针,只有指向已分配的内存才有意义
4. OpenGL中的分配方式称为对象绑定
绑定顶点数组对象
1. 当array首次使用从glGenVertexArrays()返回的非零值时,创建一个新的顶点数组对象并赋以该名字
2. 当绑定到已创建的顶点数组对象时,该对象变成当前活动对象
3. 当绑定到零值时,OpenGL停止使用应用程序分配的顶点数组对象并返回到顶点数组的默认状态
删除顶点数组对象
1. Void glDeleteVertexArrays(GLsizein,constGLuint*arrays);
2. 删除arrays中指定的n个顶点数组对象,使得这些名字可被重用
3. 如果一个当前绑定的顶点数组对象被删除,该顶点数组的绑定变为0,并且默认顶点数组成为当前活动对象
查询顶点数组对象名
1. GLboolean glIsVertexArray(GLuintarray);
2. 查询array是否对应到一个顶点数组对象
3. 返回GL_TRUE,如果array是一个之前glGenVertexArrays()产生的顶点数组对象名,且后来未被删除
4. 返回GL_FALSE,如果array是0,或者一个非顶点数组对象名的非零值
(三) 顶点缓冲区对象(VBO)
1. 顶点的各种数据存储在缓冲区对象中,并由当前绑定的顶点数组对象所管理
2. 缓冲区对象是由GPU分配并管理的内存创建、绑定、传送(或更新)数据
产生缓冲区对象名
1. void glGenBuffers(GLsizein,GLuint*buffers);
2. 返回n个当前未被使用的缓冲区对象名到数组buffers
3. 返回的名字不必是连续的
4. 缓冲区对象名是无符号整数,0是保留值
绑定缓冲区对象
1. Void glBindBuffer(GLenumtarget,GLuintbuffer);
2. 缓冲区对象的类型target有如下9种:
GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER, GL_TEXTURE_BUFFER, GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, GL_UNIFORM_BUFFER, GL_TRANSFORM_FEEDBACK_BUFFER
3. 当buffer是首次使用的从glGenBuffers()返回的非零值时,创建一个新的缓冲区对象并赋以该名字
4. 当绑定到以前创建的缓冲区对象时,该对象变成当前活动对象
5. 当绑定到零值时,OpenGL停止使用target类型的缓冲区对象
删除缓冲区对象
1. Void glDeleteBuffers(GLsizein,constGLuint*buffers);
2. 删除buffers中指定的n个缓冲区对象,使得这些名字可被重用
3. 如果一个当前绑定的缓冲区对象被删除,该对象的绑定重置为默认缓冲区对象
查询缓冲区对象名
1. GLbooleanglIsBuffer(GLuintbuffer);
2. 查询buffer是否对应到一个缓冲区对象
3. 返回GL_TRUE,如果buffer是一个已被绑定的缓冲区对象名,且后来未被删除
4. 返回GL_FALSE,如果buffer是0,或者一个不是缓冲区对象名的非零值
加载数据到缓冲区对象
1. void glBufferData(GLenumtarget, GLsizeiptr size,const GLvoid* data, GLenum usage);
2. 为target类型的当前绑定缓冲区对象分配size字节的服务器内存,并用data指向的数据来初始化。以前与当前绑定对象关联的数据都将删除。
3. size 是存储相关数据所需的内存数量,通常是数据元素的个数乘以各自的字节大小
4. data 可以是指向客户机内存的指针或NULL。如果是有效指针,size字节的数据从客户机复制到服务器;如果是NULL,只分配size字节的服务器内存
5. usage 指定数据存储区的使用方式,取值:
GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY, GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY,GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, or GL_DYNAMIC_COPY.
更新缓冲区对象数据
1. void glBufferSubData(GLenumtarget, GLintprt offset,GLsizeiptr size, const GLvoid* data);
2. 用data指向的数据更新target类型的当前绑定缓冲区对象中从offset字节开始的size字节的数据。
3. 如果size或offset小于零,或者它们的和大于缓冲区对象创建时所指定的大小时,报错GL_INVALID_VALUE。
(五) 顶点属性变量
1. 顶点属性是顶点着色器中的attribute变量
2. 链接器生成一张属性变量的索引表
3. 应用程序从表中查询属性变量的索引值,并关联到应用程序中的变量
获取属性变量的索引
1. GLint glGetAttribLocation(GLuint program,const GLchar*name);
2. 返回与链接过的着色器程序program中属性变量name相关联的索引
3. 如果name不是program的一个活动属性变量,或是内置属性变量(以gl_开头) ,返回-1
4. 如果name是矩阵属性变量,返回矩阵第一列的索引。后一列的索引为前一列的索引加1
指定顶点属性数组值
1. void glVertexAttribPointer(GLuintindex,GLintsize,GLenum type, GLboolean normalized,GLsizei stride,constGLvoid*pointer);
2. 为索引值为index的顶点属性变量的数组指定位置pointer和数据格式
3. size每个顶点属性的分量个数,为1,2,3,4或GL_RGBA,初始值为4
4. type数组元素的数据类型,初始为GLfloat
5. normalized指定浮点数据值是否要规范化
6. stride数组中相邻元素的偏移字节,0表示数据连续存储
7. pointer指定顶点属性数组的第一个分量在当前绑定的GL_ARRAY_BUFFER缓冲区对象中的偏移量
启用/禁用顶点属性数组
1. voidglEnableVertexAttribArray(GLuintindex)
2. voidglDisableVertexAttribArray(GLuintindex)
3. 启用/禁用属性index的顶点属性数组
4. 启用后,就可用glDrawArrays()等来为顶点属性变量加载值
(六) ArrayDraw的方式:
void glDrawArrays(GLenum type, GLint start, GLint count) { for(GLint element = start; element < start + count; element++) { VertexShader(positionAttribArray[element], colorAttribArray[element]); } }
Indexed Draw 的方式
void glDrawElements(GLenum type, GLint count, GLenum type, GLsizeiptr indices) { GLtype *ourElementArray = (type*)((GLbyte *)elementArray + indices); for(GLint elementIndex = 0; elementIndex < count; elementIndex++) { GLint element = ourElementArray[elementIndex]; VertexShader(positionAttribArray[element], colorAttribArray[element]); } }
查询GLSL 和OpenGL所支持的版本
const GLubyte *renderer =glGetString( GL_RENDERER ); const GLubyte *vendor =glGetString( GL_VENDOR ); const GLubyte *version =glGetString( GL_VERSION ); const GLubyte *glslVersion = glGetString( GL_SHADING_LANGUAGE_VERSION); GLint major, minor; glGetIntegerv(GL_MAJOR_VERSION,&major); glGetIntegerv(GL_MINOR_VERSION,&minor); printf("GL Vendor :%s\n", vendor); printf("GL Renderer :%s\n", renderer); printf("GL Version(string) : %s\n", version); printf("GL Version(integer) : %d.%d\n", major, minor); printf("GLSLVersion : %s\n", glslVersion);
用glGetString and glGetIntegerv两种方式查询系统支持OpenGL的版本,不过glGetIntegerv更利于编程使用
获得当前活动顶点属性和其索引
//获得当前活动顶点属性和其索引 GLint maxLength, nAttribs; glGetProgramiv(shader.GetHandler(), GL_ACTIVE_ATTRIBUTES,&nAttribs); glGetProgramiv(shader.GetHandler(), GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,&maxLength); GLchar * name = (GLchar *) malloc( maxLength ); GLint written, size, location; GLenum type; printf(" Index | Name\n"); printf("------------------------------------------------\n"); for( int i = 0; i < nAttribs; i++ ) { glGetActiveAttrib( shader.GetHandler(), i, maxLength, &written, &size, &type, name ); location = glGetAttribLocation(shader.GetHandler(), name); printf(" %-5d | %s\n",location, name); } free(name); printf("------------------------------------------------\n");
查询uniform变量
//查询uniform变量 GLint nUniforms, maxLen; glGetProgramiv( shader.GetHandler(), GL_ACTIVE_UNIFORM_MAX_LENGTH,&maxLen); glGetProgramiv( shader.GetHandler(), GL_ACTIVE_UNIFORMS,&nUniforms); GLchar * name = (GLchar *) malloc( maxLen ); GLint size, location; GLsizei written; GLenum type; printf(" Location | Name\n"); printf("------------------------------------------------\n"); for( int i = 0; i < nUniforms; ++i ) { glGetActiveUniform( shader.GetHandler(), i, maxLen, &written, &size, &type, name ); location = glGetUniformLocation(shader.GetHandler(), name); printf(" %-8d | %s\n", location, name); } printf("------------------------------------------------\n"); free(name);
OpenGL 4.0 GLSL 框架 下载地址