从这篇开始,我们就跟着课本源码边调试边熟悉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 );
开始绘制。
效果
程序默认效果
按下键盘字母M的效果
详细源码
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 // //////////////////////////////////////////////////////////////////////////////
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) {
}
|