当前位置:网站首页>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 .
边栏推荐
- Procédures stockées MySQL
- Uni app custom selection date 1 (September 16, 2021)
- Uni app QR code scanning and identification function
- 使用SOAPUI访问对应的esb工程
- xml 解析bean工具类
- [LOJ 6718] nine suns' weakened version (cyclic convolution, arbitrary modulus NTT)
- How to solve the problem that iterative semi supervised training is difficult to implement in ASR training? RTC dev Meetup
- MySQL高级部分( 四: 锁机制、SQL优化 )
- 在出海获客这件事上,数字广告投放之外,广告主还能怎么玩儿?
- High performance computing center roce overview
猜你喜欢

The style of the mall can also change a lot. DIY can learn about it

Analysis of camera memory memory leakage (II)

Quanergy welcomes Lori sundberg as chief human resources officer

Nebula Graph学习篇3_多线程完成6000w+关系数据迁移

如何解决 Iterative 半监督训练 在 ASR 训练中难以落地的问题丨RTC Dev Meetup

Machine learning notes - trend components of time series

阿里云函数计算服务一键搭建Z-Blog个人博客

【Flink】Flink Sort-Shuffle写流程简析
![[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)

第 4 篇:绘制四边形
随机推荐
2020 summary: industrial software development under Internet thinking
(15)Blender源码分析之闪屏窗口显示菜单功能
Nepal graph learning Chapter 3_ Multithreading completes 6000w+ relational data migration
763. 划分字母区间
ABP framework
After Ali failed to start his job in the interview, he was roast by the interviewer in the circle of friends (plug)
[appium stepping pit] io appium. uiautomator2. common. exceptions. InvalidArgumentException: ‘capabilities‘ are mand
R语言与机器学习
Kotlin uses viewpager2+fragment+bottomnavigationview to implement the style of the switching module of the bottom menu bar.
Uni app custom navigation bar component
Evaluation - analytic hierarchy process
MapReduce execution principle record
TiFlash 函数下推必知必会丨十分钟成为 TiFlash Contributor
优化——多目标规划
IEDA 突然找不到了compact middle packages
1.基础关
[Flink] Flink batch mode map side data aggregation normalizedkeysorter
动态线段树leetcode.715
chrome页面录制,重放功能
1. foundation closing