返回
OpenGL正方形绘制及上下左右移动详解
见解分享
2023-09-26 06:46:18
OpenGL简介
OpenGL是一个跨平台的图形库,用于创建三维计算机图形。它是一个低级的图形库,这意味着它直接与图形硬件进行交互。OpenGL被广泛用于游戏、视频编辑和科学可视化等领域。
绘制正方形
要使用OpenGL绘制正方形,我们需要遵循以下步骤:
- 创建OpenGL上下文。
OpenGL上下文是一个与图形硬件关联的特殊环境,它是OpenGL进行渲染操作的场所。创建OpenGL上下文需要使用操作系统提供的函数。
- 加载着色器程序。
着色器程序是OpenGL用来渲染图形的程序。它由两个着色器组成:顶点着色器和片段着色器。顶点着色器负责处理顶点数据,片段着色器负责处理片元数据。
- 创建顶点缓冲区对象。
顶点缓冲区对象是一个存储顶点数据的缓冲区。顶点数据包括顶点的位置、颜色和纹理坐标等信息。
- 创建索引缓冲区对象。
索引缓冲区对象是一个存储索引数据的缓冲区。索引数据告诉OpenGL如何将顶点组装成几何图形。
- 绑定顶点缓冲区对象和索引缓冲区对象。
将顶点缓冲区对象和索引缓冲区对象绑定到OpenGL的管道中,以便OpenGL可以访问这些数据。
- 绘制正方形。
使用OpenGL的glDrawElements
函数绘制正方形。这个函数需要提供索引缓冲区对象作为参数,以便OpenGL知道如何将顶点组装成正方形。
实现正方形的上下左右移动
要实现正方形的上下左右移动,我们需要使用矩阵变换。矩阵变换可以将正方形平移、旋转和缩放。
平移矩阵:
[1, 0, 0, 0]
[0, 1, 0, 0]
[0, 0, 1, 0]
[x, y, z, 1]
旋转矩阵:
[cos(theta), -sin(theta), 0, 0]
[sin(theta), cos(theta), 0, 0]
[0, 0, 1, 0]
[0, 0, 0, 1]
缩放矩阵:
[x_scale, 0, 0, 0]
[0, y_scale, 0, 0]
[0, 0, z_scale, 0]
[0, 0, 0, 1]
要将矩阵变换应用到正方形,我们需要将矩阵变换矩阵与正方形的模型矩阵相乘。模型矩阵是一个4x4矩阵,它定义了正方形在世界空间中的位置、旋转和缩放。
model_matrix = translation_matrix * rotation_matrix * scale_matrix;
将模型矩阵应用到正方形后,OpenGL就会根据模型矩阵来渲染正方形。
完整示例代码
以下是一个完整的示例代码,展示了如何使用OpenGL绘制正方形,并实现正方形的上下左右移动:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
// 顶点着色器代码
const char *vertex_shader_source =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"uniform mat4 model;\n"
"void main()\n"
"{\n"
" gl_Position = model * vec4(aPos, 1.0);\n"
"}\n";
// 片段着色器代码
const char *fragment_shader_source =
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
// 顶点数据
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f
};
// 索引数据
unsigned int indices[] = {
0, 1, 2,
0, 2, 3
};
int main()
{
// 初始化GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// 创建窗口
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL正方形绘制", NULL, NULL);
if (window == NULL)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// 初始化GLEW
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
glfwTerminate();
return -1;
}
// 创建着色器程序
unsigned int shader_program = glCreateProgram();
// 编译顶点着色器
unsigned int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
glCompileShader(vertex_shader);
// 编译片段着色器
unsigned int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
glCompileShader(fragment_shader);
// 将着色器附加到着色器程序
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
// 链接着色器程序
glLinkProgram(shader_program);
// 使用着色器程序
glUseProgram(shader_program);
// 创建顶点缓冲区对象
unsigned int VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 创建索引缓冲区对象
unsigned int IBO;
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// 绑定顶点缓冲区对象和索引缓冲区对象
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
// 获取顶点着色器中的位置属性位置
unsigned int pos_loc = glGetAttribLocation(shader_program, "aPos");
glEnableVertexAttribArray(pos_loc);
glVertexAttribPointer(pos_loc, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
// 获取顶点着色器中的模型矩阵统一变量位置
unsigned int model_loc = glGetUniformLocation(shader_program, "model");
// 矩阵变换
glm::mat4 translation_matrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
glm::mat4 rotation_matrix = glm::rotate(glm::mat4(1.0f), 0.0f, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 scale_matrix = glm::scale(glm::mat4(1.0f), glm::vec3(1.0f, 1.0f, 1.0f));
glm::mat4 model_matrix = translation_matrix * rotation_matrix * scale_matrix;
// 渲染循环
while (!glfwWindowShouldClose(window))
{