GLEW说明
GLEW(OpenGL Extension Wrangler) 是OpenGL的另一个辅助库,主要封装了从OpenGL库中获取函数地址的过程,还包含了一些可以跨平台使用的OpenGL编程方法。
本次实践是使用数据缓存绘制两个三角形,重点是缓存的创建和数据输入。数据输入后,根据数据使用方式可分为非基于索引绘制和基于索引绘制,使用的方法分别为glDrawArray和glDrayElements。
首先,明确OpenGL缓存使用步骤:
- glGenBuffer
- glBindBuffer
- glBufferData
- glVertexAttribPointer
- glBindVertexArray
- glDrawArrays
简单来说就是:先创建缓存,然后输入缓存数据,然后绘制。以下是相关API的一个说明:
创建缓存
glGenBuffer(GLsizei n, GLuint* buffers);//创建n个缓存对象,保存在buffers数组中
向缓存中输入或输出数据
glBindBuffer(GLenum target, GLuint buffer); //绑定缓存到target指定的缓存结合点
glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); //为绑定到target的缓存对象分配size大小的存储空间,如果data不为NULL,则使用data初始化所为配的存储空间。usage指示缓存中的数据可能具备的一些特定的用途。
glBufferSubData(GLenum target, GLsizeiptr offset, GLsizeiptr size, const GLvoid* data);//使用新数据替换缓存中的部分数据
清除数据
glClearBufferData(GLenum target, GLenum internalformat, GLenum format, GLenum type, const GLvoid* data); //使用data填充缓存存储空间,format和type指定data的数据格式和类型,填充前需要把data转化为internalformat
glClearSubBufferData(GLenum target, GLenum internalformat, GLsizeiptr offset, GLsizeiptr size, GLenum format, GLenum type, const GLvoid* data); //同上,区别是这个方法只填充offset和size指定的区域;
设置顶点属性
glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer);
绘制
glDrawArrays(GLenum mode, GLint first, GLsizei count);//直接读取顶点数据绘制
glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);基于索引绘制(即所有的顶点在一个数组中,使用索引来引用顶点数据)
以下是根据上述API编写的绘制两个三角形的例子。
#include <GL/glew.h> #include <GL/freeglut.h> #include <stdio.h> #include "ShaderHelper.h" #define BUFFER_OFFSET(n) ((GLvoid*)n) enum VAO_IDs { Triangles,NumVAOs}; enum Buffers_IDs { ArrayBuffer, NumBuffers }; enum Attrib_IDs { vPosition=0 }; GLuint VAOs[NumVAOs]; GLuint Buffers[NumBuffers]; const GLuint NumVertices=6; void init(); void display(); int main(int argc,char* argv[]) { glutInit(&argc,argv); glutInitContextVersion(3,3); glutInitContextProfile(GLUT_CORE_PROFILE); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowPosition(0,0); glutInitWindowSize(300,300); glutCreateWindow("Frame Buffer"); /* const GLubyte* name = glGetString(GL_VENDOR); //返回负责当前OpenGL实现厂商的名字 const GLubyte* biaoshifu = glGetString(GL_RENDERER); //返回一个渲染器标识符,通常是个硬> 件平台 const GLubyte* OpenGLVersion =glGetString(GL_VERSION); //返回当前OpenGL实现的版本号 const GLubyte* gluVersion= gluGetString(GLU_VERSION); //返回当前GLU工具库版本 printf("OpenGL实现厂商的名字:%s\n", name); printf("渲染器标识符:%s\n", biaoshifu); printf("OOpenGL实现的版本号:%s\n",OpenGLVersion ); printf("OGLU工具库版本:%s\n", gluVersion);*/ glewExperimental=GL_TRUE; glewInit(); init(); glutDisplayFunc(display); glutMainLoop(); return 0; } void init() { glClearColor(0.0,0.0,0.0,1.0); glMatrixMode(GL_PROJECTION); glOrtho(-5,5,-5,5,5,15); glMatrixMode(GL_MODELVIEW); gluLookAt(0,0,10,0,0,0,0,1,0); glGenVertexArrays(NumVAOs,VAOs); glBindVertexArray(VAOs[Triangles]); GLfloat vertices[NumVertices][2]={ {-0.90,-0.90}, {0.85, -0.90}, { -0.90, 0.85 }, { 0.90, -0.85 }, { 0.90, 0.90 }, {-0.85, 0.90 }, }; glGenBuffers(NumBuffers,Buffers); glBindBuffer(GL_ARRAY_BUFFER,Buffers[ArrayBuffer]); glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW); ShaderInfo shaders[] = { {GL_VERTEX_SHADER,"triangles.vert"}, {GL_FRAGMENT_SHADER,"triangles.frag"}, {GL_NONE,NULL}, }; GLuint program = LoadShaders(shaders); glUseProgram(program); glVertexAttribPointer(vPosition,2,GL_FLOAT,GL_FALSE,0,BUFFER_OFFSET(0)); glEnableVertexAttribArray(vPosition); } void display() { glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(VAOs[Triangles]); glDrawArrays(GL_TRIANGLES,0,NumVertices); glFlush(); }
注意:代码根据红宝书编写,一些辅助性代码(如LoadShader)并未贴出,详情请参照www.opengl-readbook.com。
最终的效果如下: