OpenGL简介
OpenGL(Open Graphics Library)是指定义了一个跨编程语言、跨平台的编程接口规格的专业的图形程序接口。它用于三维图像(二维的亦可),是一个功能强大,调用方便的底层图形库。OpenGL是行业领域中最为广泛接纳的 2D/3D 图形 API,其自诞生至今已催生了各种计算机平台及设备上的数千优秀应用程序。
GLFW简介
GLFW(Graphics Library Framework),它是一个小型 C 库,允许使用 OpenGL 上下文创建和管理窗口,从而也可以使用多个监视器和视频模式。它同时提供对键盘、鼠标和操纵杆输入的访问。
GLAD简介
由于OpenGL驱动版本众多,大多数函数的位置都无法在编译时确定下来,需要在运行时进行查询,使得开发过程较为繁琐。GLAD (Multi-Language GL/GLES/EGL/GLX/WGL Loader-Generator based on the official specs) 是一个开源的库,可以提供一种更为简单的方法加载所有相关的OpenGL函数。
GLM简介
GLM(OpenGL Mathematics)是专门为OpenGL量身定做的数学库,它是一个只有头文件的库,可以快速实现矩阵变换等各种图形学中常用的几何计算。
三者的关系
OpenGL定义标准 → 显卡厂商编写驱动 → GLAD提供接口 → GLFW建立窗口
因为我喜欢也习惯了用clion写C ,所以还是决定配置clion的OpenGL环境
首先下载GLFW和glad这两个库
glad下载
glad.dav1d.de
选择最新的版本
再点这个
下载压缩包
GLFW下载
Download | GLFW
这个可能需要开一下,然后下对应电脑适配版本,我是Windows64,下这个64位的
完事之后打开Clion,创建一个新项目,就叫OpenGL吧,然后建立起三个目录,include,lib,src
解压刚刚那两个文件夹,把GLFW的include文件夹下的GLFW文件夹放到刚刚Clion项目的新目录include下,然后把lib-mingw-w64文件夹下的glfw3.dll复制到新目录lib和目录cmake-build-debug下
把glad的include文件夹下的glad和KHR放到项目目录include下,src文件夹下的glad.c放到项目目录src下
然后修改CMakeList.txt,除了你的项目名称和cmake版本以及C 版本可以不一样,其他都需要修改成这个样子
代码语言:javascript复制cmake_minimum_required(VERSION 3.23)
project(OpenGL)
set(CMAKE_CXX_STANDARD 14)
add_executable(OpenGL main.cpp src/glad.c)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
link_directories(${PROJECT_SOURCE_DIR}/lib)
target_link_libraries(OpenGL ${PROJECT_SOURCE_DIR}/lib/glfw3.dll)
让gpt写个程序检验一下环境配置,因为我还是啥也不会的才寄,所以现在只能先让gpt来写一下
代码语言:javascript复制#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
// 顶点着色器源码
const char* vertexShaderSource = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
)";
// 片段着色器源码
const char* fragmentShaderSource = R"(
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
)";
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)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// 初始化GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// 编译顶点着色器
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// 编译片段着色器
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// 链接着色器程序
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// 删除着色器
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// 设置顶点数据(这里我们只绘制一个三角形)
float vertices[] = {
0.5f, 0.5f, 0.0f, // 右上角
0.5f, -0.5f, 0.0f, // 右下角
-0.5f, -0.5f, 0.0f, // 左下角
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 渲染循环
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
// 清理资源
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
// 终止GLFW
glfwTerminate();
return 0;
}
居然可以跑,证明我们的clion配置成功了
如果需要的话,还可以下载glm
Release GLM 0.9.8.0 · g-truc/glm (github.com)
下载后解压,把里面的glm文件夹,注意是下面这个,放到项目的include目录下
再让gpt先生给我们写一个用glad、glm和glfw画画的程序
代码语言:javascript复制#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
#include "glm/gtc/type_ptr.hpp"
// 顶点着色器源码
const char* vertexShaderSource = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec3 color;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
color = aColor;
}
)";
// 片段着色器源码
const char* fragmentShaderSource = R"(
#version 330 core
in vec3 color;
out vec4 FragColor;
void main()
{
FragColor = vec4(color, 1.0);
}
)";
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)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// 初始化GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// 编译顶点着色器
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// 编译片段着色器
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// 链接着色器程序
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// 删除着色器
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// 设置顶点数据(这里我们只绘制一个彩色的三角形)
float vertices[] = {
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 顶部顶点,红色
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 左下角顶点,绿色
0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f // 右下角顶点,蓝色
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 设置投影矩阵
glm::mat4 projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);
// 渲染循环
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
// 设置视图矩阵
glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
// 设置模型矩阵
glm::mat4 model = glm::mat4(1.0f);
model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f));
// 设置着色器uniform变量
unsigned int modelLoc = glGetUniformLocation(shaderProgram, "model");
unsigned int viewLoc = glGetUniformLocation(shaderProgram, "view");
unsigned int projectionLoc = glGetUniformLocation(shaderProgram, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
// 清理资源
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
// 终止GLFW
glfwTerminate();
return 0;
}
多么好看,还会转