OpenGL4-使用顶点缓冲区绘制三角形

01、缓冲区与顶点属性:
  • 之前我们实现了,在屏幕中心上绘制了一个点,而且这个点是固定值不能修改的,现在我们想一次绘制多个点,应该怎么做呢?需要使用顶点缓冲区进行数据传递
  • OpenGL中想要绘制一个图形,需要将图形的顶点数据发送给顶点着色器。
  • 通常做法会将顶点数据在C++端放入一个缓冲区,并把这个缓冲区和着色器中声明的顶点属性相关联(gl_Position)
02、VAO,VBO
  • VBO(Vertex Buffer Object:顶点缓冲对象),在OpenGL中缓冲区被包含在VBO中,VBO在OpenGL应用程序中声明和实例化。
  • VAO(Vertex Array Object:顶点数组对象),之前我们有使用过,作为一种组织缓冲区的方法,OpenGL程序中至少需要创建一个VAO

缓冲区与顶点属性交互方式:

  • 当调用glDrawArrays()方法时,缓冲区中的数据开始流动,从缓冲区的开头开始按顺序流过顶点着色器,顶点着色器对每个顶点执行一次。

03、GLSL中设置顶点属性
   "#version 410          \n"





   "layout(location=0) in vec3 position;  \n"





   "void main(void){      \n"





   "  gl_Position = vec4(position, 1.0); \n"





   "} \n";   
   
  • 解析:
    • #version 410:表示当前电脑支持的OpenGL版本
    • layout(location=0) in vec3 position;
    • layout (location=0)称为“layout修饰符”,也就是我们把顶点属性和特定缓冲区关联起来的方法。这意味着,这个顶点属性的识别号是0,我们后面会用到
    • 关键字in意思是输入(input),表示这个顶点属性将会从缓冲区中接收数值,vec3的意思是着色器每次调用会抓取3个浮点类型数值(用于表示顶点数据的X,Y,Z轴的坐标),变量名字为position
04、顶点数据放到缓冲区中并于顶点属性关联
  • a、准备三个顶点坐标数据
   float vPositions[9] = {





         0.0, 0.5, 0.0,





       -0.5,-0.5, 0.0,





         0.5,-0.5, 0.0,





   };
  • b、创建VAO,和VBO
  • glGenVertexArrays和glGenBuffers方法会创建VAO和VBO,创建成功会将缓冲区的整数型id值保存到数组vao和vbo中
  • glBindVertexArray和glBindBuffer方法会将创建的缓冲区标记为活跃
  • glBufferData方法会将顶点数据的数组复制到活跃缓冲区中,
GLuint vao[1];





GLuint vbo[2];





   // 创建vao,并绑定





   glGenVertexArrays(1, vao);





   glBindVertexArray(vao[0]);



   // 创建顶点缓冲对象vbo


   glGenBuffers(2,vbo);

   glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);

   // 将数据填充到缓冲区对象中

   glBufferData(GL_ARRAY_BUFFER,sizeof(vPositions),vPositions,GL_STATIC_DRAW);
  • c、将活跃的缓冲区数据关联到顶点属性
    • glVertexAttribPointer方法的第一个参数为0,表示将缓冲区中的数据关联到顶点属性(location=0)的position中
    • glEnableVertexAttribArray方法是启动顶点属性
// 标记第0个缓冲区为“活跃”





glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);       





// 将第0个属性关联到缓冲区             





glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);





// 启用第0个顶点属性     



glEnableVertexAttribArray(0);                             
  • d、最后我们执行glDrawArrays 方法时,第0个VBO中的数据将会传递给拥有位置为0(location=0)layout修饰符的顶点属性中。
