简介

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

OpenGL ES on iOS --- 统一变量(Uniform)和统一变量块(UBO)的更多相关文章

  1. WebGL 在 OpenGL ES 指令 iOS 在 C 分歧版指令分析

    WebGL 中 OpenGL ES 指令与 iOS 中 C 版指令的差异简析 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途 ...

  2. 通过OpenGL ES在iOS平台实践增强现实

    http://www.cnblogs.com/elvisyzhao/p/3398250.html 本文采用OpenGL ES 1固定渲染管线实现,目标为在设备拍摄到的现实世界中,绘制世界坐标轴,并根据 ...

  3. 通过OpenGL ES在iOS平台实践增强现实(一)

    http://ios.9tech.cn/news/2013/1108/38495.html 1.本文采用OpenGL ES 1固定渲染管线实现,目标为在设备拍摄到的现实世界中,绘制世界坐标轴,并根据设 ...

  4. 通过OpenGL ES在iOS平台实践增强现实(二)

    上一篇讲到如何使用OpenGL ES绘制一个3D场景,这一篇我们会配合使用iOS提供的CoreMotion框架把虚拟世界中的摄像机的位置朝向和设备实际的位置朝向绑定起来.本文还对防抖做了处理. 首先说 ...

  5. 【转载】OpenGL ES 三种类型修饰 uniform attribute varying

    其实attribute varying已经被in和out代替了,但是有些工程代码里面仍然还在,所以权当笔记好了. 1.uniform变量uniform变量是外部application程序传递给(ver ...

  6. OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章)和varying,uniform,attribute修饰范围

    OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章)   所有变量和函数在使用前必须声明.变量和函数名是标识符. 没有默认类型,所有变量和函数声明必须包含一个声明类型以及可选的修饰符. ...

  7. iOS 中OpenGL ES 优化 笔记 1

    1,避免同步和Flushing操作 OpenGL ES的命令执行通常是在command buffer中积累一定量的命令后,再做批处理执行,这样效率会更高:但是一些OpenGL ES命令必须flush ...

  8. OpenGL ES应用开发实践指南:iOS卷

    <OpenGL ES应用开发实践指南:iOS卷> 基本信息 原书名:Learning OpenGL ES for iOS:A Hands-On Guide to Modern 3D Gra ...

  9. OpenGL ES for Android

    经过半年的准备OpenGL ES for Android系列文章终于要和大家见面了,在这里定一个小目标-先吸引1000个粉丝,万一实现了呢.写关于OpenGL ES的文章开始是有一些犹豫的,因为Ope ...

随机推荐

  1. 关于async await的测试

    async await的教程:https://www.cnblogs.com/zhaoshujie/p/11192036.html 异步方法: private async Task<string ...

  2. gd库的相关内容

    gd库注意事项 对于乱码问题 在php里面包含 header("content-type:image/png"); 这样输出的图像就不会乱码了后面跟的Png也可以改变为自己想要输出 ...

  3. 海量无损高音质音乐文件分享180TB(持续更新)

    海量无损高音质音乐文件分享180TBWAV,flac,ape格式(持续更新),由于本人是音乐发烧爱好者,收集海量的无损音乐,已经分类好了,比较方便查找,但是本地没法存储,所有放在网盘中,并且我这边还会 ...

  4. 粒子系统与雨的效果 (DirectX11 with Windows SDK)

    前言 最近在学粒子系统,看这之前的<<3D图形编程基础 基于DirectX 11 >>是基于Direct SDK的,而DXSDK微软已经很久没有更新过了并且我学的DX11是用W ...

  5. CSS History

    Preface 如果只是要写程序,那的确是不需要这么麻烦,上来直接看Syntax,动手写上至少300行代码,做上3个应用程序,这门语言你也就差不多会用了,接下来不过就是模式,特殊的地方以及记住一些函数 ...

  6. 学习笔记:oracle学习二:oracle11g数据库sql*plus命令之数据库交互、设置运行环境

    目录 1.SQL*PLUS与数据库的交互 2.设置sql*plus运行环境 2.1 set命令简介 2.2 使用set命令设置运行环境 2.2.1 pagesize变量 2.2.2 NEWPAGE变量 ...

  7. SrpingBoot入门到入坟03-基于idea快速创建SpringBoot应用

    先前先创建Maven项目然后依照官方文档再然后编写主程序写业务逻辑代码才建立好SpringBoot项目,这样太过麻烦,IDE都支持快速创建,下面基于idea: 使用Spring Initializer ...

  8. recover函数捕获异常

    package main import ( //"fmt" "time" ) func test () { var m map[string]int m[&qu ...

  9. base全家桶的安装使用方法

    base编码是Binary-to-text encoding的一种实现方法,它可以把二进制数据(含不可打印的字符)编码成可打印字符序列. 本文会不定时收录“base全家桶”:base64.base32 ...

  10. python03-break、continue、for循环、数据bytes类型、字符串与字节的关系、变量指向与深浅拷贝、set集合、文件操作

    目录: 1.break.continue 2.for循环 3.数据bytes类型 4.字符串与字节的关系 5.变量指向与深浅拷贝 6.set集合 7.文件操作 一.break.continue bre ...