OpenGL -- 你好三角形

Posted working-in-heart

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL -- 你好三角形相关的知识,希望对你有一定的参考价值。

一、概念

VAO:Vertex Array Object

VBO:Vertex Buffer Object

EBO/IBO:Element Buffer Object,Index Buffer Object

二、解释为何如此编程

A vertex buffer object (VBO) is nothing fancy - it‘s just an array of data (usually floats).

A VBO is not an "object" in the object-oriented programming sense, it is a simple array of data. OpenGL has several other types of data that it refers to as singular "buffer objects". 

(一)为什么要用VBO?:The key idea of VBOs is this: in the old, "immediate-mode" days of OpenGL, before VBOs, we would define the vertex data in main memory (RAM), and copy them one-by-one each time that we draw. With VBOs, we copy the whole lot into a buffer before drawing starts, and this sits on the graphics hardware memory instead. This is much more efficient for drawing because, although the bus between the CPU and the GPU is very wide, a bottleneck for drawing performance is created when drawing operations stall to send OpenGL commands from the CPU to the GPU. To avoid this we try to keep as much data and processing on the graphics hardware as we can.

解释一下,其实就是IO瓶颈,其实读取一个字节和1千个字节花费时间是差不多的,这也是为什么提出B-树,红黑树的原因,时间的花费主要在不同速度存储介质上寻找(可能这段不对,请具体查询)

而3.3之前的OpenGL是立即渲染模式"immediate-mode",这大大浪费IO,这也是为什么大多数教程从3.3开始教OpenGL,使用VBO可以使得大量点的数据一次读入,节约IO,但这提升肯定不够,于是就有了VAO,可以理解为是VBO的数组?

但还是不够,为什么?因为大多数物体表面肯定不是我们所看到那样,极有可能是各种三角形、线段组成的,这会使得如果使用VAO,那么会有大量的点重复(因为物体是封闭的,两个三角形之间有一条边是重合的等其他情况)造成内存浪费,于是就提出IBO,索引,一个点就存一次,如果要使用,我们就是用像访问数组的方式,通过下标直接访问,这样大大节约空间。

以上仅仅是我的理解,不一定对,请多多参考他人。

代码:

  1 #include <glad/glad.h>
  2 #include <GLFW/glfw3.h>
  3 
  4 #include <iostream>
  5 
  6 void framebuffer_size_callback(GLFWwindow* window, int width, int height);
  7 void processInput(GLFWwindow* window);
  8 const char* vertexShaderSource = "#version 330 core
"
  9 "layout (location = 0) in vec3 aPos;
"
 10 "void main()
"
 11 "{
"
 12 "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
"
 13 "}";
 14 const char* fragmentShaderSource = "#version 330 core
"
 15 "out vec4 FragColor;
"
 16 "void main()
"
 17 "{
"
 18 "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
"
 19 "}
";
 20 int main()
 21 {
 22     glfwInit();
 23     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
 24     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
 25     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
 26 
 27     GLFWwindow* window = glfwCreateWindow(2000, 2000, "LearnOpenGL", NULL, NULL);
 28     if (window == NULL)
 29     {
 30         std::cout << "Failed to create GLFW window" << std::endl;
 31         glfwTerminate();
 32         return -1;
 33     }
 34     glfwMakeContextCurrent(window);
 35     glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
 36 
 37     if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
 38     {
 39         std::cout << "Failed to initialize GLAD" << std::endl;
 40         return -1;
 41     }
 42 
 43     
 44 
 45     unsigned int vertexShader;
 46     vertexShader = glCreateShader(GL_VERTEX_SHADER);
 47     glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
 48     glCompileShader(vertexShader);
 49     int  success;
 50     char infoLog[512];
 51     glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
 52     if (!success)
 53     {
 54         glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
 55         std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED
" << infoLog << std::endl;
 56     }
 57 
 58 
 59     unsigned int fragmentShader;
 60     fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
 61     glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
 62     glCompileShader(fragmentShader);
 63 
 64 
 65     unsigned int shaderProgram;
 66     shaderProgram = glCreateProgram();
 67     glAttachShader(shaderProgram, vertexShader);
 68     glAttachShader(shaderProgram, fragmentShader);
 69     glLinkProgram(shaderProgram);
 70 
 71     glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
 72     if (!success) {
 73         glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
 74         std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED
" << infoLog << std::endl;
 75     }
 76 
 77     glUseProgram(shaderProgram);
 78     glDeleteShader(vertexShader);
 79     glDeleteShader(fragmentShader);
 80 
 81     float vertices[] = {
 82      -0.5f, -0.5f, 0.0f, 
 83      0.0f, -0.5f, 0.0f,  
 84      -0.25f, 0.5f, 0.0f,
 85      0.0f, -0.5f, 0.0f,
 86      0.5f, -0.5f, 0.0f,
 87      0.25f, 0.5f, 0.0f
 88     };
 89 
 90     unsigned int indices[] = { // 注意索引从0开始! 
 91         0, 1, 2, // 第一个三角形
 92         3, 4, 5  // 第二个三角形
 93     };
 94     unsigned int VBO, VAO, EBO;
 95     glGenBuffers(1, &EBO);
 96     glGenVertexArrays(1, &VAO);
 97     glGenBuffers(1, &VBO);//生成
 98 
 99     glBindVertexArray(VAO);
100 
101     glBindBuffer(GL_ARRAY_BUFFER, VBO);
102     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
103 
104     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);//把新创建的缓冲绑定到目标上
105     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
106     //一个专门用来把用户定义的数据复制到当前绑定缓冲的函数
107 
108 
109     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//告诉OpenGL该如何解析顶点数据
110     //每个顶点属性从一个VBO管理的内存中获得它的数据,而具体是从哪个VBO(程序中可以有多个VBO)获取
111     //则是通过在调用glVertexAttribPointer时绑定到GL_ARRAY_BUFFER的VBO决定的。
112     glEnableVertexAttribArray(0);//vertex attribute location as its argument.
113     //vertex attributes are disabled by default.
114 
115     glBindBuffer(GL_ARRAY_BUFFER, 0);//参数0,好像是解绑的意思
116     glBindVertexArray(0);
117     //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
118     while (!glfwWindowShouldClose(window))
119     {
120         processInput(window);
121 
122         glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
123         glClear(GL_COLOR_BUFFER_BIT);
124 
125         glUseProgram(shaderProgram);
126         glBindVertexArray(VAO);
127         glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
128         glBindVertexArray(0);
129 
130         glfwSwapBuffers(window);
131         glfwPollEvents();
132     }
133 
134     glDeleteVertexArrays(1, &VAO);
135     glDeleteBuffers(1, &VBO);
136     glDeleteBuffers(1, &EBO);
137 
138     glfwTerminate();
139  
140     return 0;
141 }
142 
143 
144 void framebuffer_size_callback(GLFWwindow* window, int width, int height)
145 {
146     glViewport(0, 0, width, height);
147 }
148 
149 void processInput(GLFWwindow* window)
150 {
151     if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
152         glfwSetWindowShouldClose(window, true);
153 }

 

以上是关于OpenGL -- 你好三角形的主要内容,如果未能解决你的问题,请参考以下文章

我的OpenGL学习进阶之旅你好,三角形:一个OpenGL ES 3.0示例。 分别使用C++ Native & Java 两种方式来实现

openGL 纹理05

未触发opengl片段着色器条件语句

片段着色器不会在 OpenGL GLSL 中创建像光一样的渐变

LearnOpenGL - Android OpenGL ES 3.0 绘制三角形

绘制三角形的OpenGL程序给出了一个黄色的屏幕