OpenGL ES on iOS --- 统一变量(Uniform)和统一变量块(UBO)

摘要:
首先,uniform是全局的。全局意味着uniform变量必须在每个着色器程序对象中都是独一无二的,而且它可以被着色器程序的任意着色器在任意阶段访问。提到UBO就必须要提到着色语言GLSL中的UniformBlocks,它将众多的Uniform类型的变量集中在一起进行统一的管理,对于需要大量Uniform类型变量的程序可以显著地提高性能。
简介

Uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式,但uniform和顶点属性有些不同。

首先,uniform是全局的(Global)。全局意味着uniform变量必须在每个着色器程序对象中都是独一无二的,而且它可以被着色器程序的任意着色器在任意阶段访问。
第二,无论你把uniform值设置成什么,uniform会一直保存它们的数据,直到它们被重置或更新。

单独统一变量

声明

uniform vec3 color

赋值

//获取指定统一变量的location
int vertexColorLocation = glGetUniformLocation(_program, "test");
//为vec3 的统一变量 赋值
glUniform3f(vertexColorLocation, 0.0f, 1.0f, 0.0f);

赋值函数是根据 统一变量类型的不同而调整的.其中函数名中包含数字(1、2、3、4)表示接受这个数字个用于更改uniform变量的值,i表示32位整形,f表示32位浮点型,ub表示8位无符号byte,ui表示32位无符号整形,v表示接受相应的指针类型(或者就是传入的是数组)。

glUniform1f(GLint locaation,GLFloat x) 表示 float类型
glUniform2f(GLint locaation,GLFloat x,GLFloat y) 表示 二位向量 分量类型为float
glUniform1fv(GLint locaation,GLSize count,const GLfloat* value) float类型指针
glUniformMatrix4x3(Glint location,GLsizei count,GLboolean transpose,const GLfloat* value) 表示为 4x3矩阵. 参数: transpose 表示是否采用 行优先顺序(GL_TRUE)

UBO

UBO(Uniform Buffer Object)是用来存储着色语言中Uniform类型变量的缓冲区对象,使用UBO可以让uniform变量在不同的着色语言程序中实现共用,也可以在着色语言程序中实现uniform类型变量的设置与更新。

提到UBO就必须要提到着色语言GLSL中的Uniform Blocks,它将众多的Uniform类型的变量集中在一起进行统一的管理,对于需要大量Uniform类型变量的程序可以显著地提高性能。(有点像全局版的VBO)

原理

OpenGL ES on iOS --- 统一变量(Uniform)和统一变量块(UBO)第1张
原理示意图.png

在显存中创建缓存对象(Buffer),在buffer中存储统一变量数据, 将Buffer与 指定的point绑定, 将统一变量缓冲区的索引 和 point绑定. 这样通过point 将变量 和 缓存 连接.

设置UBO

//统一变量块
layout (std140) uniform colorBlock{
    vec4 cc;
};
        GLuint blockid,bufferid;
        GLint blocksize;
        GLint point = 1;
        // 统一变量数据
        GLfloat blockData[] = {
            1.0f,1.0f,1.0f,1.0f
        };
        //获取统一变量块索引
        blockid = glGetUniformBlockIndex(_program, "colorBlock");
        //获取统一变量块大小
        glGetActiveUniformBlockiv(_program, blockid, GL_UNIFORM_BLOCK_DATA_SIZE, &blocksize);
        //将变量索引 和 point 绑定
        glUniformBlockBinding(_program, blockid, point);
        //创建与绑定缓冲区
        glGenBuffers(1, &bufferid);
        glBindBuffer(GL_UNIFORM_BUFFER, bufferid);
        //向缓冲区中赋值
        glBufferData(GL_UNIFORM_BUFFER, blocksize, blockData, GL_DYNAMIC_DRAW);
        //将UBO 和 point 绑定
        glBindBufferBase(GL_UNIFORM_BUFFER, point, bufferid);

