一、跨平台环境基本配置
1、环境搭建
1)linux OpenGL环境搭建参考:ubuntu18.04 OpenGL开发(显示YUV)_ubuntu opengl-CSDN博客
https://blog.51cto.com/cerana/6433535
2)windows下环境搭建
OpenGL+Visual Studio2022+GLFW+glad详细配置教程_给vs配置glfw和glad-CSDN博客
2、创建cmake
这里测试使用的图形界面使用QT。其中路径后面讲解。
主要有几个注意事项:
1)linux下需要添加
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-error=register")
2)windows下需要设置vitual studio
set(LIBRARY_GLFW_PATH "${PROJECT_SOURCE_DIR}/lib-vc2022")
cmake_minimum_required(VERSION 3.5)SET(TARGET "QTGL")project(${TARGET} VERSION 0.1 LANGUAGES CXX)set(CMAKE_INCLUDE_CURRENT_DIR ON)set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)if(WIN32)
else()set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-error=register")
endif()set(QTGL_GLAPI_PATH "${PROJECT_SOURCE_DIR}/GLAPI")
set(GLAD_FOLDER_INCLUDE_PATH "${PROJECT_SOURCE_DIR}/glad/include")
set(GLAD_FOLDER_SOURCE_PATH "${PROJECT_SOURCE_DIR}/glad/src")
set(GLM_FOLDER_INCLUDE_PATH "${PROJECT_SOURCE_DIR}/glm")
set(GLFW_FOLDER_INCLUDE_PATH "${QTGL_GLAPI_PATH}/glfw")if(WIN32)set(LIBRARY_GLFW_PATH "${PROJECT_SOURCE_DIR}/lib-vc2022")LINK_DIRECTORIES("${LIBRARY_GLFW_PATH}")
endif()include_directories(${QTGL_GLAPI_PATH})
include_directories(${GLAD_FOLDER_INCLUDE_PATH})
include_directories(${GLM_FOLDER_INCLUDE_PATH})
include_directories(${GLFW_FOLDER_INCLUDE_PATH})file(GLOB GLAPI_HEADERS "${QTGL_GLAPI_PATH}/*.h")
source_group("GLAPI/include" FILES ${GLAPI_HEADERS})file(GLOB GLAPI_SOURCES "${QTGL_GLAPI_PATH}/*.cpp")
source_group("GLAPI/source" FILES ${GLAPI_SOURCES})file(GLOB_RECURSE GLAD_INCLUDE "${GLAD_FOLDER_INCLUDE_PATH}/*.*")
source_group("glad/include" FILES ${GLAD_INCLUDE})file(GLOB GLAD_SOURCE "${GLAD_FOLDER_SOURCE_PATH}/*.*")
source_group("glad/src" FILES ${GLAD_SOURCE})SET(QTUI_PATH "${PROJECT_SOURCE_DIR}/QTUI")file(GLOB_RECURSE QTUI_FILES "${QTUI_PATH}/*.*")
source_group("QTUI" FILES ${QTUI_FILES})set(ALL_SOURCES${GLAPI_HEADERS}${GLAPI_SOURCES}${GLAD_INCLUDE}${GLAD_SOURCE}${QTUI_FILES}
)ADD_EXECUTABLE(${TARGET} WIN32 ${ALL_SOURCES})find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)target_link_libraries(${TARGET} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)if(WIN32)target_link_libraries(${TARGET} PRIVATE debug "${LIBRARY_GLFW_PATH}/glfw3.lib" optimized "${LIBRARY_GLFW_PATH}/glfw3.lib")target_link_libraries(${TARGET} PRIVATE debug "${LIBRARY_GLFW_PATH}/glfw3_mt.lib" optimized "${LIBRARY_GLFW_PATH}/glfw3_mt.lib")target_link_libraries(${TARGET} PRIVATE debug "${LIBRARY_GLFW_PATH}/glfw3dll.lib" optimized "${LIBRARY_GLFW_PATH}/glfw3dll.lib")
else()target_link_libraries(${TARGET} PRIVATE glfw3)target_link_libraries(${TARGET} PRIVATE GL)target_link_libraries(${TARGET} PRIVATE X11)target_link_libraries(${TARGET} PRIVATE m)target_link_libraries(${TARGET} PRIVATE pthread)target_link_libraries(${TARGET} PRIVATE dl)
endif()
3、第三方库文件
1)glad和glm
glad下载:https://glad.dav1d.de/,下载后得到glad.zip
把glad整个文件夹放置到工程目录下,然后,把src下的glad.c改为glad.cpp。
把glm整个文件夹放置到工程目录下,不需要额外的修改。
2)glfw
glfw下载,Download | GLFW
windows下,需要将编译好的glfw库放置到工程下。如图:
3)整体工程结构如图:
4、QT界面文件QTUI
创建一个QDialog或者QMainWindow,带有.ui文件,可以使用uic指令将其转换为.h文件。
二、OPENGL 简单示例
1、初始化工程
1)初始化glfw,具体解释看:OpenGL学习(一) 绘制一个三角形 - 简书
int DrawApi::initialGlfw()
{glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// glad: load all OpenGL function pointersreturn 0;
}
2)创建窗口:
int DrawApi::createWindow(string windowName, OUT GLFWwindow*& window)
{// glfw window creation// --------------------window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, windowName.c_str(), NULL, NULL);if (window == NULL){glfwTerminate();return -1;}glfwMakeContextCurrent(window);// ---------------------------------------if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){cout << "Failed to initialize GLAD" << endl;return -1;}glViewport(0, 0, 800, 800);glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // 窗体能够根据拉动变化return 0;
}
3)顶点着色器
int DrawApi::createVertexShader(OUT GLuint& vertexShader, const char* vertexShaderSource)
{//1.初始化着色器//创建一个着色器类型vertexShader = glCreateShader(GL_VERTEX_SHADER);//把代码复制进着色器中glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);//编译顶点着色器glCompileShader(vertexShader);int success;char infoLog[512];glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);//判断是否编译成功if (!success) {glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);cout << "error when vertex compile:" << infoLog << endl;return -1;}return 0;
}
4)片元着色器
int DrawApi::createFragmentShader(OUT GLuint& fragmentShader, const char* fragmentShaderSource)
{fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);int success;char infoLog[512];glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);//判断是否编译成功if (!success) {glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);cout << "error when fragment compile:" << infoLog << endl;return -1;}return 0;
}
5)编译程序
int DrawApi::createProgram(GLuint& vertexShader, GLuint& fragmentShader, OUT GLuint& shaderProgram)
{//链接,创建一个程序shaderProgram = glCreateProgram();//链接上共享库glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);//链接glLinkProgram(shaderProgram);int success;char infoLog[512];glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);cout << "error when link compile:" << infoLog << endl;return -1;}glDeleteShader(vertexShader);glDeleteShader(fragmentShader);return 0;
}
6)绘制三角形
int DrawApi::drawTriangles(const vector<vector<float>>& triangelValues)
{//1.会先绑定顶点//2.绑定缓冲区//3.接着把顶点输入到顶点缓冲去中//4.把缓冲区的数据传送到着色器中//5.输出到屏幕。if (initialGlfw() < 0)return -1;GLFWwindow* window = nullptr;if (createWindow("learnOpenGL", window) < 0)return -2;GLuint vertexShader;if (createVertexShader(vertexShader, VERTEX_SHADER) < 0)return -3;GLuint fragmentShader;if (createFragmentShader(fragmentShader, FRAGMENT_SHADER) < 0)return -4;GLuint shaderProgram;if (createProgram(vertexShader, fragmentShader, shaderProgram) < 0)return -5;if (triangelValues.size() == 0)return -6;if (triangelValues.size() > 1256)return -7;float vertices[4096] = {0};for (int i = 0; i < triangelValues.size(); i++){for (int j = 0; j < 3; j++){vertices[3 * i + j] = triangelValues[i][j];}}GLuint VAO;// 生成分配VAOglGenVertexArrays(1, &VAO);// 绑定VAO,注意在core模式,没有绑定VAO,opengl拒绝绘制任何东西glBindVertexArray(VAO);GLuint VBO;// 生成一个VBO缓存对象glGenBuffers(1, &VBO);// 绑定VBOglBindBuffer(GL_ARRAY_BUFFER, VBO);// 类型为GL_ARRAY_BUFFER 第二第三参数说明要放入缓存的多少,GL_STATIC_DRAW当画面不动的时候推荐使用glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);// render loop// -----------while (!glfwWindowShouldClose(window)){// inputprocessInput(window);// renderglClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(shaderProgram);//绑定数据glBindVertexArray(VAO);//绘制一个三角形//从0开始,3个glDrawArrays(GL_TRIANGLES, 0, triangelValues.size() * 3);glBindVertexArray(0);// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)// -------------------------------------------------------------------------------glfwSwapBuffers(window);glfwPollEvents();}glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);// glfw: terminate, clearing all previously allocated GLFW resources.// ------------------------------------------------------------------glfwTerminate();return 0;
}