0%

OpenGL(三)

从这篇开始,我们就跟着课本源码边调试边熟悉OpenGL函数的使用了。里面涉及的C++语法后面会在《C++重温》这里作补充。拿到课本源码,我们需要通过Cmake编译出Mac上运行的Xcode程序。

01-keypress.cpp

程序概括

程序先执行init函数void KeyPressExample::Initialize(const char * title)再执行display函数void KeyPressExample::Display(bool auto_redraw).

按下键盘会调用void KeyPressExample::OnKey(int key, int scancode, int action, int mods)

程序窗口缩放void KeyPressExample::Resize(int width, int height)

init函数说明

glGenVertexArrays( NumVAOs, VAOs );
分配NumVAOs个未使用的对象名到数组VAOs中,用作顶点数组对象。再看下其数组定义:GLuint VAOs[NumVAOs];

glBindVertexArray( VAOs[Triangles] );
VAOs[Triangles]

  • 输入的变量array非0,且为glGenVertexArrays所分配时,激活顶点数组对象,并直接影响对象中所保存的顶点数组状态。
  • array为0,OpenGL不再使用之前绑定的顶点数组。
  • array不是glGenVertexArrays所分配的,或者它已经被glDeleteVertexArray函数释放了,这时会产生一个无效错误。

glGenBuffers( NumBuffers, Buffers );
分配NumBuffers个当前未使用的缓存对象名称,并保存到Buffers数组中。

glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer] );

  • 如果绑定到一个已经创建的缓存对象,那么他将成为当前GL_ARRAY_BUFFER中被激活的缓存对象。
  • 如果绑定的Buffers[ArrayBuffer]值为0,那么OpenGL将不再对当前GL_ARRAY_BUFFER使用任何缓存对象。

glBufferData( GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW );
将数据载入缓存对象。

glVertexAttribPointer( vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
将输入顶点着色器的数据 关联到 一个顶点属性的数组。

glEnableVertexAttribArray( vPosition );
启用顶点属性数组。

display函数说明

glClear( GL_COLOR_BUFFER_BIT );
清屏。

glBindVertexArray( VAOs[Triangles] );

glDrawArrays( GL_TRIANGLES, 0, NumVertices );
开始绘制。

效果

程序默认效果
keypress1.png

按下键盘字母M的效果
keypress2.png

详细源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//////////////////////////////////////////////////////////////////////////////
//
// Triangles.cpp
//
//////////////////////////////////////////////////////////////////////////////

#include <vermilion.h>

#include "vgl.h"
#include "vapp.h"
#include "LoadShaders.h"

enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };

GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];

const GLuint NumVertices = 6;

BEGIN_APP_DECLARATION(KeyPressExample)
virtual void Initialize(const char * title);
virtual void Display(bool auto_redraw);
virtual void Finalize(void);
virtual void Resize(int width, int height);
void OnKey(int key, int scancode, int action, int mods);
END_APP_DECLARATION()

DEFINE_APP(KeyPressExample, "Key Press Example")
//----------------------------------------------------------------------------
//
// init
//

void KeyPressExample::Initialize(const char * title)
{
//typedef class VermilionApplication base
base::Initialize(title);

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
};

glGenBuffers( NumBuffers, Buffers );
glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer] );
glBufferData( GL_ARRAY_BUFFER, sizeof(vertices),
vertices, GL_STATIC_DRAW );

ShaderInfo shaders[] = {
{ GL_VERTEX_SHADER, "../media/shaders/keypress/keypress.vert" },
{ GL_FRAGMENT_SHADER, "../media/shaders/keypress/keypress.frag" },
{ GL_NONE, NULL }
};

GLuint program = LoadShaders( shaders );
glUseProgram( program );

glVertexAttribPointer( vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( vPosition );
}

void KeyPressExample::OnKey(int key, int scancode, int action, int mods)
{
if (action == GLFW_PRESS)
{
switch (key)
{
case GLFW_KEY_M:
{
static GLenum mode = GL_FILL;

mode = ( mode == GL_FILL ? GL_LINE : GL_FILL );
glPolygonMode( GL_FRONT_AND_BACK, mode );
}
return;
}
}

base::OnKey(key, scancode, action, mods);
}

//----------------------------------------------------------------------------
//
// display
//

void KeyPressExample::Display(bool auto_redraw)
{
glClear( GL_COLOR_BUFFER_BIT );

glBindVertexArray( VAOs[Triangles] );
// GL_TRIANGLES并没有指定是画三角形的边沿还是内部也画,
glDrawArrays( GL_TRIANGLES, 0, NumVertices );

base::Display(auto_redraw);
}

void KeyPressExample::Resize(int width, int height)
{
glViewport(0, 0, width, height);
}

void KeyPressExample::Finalize(void)
{

}