OpenGL 着色器详解

1. GLSL语言

glsl语言是用来编写着色器的,通过一段一段包含main函数的程序片段,告诉渲染引擎怎么去渲染内容。

glsl语言的语法有点类似c语言风格,只是增加了一些特有的关键字来修饰变量,下面是一个着色器基本的程序结构:

首先声明的是GLSL的版本号和模式,然后就是声明变量。像其他语言一样,声明变量我们要包括数据类型和变量名两个部分。而在GLSL中,我们还要指定变量的类型。

  • in,通过in关键字来声明,现在声明的变量是一个输入变量。
  • out,对应的out关键字表明这是一个输出变量。
  • uniform,而uniform就比较厉害了,他代表生成的变量是一个全局变量。

最后一部分就是主函数main。我们在这里处理输入输出值。

2. 输入变量in

首先我们可以定义的输入变量的个数是有限的,这一般取决于硬件,但OpenGL至少还是会为我们保留16个输入变量可用。我们可以查询GL_MAX_VERTEX_ATTRIBS来获取具体的上限:

3. 输出变量out

由于片段着色器直接输出色值交个显卡渲染,下一个阶段不会对色值进行处理,所以我们生成的输出变量无需与下一个阶段产生联系。但是试想一下,如果我们在顶点着色器中,想传递一个参数给片段着色器怎么办呢?**我们要建立起输入变量和输出变量间的关系。**怎么建立呢,GLSL给了我们一个很简单的方式来建立联系,一致的数据类型及变量名称即可。

顶点着色器

片段着色器

4 . 全局变量

全局的作用范围作用于整个着色器程序上。也就是你把带有全局变量x的着色器源码编译在着色器A上,再把A添加到着色器程序B上,那么B中的所有着色器都可以使用变量x。并且在GL编码中,也可以通过对应的着色器程序获取到指定的全局变量x。

这里我们仅提供一个在片段着色器中使用全局变量的示例:

片段着色器

渲染循环

5. 数据类型

向量

向量重组

6. glVertexAttribPointer

这是一个设置顶点变量属性的函数,通过它可以设置步长,偏移量和位置

顶点数据

顶点着色器

片段着色器

我们看到,顶点着色器中,我们声明了两个输入变量。一个代表位置,一个代表颜色。然后我们要把颜色值传给片段着色器,所以要声明一个输出变量,在片段着色器中在声明一个以一样的输入变量,如此,颜色也就从顶点着色器传到片段着色器中了。

着色器配置完成,我们还要设置顶点数据的属性。

7. Shader Class

一个着色器程序就是一个最小的绘制单元。其绘制结果直接取决于两个着色器。基于面向对象的思想,我们希望对其进行封装。

我们来梳理一下加载着色器的代码:

创建着色器对象->附加着色器源码并编译->创建着色器程序->绑定着色器->链接着色器

基于上述过程,我们封装了一下着色器程序的类:

