zoukankan      html  css  js  c++  java
  • OpenGL ES on iOS --- 统一变量(Uniform)和统一变量块(UBO)

    简介

    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)

    原理

    原理示意图.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(标准统一变量块布局)限定符的内存分配情况:

    std140布局.png
  • 相关阅读:
    第四周助教小结 北软
    第二周工作小结 北软
    第六周助教小结 北软
    第七周周小结 北软
    第八周周小结 北软
    几句话了解元数据(Metadata)
    App测试点(二)
    Pytest单元测试
    UnitTest单元测试
    【模板】单源最短路径
  • 原文地址:https://www.cnblogs.com/dongguolei/p/11495301.html
Copyright © 2011-2022 走看看