Opengl的最新版本中取消掉了Immediate模式,矩阵管理也都交给了用户。我们不再能够寄希望于OpenGL来给我们管理一堆ModelView、 Projection等矩阵,我们需要自己来管理;我们也不能寄希望于OpenGL默认的管线来帮我们处理所以得事情,我们需要自己写Shader来控制顶点处理、片元处理甚至片元组装。在这种情况下我们怎样来编OpenGL程序呢,继续用以前的方法?当然了,这确实是可以的,因为OpenGL提供了兼容模式,但是从长久来看的话,我们还是很有必要适应新的OpenGL环境的。而且必须看到,OpenGL给我们新提供的模式不是为了要让我们的编程更加复杂,而是要让我们对程序包括GPU有更多的控制。  GLM是一个整体用法和GLSL很相似的数学运算库,开发者也声称“GLSL + Optional features = OpenGL Mathematics (GLM)”。它可以用来帮助我们操作矩阵和向量,因为在新的OpenGL中我们glLoadIdentity等矩阵函数已经被标记为Deprecated了,我们需要自己来保存我们运算的矩阵。另外,我们可以在程序中用GLSL编写的shader来控制OpenGL管线流程。  下面是用OpenGL实现的一个最简单的旋转三角形程序,里面用GLM管理矩阵,用GLSL管理OpenGL管线。  在程序的初始化函数中我们主要做三件事情,首先是定义一个Perspective矩阵: 

  1. projectionMatrix = glm::perspective(45.0f, 1.0f, 0.1f, 100.f);  
projectionMatrix = glm::perspective(45.0f, 1.0f, 0.1f, 100.f);
然后我们用一个GLSL管理类来加载我们的shader程序:
 
  1. shaderProgramme = new GLSLProgram("triangle.vert""triangle.frag");   
  2.  if ( !shaderProgramme->initialize() )   
  3.  {   
  4.   std::cout<<"shaderProgramme initialization failed!"<<std::endl;   
  5.   exit(1);   
  6.  }   
  7.  // bind the attribute location   
  8.  shaderProgramme->bindAttrib(0, "a_Vertex");   
  9.  shaderProgramme->bindAttrib(1, "a_Color");   
  10.  //re link the program   
  11.  shaderProgramme->linkProgram();   
  12.  shaderProgramme->bindShader();   
shaderProgramme = new GLSLProgram("triangle.vert", "triangle.frag"); if ( !shaderProgramme->initialize() ) {  std::cout<<"shaderProgramme initialization failed!"<
bindAttrib(0, "a_Vertex"); shaderProgramme->bindAttrib(1, "a_Color"); //re link the program shaderProgramme->linkProgram(); shaderProgramme->bindShader(); 
最后我们生成一个VBO来管理我们的数据:

 

 
  1. glGenBuffers(1, &vbo);   
  2. glBindBuffer(GL_ARRAY_BUFFER, vbo);   
  3. glBufferData(GL_ARRAY_BUFFER, sizeof(ver_color), ver_color, GL_STATIC_DRAW);  
glGenBuffers(1, &vbo);glBindBuffer(GL_ARRAY_BUFFER, vbo);glBufferData(GL_ARRAY_BUFFER, sizeof(ver_color), ver_color, GL_STATIC_DRAW);

然后再程序的display函数中我们只需要绑定VBO,然后告诉GLSL我们的shader中用到的属性都到哪去取值,我们就可以调用函数把三角形画出来了,具体代码如下:

 
  1. glClearColor(0, 0, 0, 1);   
  2. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   
  3. glBindBuffer(GL_ARRAY_BUFFER, vbo);   
  4. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), BUFFER_OFFSET(0));   
  5. glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), BUFFER_OFFSET(3*sizeof(GLfloat)));   
  6. glEnableVertexAttribArray(0);   
  7. glEnableVertexAttribArray(1);   
  8. glm::mat4 tmp = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, -3.5));   
  9. modelMatrix = glm::rotate(tmp, angle, glm::vec3(0, 1, 0));   
  10. // send the modelview and projection matrices to the shaders   
  11. shaderProgramme->sendUniform4x4("modelview_matrix", glm::value_ptr(modelMatrix));   
  12. shaderProgramme->sendUniform4x4("projection_matrix", glm::value_ptr(projectionMatrix));   
  13. //draw triangle   
  14. glDrawArrays( GL_TRIANGLES, 0, 3);   
  15. glutSwapBuffers();  
glClearColor(0, 0, 0, 1);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glBindBuffer(GL_ARRAY_BUFFER, vbo);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), BUFFER_OFFSET(0));glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), BUFFER_OFFSET(3*sizeof(GLfloat)));glEnableVertexAttribArray(0);glEnableVertexAttribArray(1);glm::mat4 tmp = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, -3.5));modelMatrix = glm::rotate(tmp, angle, glm::vec3(0, 1, 0));// send the modelview and projection matrices to the shadersshaderProgramme->sendUniform4x4("modelview_matrix", glm::value_ptr(modelMatrix));shaderProgramme->sendUniform4x4("projection_matrix", glm::value_ptr(projectionMatrix));//draw triangleglDrawArrays( GL_TRIANGLES, 0, 3);glutSwapBuffers();

程序代码下载: