| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> 【Overload游戏引擎】源码分析之六:OvRendering函数库(四) -> 正文阅读 |
|
[游戏开发]【Overload游戏引擎】源码分析之六:OvRendering函数库(四) |
2021SC@SDUSC 目录 本章我们继续来讲OvRendering中与shader(着色器)有关的函数。 1.Uniform首先我们来介绍一下什么是uniform。 uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式,但uniform和顶点属性有些不同。 首先,uniform是全局的(Global)。 全局意味着uniform变量必须在每个着色器程序对象中都是独一无二的,而且它可以被着色器程序的任意着色器在任意阶段访问。 第二,无论你把uniform值设置成什么,uniform会一直保存它们的数据,直到它们被重置或更新。 总之,uniform对于设置一个在渲染迭代中会改变的属性是一个非常有用的工具,它也是一个在程序和着色器间数据交互的很好工具。 了解了uniform之后,我就来看与它相关的一些数据定义,其中包含了shader类中将会使用的结构体和枚举值。 1.1UniformType这个枚举类中列出来一个uniform可以使用的数据类型:
1.2UniformInfo在这个结构体中,使用UniformType定义数据类型,之后定义了uniform的变量名称与着色器位置,其中std::any能够接收任意类型的单值数据。
2.Shader了解了以上内容后,我们进入本文的正题。 我们可以看到,原本的作用域中嵌套定义了一个命名空间Loader,其中包含以一个ShaderLoader类,这个类将会在以后的文章中提及,它将作为Shader类的友元类。
接下来我们来看它的成员变量,其中共有变量包括一个uint32_t型的着色器ID,一个string型的路径名称,依旧一个UniformInfo类型的向量。前两个变量用于指定着色的唯一标识与位置,所以不可以更改。 然后私有变量定义了一个无向图类型的uniform位置缓冲,具体的作用将在下文提到。
在Shader的构造函数中,它将两个常量变量初始化,然后调用了一个私有函数QueryUniforms(),这个函数我们将在下文来分析。
2.1SetUniform和GetUniformShader类中的函数主要分为2大类:设置uniform和获取uniform,接下来我们将用int型数据来举例,其他类型的函数可以以此类推: SetUniformInt(const std::string& p_name, int p_value):
glUniform1i()是OpenGL内置的设置uniform的函数,函数的后缀表示传递数据的个数+传递数据的类型的首字母,就像本例中传递了1个int型数据,函数的后缀就是1i,其余情况下也可以是2i、1f、2f等,就像下列函数这样:
但是,在这里还有个特殊的存在就是矩阵。当传递的数据时矩阵时,函数的结构也会发生细微的改变,我们可以看到在下列代码中,函数的后缀是“Matrix4fv”,它由Matrix+传递数据的个数+传递数据的类型的首字母+vector首字母组成,表示传递1个4×4的浮点型矩阵(使用v作后缀的glUniform函数时,只能传入4维向量)。
接下来我们统一来讲glUniform的传入参数,对于所有的glUniform来说,第一个参数都是对应着色器中变量的位置。在这里它调用了GetUniformLocation()函数,该函数可以通过一个字符串来查找对应的着色器变量,同时返回该着色器变量的位置。 对于大部分glUniform函数来说,它的其余参数只是将要传递的数据按序传入,但是在glUniformMatrix4fv中却发生了变化,它的第二个参数表示传入的矩阵个数,第三个参数指明矩阵是列优先(column major)矩阵(GL_FALSE)还是行优先(row major)矩阵(GL_TRUE),最后一个参数是矩阵首个元素的引用。 由于uniform是全局操作,所以所有名称相同的变量都会接收传递的数据。 GetUniformInt(const std::string& p_name):
GetUniform函数与前者殊途同归,同样调用了OpenGL的内置函数glGetUniformiv,它会比glUniformiv多出一个id用于访问当前的shader,然后通过变量名查找变量的位置,将变量中的数据传给第三个参数的引用,由此可以实现从GPU到CPU的数据传递。 讲完了以上内容,我们回来看QueryUniforms()函数的具体实现。
在函数开头,一共完成了4件事: 1.初始化numActiveUniforms 指明激活的uniform的数目; 2.将Shader类中的uniforms变量清空; 3.利用glGetProgramiv函数返回当前id的shader激活的uniform的数目; 4.定义长度为256的GLchar型数组。 在完成了以上操作后,进入了一个for循环,遍历每一个uniform。在这里涉及到1个重要的函数 void?glGetActiveUniform(GLuint?program,GLuint?index,GLsizei?bufSize,GLsizei *length,GLint *size,GLenum *type,GLchar *name)。
id:指定要查询的shader对象的id; unif:指定要查询的shader中uniform变量的索引; &nameData[0]:返回包含uniform变量名称的,以null结尾的字符串; static_cast<GLsizei>(nameData.size()):指定允许OpenGL在由name指示的字符缓冲区中写入的最大字符数; &actualLength:如果传递NULL以外的值,则返回由name指示的字符串中的OpenGL实际写入的字符数(不包括空终止符); &arraySize:返回shader中uniform变量的大小; &type:返回shader中uniform变量的数据类型。 之后,用nameData与actualLength构建字符串name,包含当前uniform变量的名称。 完成以上任务后,函数进行if判断,返回是否name中包含字符串‘ubo_’,是返回True。
之后,定义一个any类型的默认值变量defaultValue,并将name的类型转化为非静态的UniformType类型。 接着,对name的类型进行switch判定,在每一个case中,用GetUniform函数获取name对应的uniform变量中的数据,并传入defaultValue中。
最后,判断defaultValue是否非空,若defaultValue存入数据,则构造一个UniformInfo结构体并存入向量uniforms中,然后进入下一个循环。 除了上述几个函数后,Shader类中剩余的几个功能函数,它们在上述的函数中出现过,我们在此简单看看。 2.2GetUniformLocation
函数传入了一个uniform变量名,并通过这个变量名在m_uniformLocationCache中查找对应的key(关键字),并返回一个迭代器与m_uniformLocationCache末尾的迭代器(即空指针)对比。 若两者不相等,证明name存在,则返回m_uniformLocationCache中name对应的路径; 若name不存在,在调用OpenGL内置函数glGetUniformLocation,获取name对应的路径,若路径为-1则报错,最后将路径的值传入m_uniformLocationCache中以name为关键字的节点。 2.3GetUniformInfo(const std::string& p_name) const
该函数用于获取uniform的信息,它的关键在于std::find_if,它的定义如下:
第一个参数是头迭代器,第二个参数是末尾迭代器,最后一个参数p是一个可调用对象。 我们可以将p定义为一个函数,find_if将会在每一个for循环中调用p对象,其中[……]中传入外界参数,(……)中定义函数内部变量。 在本例中,p函数传入外界参数p_name,并定义一个UniformInfo迭代器p_element的引用,将p_element中的name值与我们传入的p_name比较,将比较结果返回find_if: [&p_name](const UniformInfo& p_element) 若两者对比的结果相同,则find_if会返回当前的迭代器,并存入found。 若found等于uniforms的末尾的迭代器(即空指针),则表示为找到name对应的uniform变量;反之则返回name对应的迭代器。 以上就是本章的全部内容。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 22:24:31- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |