一、OpenGL
参考资料
计算机图形学编程(使用OpenGL和C++)
OpenGL编程指南
The OpenGL® Programming Guide 9th Edition 官网源码
WebGL编程指南
Vulkan学习指南
Vulkan开发实战详解
Vulkan Programming Guide
坐标系统
参考教程
教程 1
【OpenGL】一、Visual Studio 2019 创建 Windows 桌面程序 ( Visual Studio Installer 安装 C++ 桌面开发库 | 创建桌面程序 )
【OpenGL】二、Visual Studio 2019 配置 GitHub ( 下载并安装 GitHub 扩展 | 配置 GitHub )
【OpenGL】三、Visual Studio 2019 配置 GitHub ( 将项目上传到 GitHub )
【OpenGL】四、Visual Studio 2019 配置 GitHub ( 从 GitHub 上克隆项目 )
【OpenGL】五、Visual Studio 2019 配置 GitHub ( 提交代码 )
【OpenGL】六、Visual Studio 2019 配置 GitHub ( 提取和拉取简介 | 拉取远程代码 )
【OpenGL】七、桌面窗口搭建 ( 导入头文件 | 桌面程序入口函数 | 注册窗口 | 创建窗口 | 显示窗口 )
【OpenGL】八、初始化 OpenGL 渲染环境 ( 导入 OpenGL 头文件 | 链接 OpenGL 库 | 将窗口设置为 OpenGL 窗口 | 设置像素格式描述符 | 渲染绘制 ) ★
【OpenGL】九、OpenGL 绘制基础 ( OpenGL 状态机概念 | OpenGL 矩阵概念 )
【OpenGL】十、OpenGL 绘制点 ( 初始化 OpenGL 矩阵 | 设置投影矩阵 | 设置模型视图矩阵 | 绘制点 | 清除缓冲区 | 设置当前颜色值 | 设置点大小 | 绘制点 )
【OpenGL】十一、OpenGL 绘制多个点 ( 绘制单个点 | 绘制多个点 )
【OpenGL】十二、OpenGL 绘制线段 ( 绘制单条线段 | 绘制多条线段 | 依次连接的点组成的线 | 绘制圈 | 绘制彩色的线 )
【OpenGL】十三、OpenGL 绘制三角形 ( 绘制单个三角形 | 三角形绘制顺序 | 绘制多个三角形 )
【OpenGL】十四、OpenGL 绘制三角形 ( 绘制 GL_TRIANGLE_STRIP 三角形 | GL_TRIANGLE_STRIP 三角形绘制分析 )
【OpenGL】十五、OpenGL 绘制三角形 ( 绘制 GL_TRIANGLE_FAN 三角形扇 )
【OpenGL】十六、OpenGL 绘制四边形 ( 绘制 GL_QUADS 四边形 )
【OpenGL】十七、OpenGL 绘制四边形 ( 绘制 GL_QUAD_STRIP 模式四边形 )
【OpenGL】十八、OpenGL 绘制多边形 ( 绘制 GL_POLYGON 模式多边形 )
【OpenGL】十九、OpenGL 绘制模式 ( 绘制线框模式 | 绘制点模式 )
【OpenGL】二十、OpenGL 矩阵变换 ( 矩阵缩放变换 | 矩阵旋转变换 | 矩阵平移变换 )
【OpenGL】二十一、OpenGL 矩阵压栈与出栈 ( 不同类型矩阵变换先后顺序 | 渲染前不设置单位阵 | 压栈出栈原理分析 | 代码示例 )
【OpenGL】二十二、OpenGL 光照效果 ( 模型准备 | 光照设置 | 启用光照 | 启用光源 | 设置光源位置 | 设置光照参数 | 设置环境光 | 设置反射材质 | 设置法线 )
【OpenGL】二十四、OpenGL 纹理贴图 ( 读取文件内容 | 桌面程序添加控制台窗口 | ‘fopen‘: This function may be unsafe 错误处理 )
教程 2
相关库
GLFW
GLFW 是配合 OpenGL 使用的轻量级工具程序库,缩写自 Graphics Library Framework(图形库框架)。GLFW 的主要功能是创建并管理窗口和 OpenGL 上下文,同时还提供了处理手柄、键盘、鼠标输入的功能。 有类似功能的库还有 GLUT和 SDL。
示例
CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0) project(ch1 VERSION 0.1.0 LANGUAGES C CXX) add_executable(ch1 main.cpp) target_include_directories(ch1 PRIVATE "D:/work/learnOpenGl/glfw-3.3.8.bin.WIN64/include") target_link_directories(ch1 PRIVATE "D:/work/learnOpenGl/glfw-3.3.8.bin.WIN64/lib-vc2019") target_link_libraries(ch1 glfw3 opengl32)
代码:main.cpp
#include <GLFW/glfw3.h> #include <gl/GL.h> #include <iostream> // #pragma comment(lib, "opengl32.lib") // #pragma comment(lib, "glfw3.lib") void error_callback(int code, const char *description); void display() { glLineWidth(2.0f); // glColor4ub(255, 255, 255, 255); glColor3f(1.f, 0.f, 0.f); glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 1.0f); glVertex3f(-5.0f, 3.0f, -0.5f); glEnd(); } int main(int argc, char **argv) { GLFWwindow *window; /* Handle GLFW Error */ glfwSetErrorCallback(error_callback); /* Initialize the library */ if (!glfwInit()) return -1; /* Create a windowed mode window and its OpenGL context */ window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL); if (!window) { glfwTerminate(); return -1; } /* Make the window's context current */ glfwMakeContextCurrent(window); // glfwSwapInterval(1); /* Loop until the user closes the window */ while (!glfwWindowShouldClose(window)) { /* Render here */ glClear(GL_COLOR_BUFFER_BIT); display(); /* Swap front and back buffers */ glfwSwapBuffers(window); /* Poll for and process events */ glfwPollEvents(); } glfwTerminate(); return 0; } void error_callback(int code, const char *description) { std::cout << code << ":" << description << std::endl; }
运行结果:
GL3W
gl3w是获得OpenGL核心配置文件规范提供的功能的最简单方法。
它的主要部分是一个简单的gl3w_gen.py Python脚本,该脚本下载Khronos支持的glcorearb.h标头,并从中生成gl3w.h和
gl3w.c。然后可以将这些文件添加并链接(静态或动态)到您的项目中。
Note that GL/gl3w.h must be included before any other OpenGL related headers
#include <Windows.h> #include <GL/gl3w.h> #include <GL/GL.h> #include <GLFW/glfw3.h>
API Reference
The gl3w API consists of just three functions:
int gl3wInit(void)
Initializes the library. Should be called once after an OpenGL context has been created. Returns 0 when gl3w was initialized successfully, non-zero if there was an error.
glfwMakeContextCurrent(window); gl3wInit();
int gl3wIsSupported(int major, int minor)
Returns 1 when OpenGL core profile version major.minor is available and 0 otherwise.
GL3WglProc gl3wGetProcAddress(const char *proc)
Returns the address of an OpenGL extension function. Generally, you won’t need to use it since gl3w loads all functions defined in the OpenGL core profile on initialization. It allows you to load OpenGL extensions outside of the core profile.
示例
CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0) project(ch4 VERSION 0.1.0 LANGUAGES C CXX) include_directories("D:/work/learnOpenGl/gl3w-master/include") set(gl3w_src D:/work/learnOpenGl/gl3w-master/src/gl3w.c) # include_directories("D:/work/learnOpenGl/gl3w-master/build/include") # set(gl3w_src D:/work/learnOpenGl/gl3w-master/build/src/gl3w.c) add_executable(ch4 main.cpp ${gl3w_src}) include_directories("D:/work/learnOpenGl/glfw-3.3.8.bin.WIN64/include") target_link_directories(ch4 PRIVATE "D:/work/learnOpenGl/glfw-3.3.8.bin.WIN64/lib-vc2019") target_link_libraries(ch4 glfw3 opengl32)
代码:main.cpp
#include <Windows.h> #include <GL/gl3w.h> #include <GL/GL.h> #include <GLFW/glfw3.h> #include <iostream> // #pragma comment(lib, "opengl32.lib") // #pragma comment(lib, "glu32.lib") float vertices[] = {-0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f}; 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"; static void error_callback(int error, const char *description) { fputs(description, stderr); } void framebuffer_size_callback(GLFWwindow *window, int width, int height); int main() { glfwSetErrorCallback(error_callback); if (!glfwInit()) { std::cout << "glfwInit error" << std::endl; exit(EXIT_FAILURE); } // 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, "LearnOpenGL", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); gl3wInit(); glfwSwapInterval(1); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); std::cout << "[Debug] " << __LINE__ << std::endl; unsigned int 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); std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; } std::cout << "[Debug] " << __LINE__ << std::endl; unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); glCompileShader(fragmentShader); glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; } std::cout << "[Debug] " << __LINE__ << std::endl; unsigned int shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); 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); std::cout << "[Debug] " << __LINE__ << std::endl; 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); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); glUseProgram(shaderProgram); std::cout << "[Debug] " << __LINE__ << std::endl; while (!glfwWindowShouldClose(window)) { glClearColor(0.2f, 0.3f, 0.3f, 1.0f); // 状态设置 glClear(GL_COLOR_BUFFER_BIT); // 状态使用 // 需要注意的是前面我们已经解绑了VAO,所以现在是无法解析数据的,所以我们需要重新绑定, // 至于数据我们已经存到缓冲区了 glBindVertexArray(VAO); // 从数据数组中indexwei0处开始读取,每三个做一个三角形的顶点。第三个参数是说一共绘制三个顶点数据(每个顶点由vertices数组中的3个元素组成) glDrawArrays(GL_TRIANGLES, 0, 3); glfwSwapBuffers(window); glfwPollEvents(); } // glfw: 回收前面分配的GLFW先关资源. // 一定要注意,只有关闭窗体之后才会跳出while循环走到这一步!!! glfwDestroyWindow(window); glfwTerminate(); // 在while循环退出后释放内存: glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteProgram(shaderProgram); return 0; } // 当改变窗口的大小的时候,视口也应该被调整。我们可以对窗口注册一个回调函数(Callback // Function),它会在每次窗口大小被调整的时候被调用 void framebuffer_size_callback(GLFWwindow *window, int width, int height) { // 设置窗口维度 // glViewport(前两参数为窗口左下角位置,3.宽度,4.高度) glViewport(0, 0, width, height); }
运行结果:
GLEW
GLEW 是一个跨平台的 C++ 扩展库,基于 OpenGL 图形接口。使用 OpenGL 的朋友都知道,window 目前只支持 OpenGL1.1 的涵数,但 OpenGL 现在都发展到 2.0 以上了,要使用这些 OpenGL 的高级特性,就必须下载最新的扩展,另外,不同的显卡公司,也会发布一些只有自家显卡才支 持的扩展函数,你要想用这数涵数,不得不去寻找最新的 glext.h, 有了 GLEW 扩展库,你就再也不用为找不到函数的接口而烦恼,因为 GLEW 能自动识 别你的平台所支持的全部 OpenGL 高级扩展涵数。也就是说,只要包含一个 glew.h 头文件,你就能使用 gl,glu,glext,wgl,glx 的全 部函数。GLEW 支持目前流行的各种操作系统(including Windows, Linux, Mac OS X, FreeBSD, Irix, and Solaris)。
openGl新手入门学习笔记(二)下载glew,配置glew的环境与glew的初始化
根据官方文档我们可以知道Initializing GLEW的步骤:
First you need to create a valid OpenGL rendering context and call glewInit() to initialize the extension entry points. If glewInit() returns GLEW_OK, the initialization succeeded and you can use the available extensions as well as core OpenGL functionality.
即在调用 glewInit() 来初始化前必须先创造一个OpenGL的渲染上下文。使用 glfwMakeContextCurrent(window) 函数创建了渲染上下文,再调用 glewInit() 即可初始化成功。
示例
CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0) project(ch3 VERSION 0.1.0 LANGUAGES C CXX) add_executable(ch3 main.cpp) target_include_directories(ch3 PRIVATE "D:/work/learnOpenGl/glfw-3.3.8.bin.WIN64/include") target_link_directories(ch3 PRIVATE "D:/work/learnOpenGl/glfw-3.3.8.bin.WIN64/lib-vc2019") target_link_libraries(ch3 glfw3 opengl32) target_include_directories(ch3 PRIVATE "D:/work/learnOpenGl/glew-2.2.0/include") target_link_directories(ch3 PRIVATE "D:/work/learnOpenGl/glew-2.2.0/lib/Release/x64") target_link_libraries(ch3 glew32)
代码:main.cpp
与 GL3W 的差异如下:
GLM
OpenGL Mathematics (GLM) is a C++ mathematics library for 3D software based on the OpenGL Shading Language (GLSL) specification.
对于实现矩阵变化的C++库,可以使用GLM(OpenGL Mathematics)库。GLM是一个只包含头文件的库,专为需要数学运算的图形软件设计,它基于OpenGL Shading Language (GLSL) 规范,并提供了类似GLSL的接口。
GLM提供的功能包括基本向量操作,矩阵变换(如平移、缩放、旋转)、投影变换等。GLM非常适合用于OpenGL的计算,因为它的设计目标就是与GLSL和OpenGL的数据类型匹配。
其它库
SOIL2
OpenGL学习预备篇——使用premake配置SOIL2库
SOIL是简易OpenGL图像库(Simple OpenGL Image Library)的缩写,它支持大多数流行的图像格式,使用起来也很简单。当前的最新版本是SOIL2。
GLSL
GLSL(OpenGL Shading Language) 全称 OpenGL 着色语言,是用来在 OpenGL 中着色编程的语言,也即开发人员写的短小的自定义程序,他们是在图形卡的 GPU上执行的,代替了固定的渲染管线的一部分,使渲染管线中不同层次具有可编程性。 GLSL 其使用 C 语言作为基础高阶着色语言,避免了使用汇编语言或硬件规格语言的复杂性。
// 基本语法为: layout(qualifier1, qualifier2 = value, ...) variable definition // 顶点着色器的属性索引 layout(location = attribute index) in vec3 position;
3D 建模工具
3D建模工具有很多种,以下是一些常用的:
- 3ds Max :这是一款广泛使用的3D建模软件,它速度快,功能全面,常用于建筑、动画、视频游戏等领域。
- Maya :Maya功能完善,工作灵活,易学易用,制作效率极高,渲染真实感极强,被广泛应用于电影级别的CG制作。
- ZBrush :ZBrush是一款独立的三维雕塑和建模应用,以其强大的数字雕刻功能而闻名,常用于游戏影视行业的UV贴图和绘制纹理。
- Substance Painter :随着PBR(Physically Based Rendering,基于物理的渲染)工作流的应用,Substance Painter已经成为行业标准贴图处理软件。
- Blender :Blender是一个开源的跨平台3D创作套件,它的功能包括建模、动画、视觉特效等,适用于各种类型的3D艺术项目。
- Marvelous Designer :MD主要用于制作逼真的衣物和道具,特别适合写实风格的3D设计。
- Rizom UV :Rizom UV是一款展UV的神器,其内建的快速测试查看功能非常方便。
- Photoshop :虽然Photoshop主要用作图像编辑,但它也可以进行一些基本的贴图修改。
选择哪种3D建模工具取决于你的具体需求,比如你要制作的类型、预算和时间限制等因素1。