本文基于The Cherno在Youtube上的OpenGL系列视频总结出的笔记,等这个系列视频学习完后,将更加系统详细的学习《计算机图形学编程(使用OpenGL和C++ 第二版)》这本书。个人认为看cherno的视频上手速度更快,而且他对基本概念和原理的解释非常通俗易懂,对于想快速学习OpenGL的同学很适用。
目前学习进度:9/31。以下编号对应系列视频的编号:
OpenGL-youtube
1
OpenGL是一个规范,类似C++,本身不提供代码,提供那个代码的是GPU供应商,例如NVIDIA/AMD,其驱动中包含了OpenGL的实现,该实现并不开源,即你无法看到其源码
OpenGL相比于Vulcan更简单,更易学?OpenGL是跨平台的
Direct3D接口设计得很好
legacy OpenGL和modern OpenGL的区别是modern更像是一组预设功能,legacy则提供更底层的调用。另外两者的最大区别是着色器(shader)不同,shader是一段运行在GPU上的代码,modern OpenGL的shader是可编程的,legacy则是不可编程的
2
window的图形api是directX/direct3D
OpenGL函数是在GPU驱动文件中的(dll),而不是某个可以被下载的代码,我们要做的事情是从驱动的dll库中“提取”函数并且得到函数指针从而调用他们,但是这个动作与平台有关,例如window需要一些win32函数来提取dll中的函数,为了跨平台我们需要glew库帮我们处理跨平台的事情,glew是openGL的扩展库,这些库的实现是识别我们的图形驱动类型并找到相应的dll文件并加载函数指针,这些dll文件原本就在我们电脑上。
3 4 5
openGL是一个状态机,pipeline工作方式:为显卡提供绘制需要的数据并存储在GPU上,然后使用shader着色器(在GPU上执行)读取这些数据,并显示在屏幕上。通常绘制图形时我们使用vertex buffer存储数据,我们通过vertext attribute告诉OpenGL这些数据的layout布局,即如何解码/翻译这些数据。
vertex可以包含除了位置之外的其他信息,如颜色,纹理等,这些都是vertex的属性,属性通过index来索引(0,1,2…),如0时位置,1是纹理,它表明了属性在buffer中的layout
void glVertexAttribPointer(
GLuint index, // 指定当前vertex属性的索引
GLint size, // 表示当前vertex属性的由几部分(component)组成,只能是1/2/3/4,例如二维坐标size是2,三维坐标size是3
GLenum type, // 当前vertex属性的数据类型
GLboolean normalized, // 是否让opengl归一化,例如颜色0-255归一到shader中的[0,1]空间
GLsizei stride, // vertex的大小,即vertex所有属性相加的大小
const GLvoid * pointer); // 下一个属性的偏移位置
n个属性就调用glVertexAttribPointer n次
6
如果程序没有提供shader,某些GPU driver会提供默认的shader。
shader是一个运行在GPU上的程序,shader将数据进行解析,从而实现绘制、光照等等效果。
shader类型:
- vertex shader。顶点着色器
- fragment shader。片段着色器,像素着色器
- …
vertext shader和fragment shader覆盖了90%的场景。
OpenGL pipeline(管道)基本工作过程: - 在CPU上写入了一系列的数据
- 将数据送入GPU
- (使OpenGL处于某种状态从而)触发draw call()
- 进入shader stage,即GPU开始处理draw call并在屏幕上绘制
- vertex shader先于fragment shader被调用
vertex shader的作用是告诉OpenGL我们希望vertex在什么位置,此外vertex shader解析所有vertex attr并将数据传递给下一个shader。vertex shader对每个vertex都会调用一次
fragment shader的作用是决定每个像素是什么颜色,fragment shader对每个需要 绘制的/rasterized(光栅化/栅格化)的 像素都会调用一次,例如一个绘制三角形,其内部需要填充的每个像素都会调用一次fragment shader
由于不同shader的调用次数不同,因此对于某些性能优化的场景,我们应该尽可能地减少在频繁调用的shader中进行不必要的计算。
- vertex shader先于fragment shader被调用
7 8
shader代码可以直接在程序中编写,或者来自某个shader代码文件,或者是某些二进制文件,然后给OpenGL提供这些代码进行编译,链接到同一个shader程序中,并返回给我们一个唯一的shader ID。shader程序在GPU上运行
9
绘制的基本单元是三角形,因为这是使用最少vertex确定一个平面的方法。当我们绘制一个矩形,我们实际上绘制了两个三角形.
index buffer用于重用已经存在的vertex,避免过多重复数据。
GL_ELEMENT_ARRAY_BUFFER的数据类型必须是unsigned int,不能是int