复制代码
  1 #ifndef Shader_hpp
  2 #define Shader_hpp
  3 
  4 #include <glad/glad.h>
  5 #include <GLFW/glfw3.h>
  6 #include <string>
  7 #include <fstream>
  8 #include <sstream>
  9 #include <iostream>
 10 
 11 class Shader {
 12     public:
 13     ///着色器程序ID
 14     unsigned int ID;
 15     ///构造器读取着色器
 16     Shader(const GLchar * vertexPath,const GLchar * fragmentPath) {
 17         std::string vertexCode;
 18         std::string fragmentCode;
 19         std::ifstream vShaderFile;
 20         std::ifstream fShaderFile;
 21         // ensure ifstream objects can throw exceptions:
 22         vShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
 23         fShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
 24         try
 25         {
 26             ///打开文件
 27             vShaderFile.open(vertexPath);
 28             fShaderFile.open(fragmentPath);
 29             std::stringstream vShaderStream, fShaderStream;
 30             ///读取文件
 31             vShaderStream << vShaderFile.rdbuf();
 32             fShaderStream << fShaderFile.rdbuf();
 33             ///关闭文件
 34             vShaderFile.close();
 35             fShaderFile.close();
 36             ///获取源码
 37             vertexCode   = vShaderStream.str();
 38             fragmentCode = fShaderStream.str();
 39         }
 40         catch (std::ifstream::failure e)
 41         {
 42             std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
 43         }
 44         ///获取c字符串
 45         const char* vShaderCode = vertexCode.c_str();
 46         const char * fShaderCode = fragmentCode.c_str();
 47         ///编译
 48         unsigned int vertex, fragment;
 49         ///顶点着色器
 50         vertex = glCreateShader(GL_VERTEX_SHADER);
 51         glShaderSource(vertex, 1, &vShaderCode, NULL);
 52         glCompileShader(vertex);
 53         checkCompileErrors(vertex, "VERTEX");
 54         ///片段着色器
 55         fragment = glCreateShader(GL_FRAGMENT_SHADER);
 56         glShaderSource(fragment, 1, &fShaderCode, NULL);
 57         glCompileShader(fragment);
 58         checkCompileErrors(fragment, "FRAGMENT");
 59         ///着色器程序
 60         ID = glCreateProgram();
 61         glAttachShader(ID, vertex);
 62         glAttachShader(ID, fragment);
 63         glLinkProgram(ID);
 64         checkCompileErrors(ID, "PROGRAM");
 65         ///释放着色器
 66         glDeleteShader(vertex);
 67         glDeleteShader(fragment);
 68     }
 69     
 70     ///激活主色器程序
 71     void use() {
 72         glUseProgram(ID);
 73     }
 74     
 75     ///uniform setter
 76     void setBool(const std::string &name ,GLboolean value) const {
 77         glUniform1i(glGetUniformLocation(ID,name.c_str()),(GLint)value);
 78     }
 79     void setInt(const std::string &name ,GLint value) const {
 80         glUniform1i(glGetUniformLocation(ID,name.c_str()),value);
 81     }
 82     void setFloat(const std::string &name ,GLfloat value) const {
 83         glUniform1f(glGetUniformLocation(ID,name.c_str()),value);
 84     }
 85     void setVec4f(const std::string &name ,GLfloat x,GLfloat y,GLfloat z,GLfloat w) const {
 86         glUniform4f(glGetUniformLocation(ID,name.c_str()),x,y,z,w);
 87     }
 88     
 89 private:
 90     ///检查编译错误
 91     void checkCompileErrors(unsigned int shader, std::string type)
 92     {
 93         int success;
 94         char infoLog[1024];
 95         if (type != "PROGRAM")
 96         {
 97             glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
 98             if (!success)
 99             {
100                 glGetShaderInfoLog(shader, 1024, NULL, infoLog);
101                 std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
102             }
103         }
104         else
105         {
106             glGetProgramiv(shader, GL_LINK_STATUS, &success);
107             if (!success)
108             {
109                 glGetProgramInfoLog(shader, 1024, NULL, infoLog);
110                 std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
111             }
112         }
113     }
114 };
115 
116 #endif /* Shader_hpp */
相关推荐
扶尔魔ocy3 天前
【qt openGL入门笔记】windows编译MinGW版本的osgearth(2.10.1)
qt·opengl·osg
扶尔魔ocy4 天前
【QT OpenGL】知识点编目及传送门
qt·opengl·osg
扶尔魔ocy17 天前
【qt openGL入门笔记】OSG实现飞机模型在网格图上飞行并进行态势标绘(四)
qt·opengl·osg
:mnong18 天前
Web 三维可视化技术对比:ParaView Web vs 本项目 wasm + Three.js
前端·webgl·opengl·opencl·科学可视化
扶尔魔ocy19 天前
【qt openGL入门笔记】OSG实现显示飞机模型飞行的点迹(二)
qt·opengl·osg
扶尔魔ocy20 天前
【qt openGL入门笔记】OSG实现飞机模型在网格图上飞行(三)
opengl·osg
扶尔魔ocy20 天前
【qt openGL入门笔记】OSG实现飞机模型在网格图上飞行
qt·opengl·osg
扶尔魔ocy24 天前
【qt openGL入门笔记】FPS相机
qt·opengl
扶尔魔ocy24 天前
qt openGL入门笔记】FPS相机和轨道相机
qt·opengl
扶尔魔ocy1 个月前
【qt openGL入门笔记】基础光照
qt·opengl