环境
系统:Ubuntu 20.04
桌面环境:X11
OpenGL版本: 3.0
桌面环境怎么看呢?可以在终端输入echo $XDG_SESSION_TYPE
即可,或者查看桌面右上角的Settings
->About
,查看Windowing System
查看OpenGL版本
使用glxinfo
命令查看,没安装需要安装mesa-utils工具,sudo apt install mesa-utils
$ glxinfo | grep OpenGL
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) HD Graphics 4600 (HSW GT2)
OpenGL core profile version string: 4.5 (Core Profile) Mesa 21.2.6
OpenGL core profile shading language version string: 4.50
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 3.0 Mesa 21.2.6
OpenGL shading language version string: 1.30
OpenGL context flags: (none)
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.1 Mesa 21.2.6
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.10
OpenGL ES profile extensions:
上面OpenGL version string: 3.0 Mesa 21.2.6
可以看出OpenGL
的版本为3.0
开始安装
2.1 安装xorg依赖(GLFW的依赖)
# 前面我们的x11,所以需要安装下面依赖,若为其他wayland,则需要参考glfw官方编译指导进行,[点这里](https://www.glfw.org/docs/latest/compile_guide.html)
$ sudo apt install xorg-dev
2.2 安装GLFW
GLFW是一个专门针对OpenGL的C语言库,它提供了一些渲染物体所需的最低限度的接口,允许用户创建OpenGL上下文、定义窗口参数以及处理用户输入
glfw官网
下载glfw源码进行编译
git clone https://github.com/glfw/glfw
编译
cd glfw
cmake -S . -B build
cd build
make
安装
sudo make install
完成GLFW的编译及安装
2.3 安装GLAD
由于OpenGL驱动版本众多,它大多数函数的位置都无法在编译时确定下来,需要在运行时查询。所以任务就落在了开发者身上,开发者需要在运行时获取函数地址并将其保存在一个函数指针中供以后使用,取得地址的方法代码非常复杂,而且很繁琐,GLAD是一个开源的库,能解决这个繁琐的问题
前面我们知道OpenGl的版本为3.0,这里我们需要对号入座
# 再次查看一下OpenGL版本,没毛病,是3.0
glxinfo | grep "OpenGL version"
OpenGL version string: 3.0 Mesa 21.2.6
登录到GLAD官网,点这里
API
->gl
处,选择OpenGL的版本3.0
,其他不用修改,点击下面的GENERATE
点击GENREATE
后,进入如下页面
下载glad.zip
到本地,并解压得到include
及src
文件夹,将include/*
下的内容拷贝到/usr/local/include
glad.zip解压后的目录结构如下
-- glad
| -- include
| -- glad
| -- KHR
| -- src
| -- glad.c
sudo mv include/* /usr/local/include
2.3 测试环境
创建一个目录code
,并创建CMakeLists.txt
、man.cpp
两个新文件,及一个build
新文件夹
同时把前面glad目录下的src的glad/src/glad.c
复制到code目录下,如下所示
-- code
| -- build
| -- CMakeLists.txt
| -- man.cpp
| -- glad.c
编辑main.cpp
文件,如下所示:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
// 顶点着色器,GLSL语言
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
// 片元着色器
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
int main()
{
// glfw: initialize and configure
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// glfw window creation
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// glad: load all OpenGL function pointers
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// build and compile our shader program
// ------------------------------------
// vertex shader
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); // 把这个着色器源码附加到着色器对象。着色器对象,源码字符串数量,VS真正的源码
glCompileShader(vertexShader);
// check for shader compile errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// fragment shader
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// check for shader compile errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// link shaders
int shaderProgram = glCreateProgram(); // shaderProgram 是多个着色器合并之后并最终链接完成的版本
glAttachShader(shaderProgram, vertexShader); // 附加
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
float vertices[] = {
-0.5f, -0.5f, 0.0f, // left
0.5f, -0.5f, 0.0f, // right
0.0f, 0.5f, 0.0f // top
};
unsigned int VBO, VAO;
//创建VAO对象
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
//创建VBO对象,把顶点数组复制到一个顶点缓冲中,供OpenGL使用
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO); // 缓冲绑定到GL_ARRAY_BUFFER
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 顶点数据复制到缓冲的内存中
//解释顶点数据方式
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); // 顶点数据的解释
glEnableVertexAttribArray(0);
// 解绑VAO
glBindVertexArray(0);
// 解绑VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw our first triangle
glUseProgram(shaderProgram); // 激活shaderProgram,怎么画
glBindVertexArray(VAO); // 画什么
glDrawArrays(GL_TRIANGLES, 0, 3); // 开始画
glfwSwapBuffers(window);
glfwPollEvents();
}
// optional: de-allocate all resources
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
//键盘按键回调函数
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
//调整窗口大小回调函数
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
CMakeLists.txt
文件如下
make_minimum_required(VERSION 2.8)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)
project(test)
find_package(glfw3 REQUIRED)
find_package( OpenGL REQUIRED )
include_directories( ${OPENGL_INCLUDE_DIRS} )
file(GLOB project_file glad.c main.cpp)
add_executable(${PROJECT_NAME} ${project_file})
target_link_libraries(${PROJECT_NAME} ${OPENGL_LIBRARIES} glfw)
开始编译测试
cd build
cmake ..
make
执行完成后,在build文件下,生成了可执行文件text
运行该文件
./test
如下所示,成功!