暑假闲的没事干,学习了一下计算机图形学,入门了OpenGL,记录一下
什么是OpenGL
OpenGL(Open Graphics Library)是一个跨平台、跨语言的图形应用程序接口(API),用于渲染2D、3D矢量图形。它由Khronos Group维护,广泛应用于游戏开发、CAD设计、虚拟现实、科学可视化等领域。
使用C++编写创建一个窗口
1.需要安装两个库
GLFW
和Glad
库,GLFW 负责把窗口和输入搞定,GLAD 负责把 OpenGL 的函数指针加载好。
如果使用vcpkg
,可以很方便的安装
1 | vcpkg install glfw3 glad |
然后导入头文件
1 |
2.代码编写
2.1 初始化
1 | glfwInit(); |
GLFW_OPENGL_CORE_PROFILE
说明这里使用核心渲染模式,不使用过去的立即渲染模式
2.2 窗口创建
1 | GLFWwindow* window = glfwCreateWindow(800, 600, "study", nullptr, nullptr); |
回调函数定义如下:
1 | void framebufferSizeCallback(GLFWwindow* window, int width, int height) { |
1 | void keybordCallBack(GLFWwindow* window, int key, int scancode, int action, int mods) { |
2.3 加载OpenGL
1 | if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { |
2.4 窗口准备
1 | glViewport(0, 0, 800, 600); // 渲染的区域范围 |
2.5 窗口循环
1 | while (!glfwWindowShouldClose(window)) { |
即可完成窗口的创建
在窗口中渲染一个三角形
1.基础概念
在OpenGL中,任何事物都在3D空间中,而屏幕和窗口却是2D像素数组,这导致OpenGL的大部分工作都是关于把3D坐标转变为适应你屏幕的2D像素。3D坐标转为2D坐标的处理过程是由OpenGL的图形渲染管线(Graphics Pipeline,大多译为管线,实际上指的是一堆原始图形数据途经一个输送管道,期间经过各种变化处理最终出现在屏幕的过程)管理的。图形渲染管线可以被划分为两个主要部分:第一部分把你的3D坐标转换为2D坐标,第二部分是把2D坐标转变为实际的有颜色的像素。
- 图形渲染管线(Graphics Pipeline)
把 3D 坐标 → 2D 像素的一条“传送带”,分两大阶段:①坐标变换 ②像素着色,可并行、可替换其中的 Shader。 - 标准化设备坐标(NDC)
所有顶点最终必须落到 [-1, 1]³ 的立方体里,否则被裁掉;y 向上,原点在中心。 - 图元(Primitive)
告诉 OpenGL 把顶点当成什么来装配:点GL_POINTS
、线GL_LINE_STRIP
、三角形GL_TRIANGLES
…… - 顶点属性(Vertex Attribute)
每个顶点可以携带任意数据,最简形式是vec3 position
。 - VBO(Vertex Buffer Object)
GPU 显存里的“一卡车”顶点数据,一次性从 CPU 上传,减少 draw call 开销。 - 顶点着色器(Vertex Shader)
逐顶点执行,把本地坐标 → 裁剪坐标,输出gl_Position
(必须写)。 - 片段着色器(Fragment Shader)
逐像素执行,决定最终颜色;输出vec4 FragColor
(必须写)。 - 着色器程序(Shader Program)
把若干编译好的 Shader(至少顶点+片段)链接成可执行程序,绘制前glUseProgram(id)
激活。 - glVertexAttribPointer / glEnableVertexAttribArray
告诉 OpenGL 如何从 VBO 里解析出顶点属性(位置、颜色、法线…)。 - VAO(Vertex Array Object)
把“VBO + 解析规则 + EBO”打包成一个对象;绑定一次 VAO = 一键恢复全部状态,Core Profile 强制使用。 - EBO / IBO(Element/Index Buffer Object)
存索引,避免重复顶点;配合glDrawElements
做索引绘制,省内存。 - 绘制调用
- 无索引:
glDrawArrays(GL_TRIANGLES, 0, 3)
- 有索引:
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
- 无索引:
2.代码编写
2.1 创建mesh数据
1 | // 准备一个vao,位置信息和颜色信息分开 |
VBO是记录顶点的元数据,比如位置,颜色,uv之类的
VAO是记录VBO的结构,定义了如何使用VBO的数据
通过 VBO → VAO → Shader 这个过程,即可渲染出一个物体
2.2 创建着色器
1 | void createShaderProgram() { |
2.3 渲染
完成上面的步骤后,在渲染循环中编写如下代码
1 | glfwPollEvents(); |
成功渲染出一个三角形:
完整实例
main.cpp
1 |
|
OpenGLStudy.h:
1 |
|