本次实践是绘制两个三角形,重点理解顶点数组对象和OpenGL缓存的使用。
顶点数组对象
顶点数组对象负责管理一组顶点属性,顶点属性包括位置、法线、纹理坐标等。
OpenGL缓存
OpenGL缓存实质上是OpenGL服务端的一块内存区域,用于存储数据。OpenGL的所有数据都是存储在缓存对象中的。
在本次实践的思路是创建一个顶点数组对象来管理所绘制的三角性的顶点数据,数据存储在缓存对象中,然后使用绘制API绘制三角形。
开始实践
主要的实现步骤:
- 使用genVertexArrays创建顶点数组对象;
- 使用glBindVertexArray绑定数组对象,绑定数组对象可以理解为接下来调用顶点数组相关的操作时操作的都是绑定的这个顶点数组;
- 使用glGenBuffers创建缓存;
- 使用glBufferData填充数据;
- 使用glVertexAttribPointer设置顶点数组的属性;
- 使用glDrawArrays或glDrawElements绘制三角形;
具体的示例代码如下:
#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
", name);
printf("渲染器标识符:%s
", biaoshifu);
printf("OOpenGL实现的版本号:%s
",OpenGLVersion );
printf("OGLU工具库版本:%s
", 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。
GLEW
GLEW(OpenGL Extension Wrangler) 是OpenGL的另一个辅助库,主要封装了从OpenGL库中获取函数地址的过程,还包含了一些可以跨平台使用的OpenGL编程方法。
最终的效果如下:
