当前位置:网站首页>Part 4: drawing quadrilateral
Part 4: drawing quadrilateral
2022-06-26 03:55:00 【Code Knight】
Catalog
4、 Vertex shaders and clip shaders
0、 Create project
(0) choice x64 platform

(1) Add links
Open project properties

Open the project directory and add the file path :
Include directory add :D:\OpenGL_Link\Includes;
Library Directory add :D:\OpenGL_Link\Libs;

Open linker / Input add :
glfw3.lib;opengl32.lib;
Add... Under the project source folder glad.c file


newly build main.cpp file , Test code , No problem .
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
int main() {
// initialization GLFW
glfwInit();// initialization GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);// Set the major version number
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);// Set the minor version number
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// Set the core mode
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);//MAC OS
glfwWindowHint(GLFW_RESIZABLE, false);// Close resizable window
std::cout << "hello world!" << std::endl;
return 0;
}Output results

1、 initialization
Include : initialization GLFW、 create a window 、 initialization GLAD、 Create viewport
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
// Set the screen width 、 high
const int screen_width = 800;
const int screen_height = 600;
int main() {
// initialization GLFW
glfwInit();// initialization GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);// Set the major version number
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);// Set the minor version number
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// Set the core mode
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);//MAC OS
glfwWindowHint(GLFW_RESIZABLE, false);// Close resizable window
// create a window
auto window = glfwCreateWindow(screen_width, screen_height, "Quad", nullptr, nullptr);
if (window == nullptr) {
std::cout << "Failed to Create OpenGL Context" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);// Set the context of the window to the context of the current thread ( Context : Refers to the state of the current state machine )
// initialization GLAD, load OpenGL Function pointer address of the function
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// Create viewport
glViewport(0, 0, screen_width, screen_height);
return 0;
}2、 Vertex input
// Quadrilateral vertex data
float vertices[] = {
// The first triangle
0.5f,0.5f,0.0f,//right up
0.5f,-0.5f,0.0f,//right down
-0.5f,-0.5f,0.0f,//left down
// The second triangle
-0.5f,-0.5f,0.0f,//left down
0.5f,0.5f,0.0f,//right up
-0.5f,0.5f,0.0f,//left up
};
3、 Data processing
(1)VBO
We have vertex data , The next step is to send the vertex data to GPU To deal with , Here we will generate a vertex buffer object VBO, And bind the vertex data to VBO On , Through this vertex buffer object, we can send a large number of vertex data to the graphics card at one time , And then use glfwBufferData Bind vertex data to the current default buffer , there GL_STATIC_DRAW It means that our quadrilateral position data will not change .
// Generate and bind VBO
GLuint vertex_buffer_object;
glGenBuffers(1, &vertex_buffer_object);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);
// Bind vertex data to the current default buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);(2)VAO
Here we also need to generate a vertex array object VAO, Use VAO as a result of : First, the core pattern we use requires us to be practical VAO, Next is the use of VAO The advantage of this method is that we only need to call it once when rendering VAO That's all right. , The previous data are stored in VAO in , No need to call VBO 了 . in other words VAO The generation process of is also the same as VBO equally , It needs to be bound again , Wait until these operations are completed , We can untie our VAO、VBO 了 .
// Generate and bind VAO
GLuint vertex_array_object;
glGenVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);(3) Vertex Attribute
Send to GPU And then we have to tell OpenGL How do we interpret these vertex data . So we use glVertexAttribPointer This function tells OpenGL How do we interpret these vertex data .
// Set vertex property pointer
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);glVertexAttribPointer Function description :
The first parameter :0 Is the position value of the vertex shader we will use later ,
The second parameter :3 Indicates that the vertex attribute is a three component vector ,
The third parameter :GL_FLOAT It represents the type of our vertex ,
Fourth parameter :GL_FALSE Indicates whether we want the data to be standardized ,
Fifth parameter :3*sizeof(float) It's called step size , It represents the interval between successive vertex attributes , Because we only have the vertex position here , So we set the step size to this , Indicates that the next group of data is in 3 individual float after .
Last parameter :(void*)0 Is the offset of the data , Here our position attribute is at the beginning of the array , So here is 0, And because of the limitation of parameter types , We need to cast it .
And below Enable The function of is to show that we have turned on 0 This passage of the road , It's off by default , So we're going to open it here .
(4) Unbundling VAO and VBO
// Unbundling VAO and VBO
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);Why untie it here ?
reason 1: Prevent binding before continuing VAO Time affects the present VAO.
reason 2: In order to make the code more flexible and standardized , We will bind again when rendering is needed VAO.
4、 Vertex shaders and clip shaders
(1) Generate shader
We have passed VAO and VBO Store vertex data in the... Of the graphics card GPU Yes , Next we will create vertex and fragment shaders to actually process this data . Here we will give the source code of the shader , Then generate and compile shaders , Finally, link the vertices and clips to a shader program , We will use this shader program in the later rendering process , Finally, delete the previous shader .
Next, we give the source code of vertex shader and fragment shader , It's all used GLSL language-written .
// Vertex shader source code
const char* vertex_shader_source =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n" // The property location value of the location variable is 0
"void main()\n"
"{\n"
" gl_Position = vec4(aPos, 1.0);\n"
"}\n\0";GLSL The code analysis :
first line : It means that we use OpenGL3.3 The core model of .
The second line : It is the position value we mentioned before .
The third line : It was created main function
main The code statement in the function means : Output the vertex data we defined before directly to GLSL A built-in variable that has been defined gl_Position in , This is the output of our vertex shader . That is to say, we only output vertex positions as vertex shaders in vertex shaders , Nothing else .
// Fragment shader source code
const char* fragment_shader_source =
"#version 330 core\n"
"out vec4 FragColor;\n" // Output color vector
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";(2) Compiling shaders
Compile the previously written source code .
// Compile vertex shader
int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
glCompileShader(vertex_shader);
int success;
char info_log[512];
// Check whether the shader was successfully compiled , If compilation fails , Print error messages
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << info_log << std::endl;
}
// Compiling fragment shaders
int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
glCompileShader(fragment_shader);
// Check whether the shader was successfully compiled , If compilation fails , Print error messages
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << info_log << std::endl;
}(3) Link shaders
Add vertices and clips 2 Shaders are linked to a shader program , In this way, we only need to call a shader program when rendering .
// Link vertex and clip shaders to a shader program
int shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glLinkProgram(shader_program);
// Check whether the shader is successfully linked , If the link fails , Print error messages
glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shader_program, 512, NULL, info_log);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << info_log << std::endl;
}(4) Delete shader
Because when rendering later, we only need to use the shader program we linked before , No more vertex and clip shaders .
// Delete shader
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);(5) Wireframe mode
// Wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);5、 Rendering
// Render loop
while (!glfwWindowShouldClose(window)) {
// Empty the color buffer
glClearColor(0.0f, 0.34f, 0.57f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Using shader programs
glUseProgram(shader_program);
// Draw a quadrilateral
glBindVertexArray(vertex_array_object); // binding VAO
// Draw a quadrilateral
glDrawArrays(GL_TRIANGLES, 0, 6);
// use EBO Draw a quadrilateral
//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0); // Unbind
// Swap buffers and check for triggering events ( For example, keyboard input 、 Mouse movement, etc )
glfwSwapBuffers(window);
glfwPollEvents();
}6、 dealing with the aftermath
Delete previously created VAO、VBO, And call GLFW Clean up all resources and exit .
// Delete VAO/VBO
glDeleteVertexArrays(1, &vertex_array_object);
glDeleteBuffers(1, &vertex_buffer_object);
// Clean up all resources and exit the program correctly
glfwTerminate();7、 Complete code
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
// Set the screen width 、 high
const int screen_width = 800;
const int screen_height = 600;
// Quadrilateral vertex data
float vertices[] = {
// The first triangle
0.5f,0.5f,0.0f,//right up
0.5f,-0.5f,0.0f,//right down
-0.5f,-0.5f,0.0f,//left down
// The second triangle
-0.5f,-0.5f,0.0f,//left down
0.5f,0.5f,0.0f,//right up
-0.5f,0.5f,0.0f,//left up
};
int main() {
// initialization GLFW
glfwInit();// initialization GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);// Set the major version number
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);// Set the minor version number
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// Set the core mode
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);//MAC OS
glfwWindowHint(GLFW_RESIZABLE, false);// Close resizable window
// create a window
auto window = glfwCreateWindow(screen_width, screen_height, "Quad", nullptr, nullptr);
if (window == nullptr) {
std::cout << "Failed to Create OpenGL Context" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);// Set the context of the window to the context of the current thread ( Context : Refers to the state of the current state machine )
// initialization GLAD, load OpenGL Function pointer address of the function
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// Create viewport
glViewport(0, 0, screen_width, screen_height);
// Generate and bind VBO
GLuint vertex_buffer_object;
glGenBuffers(1, &vertex_buffer_object);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);
// Bind vertex data to the current default buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Generate and bind VAO
GLuint vertex_array_object;
glGenVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
// Set vertex property pointer
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Unbundling VAO and VBO
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Vertex shader source code
const char* vertex_shader_source =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n" // The property location value of the location variable is 0
"void main()\n"
"{\n"
" gl_Position = vec4(aPos, 1.0);\n"
"}\n\0";
// Fragment shader source code
const char* fragment_shader_source =
"#version 330 core\n"
"out vec4 FragColor;\n" // Output color vector
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
// Compile vertex shader
int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
glCompileShader(vertex_shader);
int success;
char info_log[512];
// Check whether the shader was successfully compiled , If compilation fails , Print error messages
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << info_log << std::endl;
}
// Compiling fragment shaders
int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
glCompileShader(fragment_shader);
// Check whether the shader was successfully compiled , If compilation fails , Print error messages
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << info_log << std::endl;
}
// Link vertex and clip shaders to a shader program
int shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glLinkProgram(shader_program);
// Check whether the shader is successfully linked , If the link fails , Print error messages
glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shader_program, 512, NULL, info_log);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << info_log << std::endl;
}
// Delete shader
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
// Wireframe mode
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// Render loop
while (!glfwWindowShouldClose(window)) {
// Empty the color buffer
glClearColor(0.0f, 0.34f, 0.57f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Using shader programs
glUseProgram(shader_program);
// Draw a quadrilateral
glBindVertexArray(vertex_array_object); // binding VAO
// Draw a quadrilateral
glDrawArrays(GL_TRIANGLES, 0, 6);
// use EBO Draw a quadrilateral
//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0); // Unbind
// Swap buffers and check for triggering events ( For example, keyboard input 、 Mouse movement, etc )
glfwSwapBuffers(window);
glfwPollEvents();
}
// Delete VAO/VBO
glDeleteVertexArrays(1, &vertex_array_object);
glDeleteBuffers(1, &vertex_buffer_object);
// Clean up all resources and exit the program correctly
glfwTerminate();
return 0;
}Output results :