05、齐次坐标
  • 在GLSL代码中发现最后传递给gl_Position的数据是一个vec4的变量(gl_Position = vec4(position, 1.0);)
  • 明明一个坐标数据只有xyz三个轴,为什么还需要使用第四个分量呢?
    • 由四个分量组成的矢量被称为齐次坐标,它能够提高处理三维数据的效率
    • 虽然齐次坐标是思维的,但是如果最后一个分量是1.0,那齐次坐标可以表示前三个分量为坐标值的那个点,比如齐次坐标(x,y,z,w)等价于(x/w, y/w, z/w)
06、实战-画三个点
#include <GL/glew.h>





#include <GLFW/glfw3.h>





#include <iostream>





using namespace std;





GLuint renderProgram;



GLuint vao[1];


GLuint vbo[2];
  

// 创建着色器程序

GLuint createShaderProgram(){

   const char *vertex_shader =

   "#version 410          \n"

   "layout(location=0) in vec3 position;  \n"

   "void main(void){      \n"

   "  gl_Position = vec4(position, 1.0); \n"

   "} \n";

   

   const char *fragment_shader =

   "#version 410      \n"

   "out vec4 color;    \n"

   "void main(void){  \n"

   "  color = vec4(1.0, 0.0, 0.0, 1.0); \n"

   "} \n";

   // 创建着色器对象

    GLuint vShader = glCreateShader(GL_VERTEX_SHADER);

    GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER);

   // 创建着色器程序

    GLuint vfProgram = glCreateProgram();

   // 加载着色器代码

   glShaderSource(vShader, 1, &vertex_shader, NULL);

   glShaderSource(fShader, 1, &fragment_shader, NULL);

   // 编译着色器对象

   glCompileShader(vShader);

   glCompileShader(fShader);

   // 着色器程序绑定着色器对象(两个)

   glAttachShader(vfProgram, vShader);

   glAttachShader(vfProgram, fShader);

   // 链接着色器程序

   glLinkProgram(vfProgram);

   return vfProgram;

}

  


void init(GLFWwindow* window) {

    renderProgram = createShaderProgram();

   

   float vPositions[9] = {

         0.0, 0.5, 0.0,

       -0.5,-0.5, 0.0,

         0.5,-0.5, 0.0,

   };

   

   // 创建vao,并绑定

   glGenVertexArrays(1, vao);

   glBindVertexArray(vao[0]);

   // 创建顶点缓冲对象vbo

   glGenBuffers(2,vbo);

   glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);

   // 将数据填充到缓冲区对象中

   glBufferData(GL_ARRAY_BUFFER,sizeof(vPositions),vPositions,GL_STATIC_DRAW);

}

  


void display(GLFWwindow* window, double currentTime) {

   glClearColor(0.0, 0.0, 0.0, 1.0);

   glClear(GL_COLOR_BUFFER_BIT);

   glUseProgram(renderProgram);

   

   // 将vbo中关联的顶点数据取出来使用

   glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);

   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,0,0);

   glEnableVertexAttribArray(0);

   

   glPointSize(30.0);

   glDrawArrays(GL_POINTS, 0, 3);

}

  


int main(void) {

   if (!glfwInit()) {

       exit(EXIT_FAILURE);

   }

   

   glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);

   glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

   glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

   glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

   

    GLFWwindow* window = glfwCreateWindow(600, 600, "OpenGL Demo", NULL, NULL);

   glfwMakeContextCurrent(window);

   

   if (glewInit() != GLEW_OK) {

       exit(EXIT_FAILURE);

   }

   glfwSwapInterval(1);

   

   init(window);

   

   while (!glfwWindowShouldClose(window)) {

       display(window, glfwGetTime());

       glfwSwapBuffers(window);

       glfwPollEvents();

   }

   

   glfwDestroyWindow(window);

   glfwTerminate();

   exit(EXIT_SUCCESS);

}
  • 效果图

0602-实战2:画个三角形
  • 还是使用上面的三个顶点数码,将三个点连接起来形成一个三角形即可,使用很简单,调用glDrawArrays 方法时,第一个参数设置为GL_TRIANGLES
glDrawArrays(GL_TRIANGLES, 0, 3);

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYyqoweg' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片