OpenGL教程:4. 手写一个Shader类

在前面的教程中,我们的着色器都是以const char的数组形式来传递的。但是这有个很严重的问题,非常不方面着色器的编写!后期的学习中,我们大部份都需要编写很多着色器的代码,如果在这种环境下编写会非常不方便的。所以,我们可以在另外一个文本中编写着色器,然后用C++的输入流来读取这个文本(这个文本的格式可以是txt,也可以是其他任何格式,但为了方便管理,推荐使用glsl格式或者vsh和fsh格式)。看来写一个Shader读取编译器势在必行。

并且,为了方便管理,我们最好写一个Shader类,专门管理着色器。

定义Shader类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Shader{
public:
//着色器id
unsigned int id;

//构造函数,读取着色器并编译。接受两个参数,分别为顶点着色器和片元着色器的路径
Shader(const std::string &vertexShaderPath, const std::string &fragmentShaderPath);
//析构函数,回收内存
~Shader();
//使用着色器的函数
void use();
//Uniform变量设置函数
void setBool(const std::string &name, bool value) const;
void setInt(const std::string &name, int value) const;
void setFloat(const std::string &name, float value) const;
void setVector3(const std::string &name, float x, float y, float z) const;
void setVector3(const std::string &name, glm::vec3 vec) const;
void setVector4(const std::string &name, float x, float y, float z, float w) const;
void setVector4(const std::string &name, glm::vec4 vec) const;
void setMatrix3(const std::string &name, glm::mat3 mat3) const;
void setMatrix4(const std::string &name, glm::mat4 mat4) const;
};
Read more

OpenGL教程:3. 绘制一个矩形与EBO

上一节我们实现了一个三角形的绘制。现在思考下如何绘制一个矩形?因为OpenGL中最小的绘制片元是一个三角面片(不考虑点和线哦),所以答案是绘制两个三角形就是一个矩形了。

顶点数据

首先确定顶点的浮点数据:

1
2
3
4
5
6
7
8
float vertices[] = {
0.5f, 0.5f, 0.0f, // 右上角
0.5f, -0.5f, 0.0f, // 右下角
-0.5f, -0.5f, 0.0f, // 左下角
-0.5f, 0.5f, 0.0f, // 左上角
-0.5f, -0.5f, 0.0f, // 左下角
0.5f, 0.5f, 0.0f, // 右上角
};

因为是两个三角形,所以就有六个顶点。

VAO和VBO

然后定义矩形的vao和vbo,并解释数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//initialize vbo
unsigned int vbo;
glGenBuffers(1, &vbo); //spawn a new vbo
glBindBuffer(GL_ARRAY_BUFFER, vbo); //bind vbo with ARRAY_BUFFER
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices,
GL_STATIC_DRAW); //transport vertices data to buffer memory

//initialize vao
unsigned int vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

//set vertices pointer
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *) nullptr);
glEnableVertexAttribArray(0);
Read more

OpenGL教程:2. 绘制一个三角形

上一节我们使用了GLFW和GLAD。接下来我们来绘制三角形。在OpenGL中,最小绘制对象是三角面片。所有的对象都是由若干个三角面片组成的。绘制也比较简单,我们只需确定顶点以及其每个顶点的颜色就可以绘制了!

img

绘制过程如上,我们需要定义顶点的数据,然后交给六个着色器处理。其中顶点、集合和片段是我们可以人为自定义的阶段。着色器非常重要,他是运行在GPU的小程序。用于渲染图形。在OpenGL中,我们使用GLSL着色器语言。它类似于C语言,还是比较好上手的。

基本过程就是,定义顶点数据->顶点着色(绘制每个顶点的位置)->图元装配(根据绘制类型装配图元,后面会解释)->几何着色器->光栅化(确定图形的像素)->片元着色(绘制每个像素的颜色)->测试混合

所以,顶点着色器的对象是每个顶点,片元着色器的对象是每个像素!这点很重要。也就是说,我们会对每个顶点执行一次顶点着色器的程序,会对每个像素执行片元着色器。一般来说,像素的数目大于顶点的数目。所以片元着色器一般计算量会大于顶点着色器。

Read more

OpenGL教程:1. GLFW和GLAD的初始化

OpenGL是图形API,是一种规范。他作为最古老的图形API,无论是后起之秀DirectX和Vulkan,都遵循这种规范。

既然是一种API,那么他就是一种图形接口,供用户去实现一些图形的操作。具体来说,这一过程如下:

这说明,各大显卡厂商根据OpenGL制定相对应的显卡(不止是OpenGL,还有DirectX和Vulkan等图形API)。用户通过GLFW和GLAD“对接API”。最后才能实现真正的图形编程。可能你目前还看不懂这些术语,之后会好好解释的。

入门计算机图形学,需要有良好的数学基础,以及编码能力。我们主要采用C++语言编程OpenGL。需要说明的是,Python、Java和Golang都可以编程OpenGL,并且在这方面的语法是出奇的相似。建议挑选自己熟悉的语言学习。(但我仍然强烈推荐用C++,问就是效率高而且高自定义性)

最后,要强调的是,OpenGL是一个巨大的状态机,每一条gl的语句都是一种状态。这一点需要明确,这对后面对OpenGL代码的理解有着重要的作用。

Read more

在MacOS(针对Arm架构)里配置OpenGL编程环境(Clion)

安装brew包管理器

brew可以让管理库更加的方便,我们使用国内的镜像安装:

1
/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"

安装glfw3

利用brew包管理器:

1
brew install glfw

注意一点,如果采用的是arm架构的M系列芯片,brew会默认把所有的文件安装在/opt/homebrew/Cellar/的一个文件夹里。如果是x86架构,那就会在/usr/local/Cellar/。这里以M系列为例子。

不仅如此,brew 还会在/opt/homebrew/Cellar/的目录里建立一个目录软连接,这个soft link 指向了/opt/homebrew/Cellar/glfw/3.3.8/include 这个目录。这样子,GLFW的头文件就被包含在IDE默认搜索的路径下了。

Read more
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×