8、 Carding process
Initialize first OpenGL, There are four steps
Then the data is processed through VAO、VBO Send it to GPU
And set the property pointer to tell GPU How to interpret these data
Then the data is processed in the shader by vertex and fragment shaders
Finally, render to generate the final graphics .
9、EBO
Our quadrilateral is made up of two triangles , From the vertex data, you will find that the upper left and lower right vertices repeat twice , If you do large-scale calculations , There is no doubt that this method will cause a lot of waste of computer resources . I want to solve this problem , In fact, we only need to store the four vertices of the quadrilateral .EBO Can help us achieve this function .
Create index
// Quadrilateral vertex data
float vertices[] = {
// The first triangle
0.5f,0.5f,0.0f,//right up
0.5f,-0.5f,0.0f,//right down
-0.5f,-0.5f,0.0f,//left down
// The second triangle
-0.5f,-0.5f,0.0f,//left down
0.5f,0.5f,0.0f,//right up
-0.5f,0.5f,0.0f,//left up
};
// Index data ( Notice that this is from 0 At the beginning )
unsigned int indices[] = {
0, 1, 5, // The first triangle
1, 2, 5 // The second triangle
};
Create buffer object EBO
// Generate and bind EBO
GLuint element_buffer_object; // == EBO
glGenBuffers(1, &element_buffer_object);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer_object);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);Complete code
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
// Set the screen width 、 high
const int screen_width = 800;
const int screen_height = 600;
// Quadrilateral vertex data
float vertices[] = {
// The first triangle
0.5f,0.5f,0.0f,//right up
0.5f,-0.5f,0.0f,//right down
-0.5f,-0.5f,0.0f,//left down
// The second triangle
-0.5f,-0.5f,0.0f,//left down
0.5f,0.5f,0.0f,//right up
-0.5f,0.5f,0.0f,//left up
};
// Index data ( Notice that this is from 0 At the beginning )
unsigned int indices[] = {
0, 1, 5, // The first triangle
1, 2, 5 // The second triangle
};
int main() {
// initialization GLFW
glfwInit();// initialization GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);// Set the major version number
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);// Set the minor version number
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// Set the core mode
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);//MAC OS
glfwWindowHint(GLFW_RESIZABLE, false);// Close resizable window
// create a window
auto window = glfwCreateWindow(screen_width, screen_height, "Quad", nullptr, nullptr);
if (window == nullptr) {
std::cout << "Failed to Create OpenGL Context" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);// Set the context of the window to the context of the current thread ( Context : Refers to the state of the current state machine )
// initialization GLAD, load OpenGL Function pointer address of the function
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// Create viewport
glViewport(0, 0, screen_width, screen_height);
// Generate and bind VBO
GLuint vertex_buffer_object;
glGenBuffers(1, &vertex_buffer_object);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);
// Bind vertex data to the current default buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Generate and bind VAO
GLuint vertex_array_object;
glGenVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
// Generate and bind EBO
GLuint element_buffer_object; // == EBO
glGenBuffers(1, &element_buffer_object);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer_object);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Set vertex property pointer
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Unbundling VAO and VBO
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Vertex shader source code
const char* vertex_shader_source =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n" // The property location value of the location variable is 0
"void main()\n"
"{\n"
" gl_Position = vec4(aPos, 1.0);\n"
"}\n\0";
// Fragment shader source code
const char* fragment_shader_source =
"#version 330 core\n"
"out vec4 FragColor;\n" // Output color vector
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
// Compile vertex shader
int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
glCompileShader(vertex_shader);
int success;
char info_log[512];
// Check whether the shader was successfully compiled , If compilation fails , Print error messages
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << info_log << std::endl;
}
// Compiling fragment shaders
int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
glCompileShader(fragment_shader);
// Check whether the shader was successfully compiled , If compilation fails , Print error messages
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << info_log << std::endl;
}
// Link vertex and clip shaders to a shader program
int shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glLinkProgram(shader_program);
// Check whether the shader is successfully linked , If the link fails , Print error messages
glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shader_program, 512, NULL, info_log);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << info_log << std::endl;
}
// Delete shader
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
// Wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// Render loop
while (!glfwWindowShouldClose(window)) {
// Empty the color buffer
glClearColor(0.0f, 0.34f, 0.57f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Using shader programs
glUseProgram(shader_program);
// Draw a quadrilateral
glBindVertexArray(vertex_array_object); // binding VAO
// Draw a quadrilateral
glDrawArrays(GL_TRIANGLES, 0, 6);
// use EBO Draw a quadrilateral
//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0); // Unbind
// Swap buffers and check for triggering events ( For example, keyboard input 、 Mouse movement, etc )
glfwSwapBuffers(window);
glfwPollEvents();
}
// Delete VAO/VBO
glDeleteVertexArrays(1, &vertex_array_object);
glDeleteBuffers(1, &vertex_buffer_object);
// Clean up all resources and exit the program correctly
glfwTerminate();
return 0;
}Output results : ditto .
边栏推荐
- 外包干了四年,人直接废了。。。
- 神经网络学习小记录71——Tensorflow2 使用Google Colab进行深度学习
- Procédures stockées MySQL
- 2022.6.20-----leetcode.715
- Mybatis的引入问题invalid
- 2022.6.20-----leetcode. seven hundred and fifteen
- Intelligent manufacturing learning videos and books
- What does virtualization mean? What technologies are included? What is the difference with private cloud?
- Kotlin learning apply plugin: 'kotlin Android extensions‘
- MySQL高级篇第一章(linux下安装MySQL)【下】
猜你喜欢

