《OpenGL编程指南》第九版——2.绘制两个三角形
我将跟随OpenGL编程指南对每个例子进行详解,每个例子将贴出实验结果和实验代码,仅供参考,代码部分可能我会进行一些修改与官方代码不同。
实现效果:
TwoTriangles.PNG
1.Main函数
1.glfwInit初始化GLFW库
2.glfwCreateWindow设置程序所使用的窗口类型以及期望的窗口尺寸。还创建了一个与窗口关联的OpenGL设备环境。在使用环境之前,我们需要设置它为当前环境。在一个程序中我们可以设置多个设备环境,但是用户指令只会传递到当前设备环境中。
3.gl3wInit调用GL3W库,简化获取函数地址的过程
4.接下来调用Init函数初始化所有OpenGl相关数据,以便之后的渲染工作
5.无限循环指令,一直处理窗口和操作系统的用户输入,在循环中判断是否需要关闭窗口(glfwWindowShouldClose),重绘内容,并展现给用户(glfwSwapBuffers),然后查看操作系统返回的任何信息(glfwPollEvents)
//----------------------------------------------------------------------------
//
// main
//
#ifdef _WIN32
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
#else
int
main( int argc, char** argv )
#endif
{
glfwInit();
GLFWwindow* window = glfwCreateWindow(800, 600, "Triangles", NULL, NULL);
glfwMakeContextCurrent(window);
gl3wInit();
init();
while (!glfwWindowShouldClose(window))
{
display();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
}
2.Init
1.glCreateVertexArrays分配顶点数组对象
2.得到对象后将其绑定(bind)到OpenGL环境以便使用,glBindVertexArray函数创建并且绑定一个顶点数组对象,如果array变量非零,并且是glCreateVertexArrays所返回的,那么会激活这个顶点数组对象。总的来说,在两种情况下需要绑定对象:创建对象并初始化它所需的数据;以及每次我们准备使用此对象的时候。
在较大的程序里,通过调用3.glDeleteVertexArrays释放顶点数组对象。
4.为了保证完整性,调用gllsVertexArray检查某个名称是否已经被保留位一个定点数组对象了。
顶点数组对象保存一系列顶点的数据,这些数据保存到缓存对象中,并且由当前绑定的顶点数组对象管理。
1.glCreateBuffers创建顶点缓存对象,在例子中创建NumVBOs个对象到数组buffers当中。
2.调用glBindBuffer规定他们到OpenGL环境。
3.所有缓存对象都可以使用glDeleteBuffers直接释放。
4.glNamedBufferStorge分配顶点数据所需的存储空间,将数据从应用程序拷贝到内存中。
glNamedBufferStorge函数详细定义:作用于名为buffer的缓存区域,由于我们的数据是顶点属性数据,因此设置这个缓存目标为GL_ARRAY_BUFFER。制定内存分配的大小size,data指定客户端内存的指针,以便初始化对象,如果是NULL,那么将保留size大小的未初始化数据。,最后指定数据在OpenGL中的使用方式。
//----------------------------------------------------------------------------
//
// init
//
void
init( void )
{
glGenVertexArrays( NumVAOs, VAOs );
glBindVertexArray( VAOs[Triangles] );
GLfloat vertices[NumVertices][2] = {
{ -0.90f, -0.90f }, { 0.85f, -0.90f }, { -0.90f, 0.85f }, // Triangle 1
{ 0.90f, -0.85f }, { 0.90f, 0.90f }, { -0.85f, 0.90f } // Triangle 2
};
glCreateBuffers( NumBuffers, Buffers );
glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer] );
glBufferStorage( GL_ARRAY_BUFFER, sizeof(vertices), vertices, 0);
ShaderInfo shaders[] =
{
{ GL_VERTEX_SHADER, "media/shaders/triangles/triangles.vert" },
{ GL_FRAGMENT_SHADER, "media/shaders/triangles/triangles.frag" },
{ GL_NONE, NULL }
};
GLuint program = LoadShaders( shaders );
glUseProgram( program );
glVertexAttribPointer( vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( vPosition );
}
3.初始化顶点与片元着色器
通过LoadShaders函数指定两个着色器,使用GLSL语言编写着色器程序。
#version 400 core表示我们使用OpenGL4.5版本对应的GLSL语言
vPosition是输入变量被声明为in指定了数据进入着色器的流向,最后字段layout(location = 0),布局限定符为变量提供元数据。
main函数实现输入顶点位置复制到顶点着色器的指定输出位置gl_Position中,
#version 400 core
layout( location = 0 ) in vec4 vPosition;
void
main()
{
gl_Position = vPosition;
}
片元着色器
声明变量fColor使用限定符out,这里着色器将fColor对应的数值输出,也就是片元对应的颜色值。
#version 450 core
out vec4 fColor;
void main()
{
fColor = vec4(0.5, 0.4, 0.8, 1.0);
}
init中最后两个函数指定了顶点着色器变量与缓存对象中数据的关系。
glEnableVertexAttribArray启用顶点属性数组,
3.Display
1.首先清除帧缓存的数据再进行渲染。
2.选择准备绘制的定点数据,然后请求进行绘制。调用glBindVertexArray选择作为顶点数据使用的顶点数组。
3.glDrawArrays实现顶点数据向OpenGL管线的传输。
//----------------------------------------------------------------------------
//
// display
//
void
display( void )
{
static const float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glClearBufferfv(GL_COLOR, 0, black);
glBindVertexArray( VAOs[Triangles] );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
}