修改UBO

        GLfloat uploadData[] = {
            0.0f,0.0f,1.0f,1.0f
        };
        // 绑定当然统一变量块的 buffer
        glBindBuffer(GL_UNIFORM_BUFFER, bufferid);
        //获取统一变量块 中 指定变量的 偏移量
        const GLchar *names[] = {"cc"};
        GLuint indices[1];
        glGetUniformIndices(_program, 1, names, indices);
        GLint offset[1];
        glGetActiveUniformsiv(_program, 1, indices, GL_UNIFORM_OFFSET, offset);
        glBufferSubData(GL_UNIFORM_BUFFER, offset[0], blocksize, uploadData);

函数补充

1, glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* const *uniformNames, GLuint* uniformIndices)
该函数用于获取统一变量块中 变量们的索引 参数:

program 程序对象
uniformCount 变量名称数组的元素数量
uniformNames 变量名称数组
uniformIndices 用于接受变量索引的数组

2,glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params)
该函数用于 通过变量索引 查询变量信息. 参数:

program 程序对象
uniformCount 变量数量
uniformIndices 变量索引数组
pname 表示要查询变量的那个属性 GL_UNIFORM_OFFSET(变量偏移量) GL_UNIFORM_SIZE(变量大小) GL_UNIFORM_NAME_LENGTH(变量名长度) GL_UNIFORM_TYPE(变量类型)....
params 接受查询结果的数组

注意

着色语言编译优化

如果你声明了一个uniform却在GLSL代码中没用过,编译器会静默移除这个变量,导致最后编译出的版本中并不会包含它.

UBO限定符

在UBO中,针对不同的限定符 还存在不同的字节补齐的情况.所以获取偏移量,大小最好还是通过查询进行,避免自己计算出现错误.

这是 std140(标准统一变量块布局)限定符的内存分配情况:

OpenGL ES on iOS --- 统一变量(Uniform)和统一变量块(UBO)第2张
std140布局.png

免责声明:文章转载自《OpenGL ES on iOS --- 统一变量(Uniform)和统一变量块(UBO)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇delphi 对应 c# 的一些函数及类型的转换方法【原】Sql高级操作下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

浅析Block闭包

浅析Block闭包 简单来说,block就是将函数及其上下文封装起来的对象,从功能上可以把它看作是C++中的匿名函数,也可称之为块。 Block类型写法: 返回值+(^块名)+(参数)= ^(参数){ 内容 } 如下所示: int (^myBlock)(int a, int b) = ^(int a, int b){ return a + b; }...

Maven环境变量配置

环境变量: 变量名:M2_HOME 变量值:D:apache-maven-3.2.2 变量名:Path 变量值:%M2_HOME%in; 检查:win + R,输入cmd 输入mvn -v,出现如下信息,则成功 C:UsersYJ>mvn -vApache Maven 3.2.2 (45f7c06d68e745d05611f7fd14efb659...

FORM开发笔记

1, 界面对行循环后在回到循环前的行 v_current_record number:=Get_Block_Property('block名称', Current_Record); --返回当前行号 go_record(v_current_record); --回到以前的当前行 2,Form中的系统变量,它存在于一个Form的整个运行时期的会话之中,变量包...

C++中extern关键字用法小结

总结C++中关于extern关键字的用法。 1.变量的生明和定义中 C++语言支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可被独立编译。为了将程序分为许多文件,则需要在文件中共享代码,例如一个文件的代码可能需要另一个文件中中定义的变量。 为了支持分离式编译,C++允许将声明和定义分离开来。变量的声明规定了变量的类型和名字,即使一个名字为程...

symfony中twig的模板变量与注释

程序会传递给模板若干变量,你需要在模板里输出他们。例如输出$hello 。1{{ hello }}。如果传递给模板的是对象或者数组,你可以使用点. 来输出对象的属性或者方法,或者数组的成员。或者你可以使用下标的方式。。1 {{ foo.bar }}。2 {{ foo[‘bar’] }}。如果你访问的值不存在就会返回null。TWIG有一整套的流程来确认值是...

IOS学习4——block代码块

本文转载自:iOS开发-由浅至深学习block 一、关于block 在iOS 4.0之后,block横空出世,它本身封装了一段代码并将这段代码当做变量,通过block()的方式进行回调。这不免让我们想到在C函数中,我们可以定义一个指向函数的指针并且调用: 1 bool executeSomeTask(void) { 2 //do somethin...