Kotlin uses viewpager2+fragment+bottomnavigationview to implement the style of the switching module of the bottom menu bar.
![[LOJ 6718] nine suns' weakened version (cyclic convolution, arbitrary modulus NTT)](/img/fd/0c299b7cc728f2d6274eea30937726.png)
[LOJ 6718] nine suns' weakened version (cyclic convolution, arbitrary modulus NTT)

. Net core learning journey

Non H5 end of uni app, regional setting of status bar on the top of mobile phone

DETR3D 多2d图片3D检测框架

Oracle技术分享 oracle 19.14升级19.15

使用SOAPUI访问对应的esb工程

Matplotlib multi line chart, dot scatter chart

【LOJ#6718】九个太阳「弱」化版(循环卷积,任意模数NTT)

C # knowledge structure
随机推荐
2022.6.25-----leetcode. Sword finger offer 091
优化——多目标规划
Li Kou 79 word search
Use soapUI to access the corresponding ESB project
WebRTC系列-网络传输之6-Connections裁剪
Open camera anomaly analysis (I)
虚拟化是什么意思?包含哪些技术?与私有云有什么区别?
【Flink】Flink 批处理模式Map端数据聚合 NormalizedKeySorter
Ten important basic principles of software debugging and testing
Intelligent manufacturing learning videos and books
Comparison of static methods and variables with instance methods and variables
Quanergy欢迎Lori Sundberg出任首席人力资源官
刷题记录Day01
R语言与机器学习
1. foundation closing
MySQL advanced part (IV: locking mechanism and SQL optimization)
ABP framework
如何解决 Iterative 半监督训练 在 ASR 训练中难以落地的问题丨RTC Dev Meetup
String到底能不能改变?
第 4 篇:绘制四边形