《OpenGL宝典》--统一变量

统一变量

[layout (location = 0)] uniform float f = 1.0f;

若设置layout,则不需要使用glGetUniformLocation来获取统一变量的位置

使用glUniform*传递值,glUniformMatrix*()设置矩阵统一变量。

glUseProgram(myShader);
glUniform1f(0,45.2f);//0为location = 0的数据位置
glUniform4fv(iColorLocation , 1, vColor);
glUniformMatrixfv(proj_location, 1, GL_FALSE, proj_matrix);

一致区块

为了降低glUniform*的调用成本,更容易在不同应用程序之间共享一系列统一变量。
这种功能称为统一变量缓冲对象。

uniform Block{
	...data
}block1;

数据布局

标准布局std140

标准布局的布局方式与c、c++的结构体的布局方式相同。在传递数据时,使用相同结构的结构体整体传递即可。

align限定符可用于整个区块以强制所有成员对齐到指定边界。如下,bar的偏移量为8,符合vec2的偏移规则,但align设置为16,则bar强制对齐边界为16的倍数,故,offset = 8会被

layout(std140, align = 16) uniform Block
{
	layout (offset = 32) vec4    foo;
	layout (offset = 8)  vec2    bar;
	layout (offset = 48) vec3    baz;
}

报错:offset只能递增,不能随机设置
在这里插入图片描述
修改如下

layout(std140,align = 16) uniform manuallyLaidOutBlock
{
    layout (offset = 8)  vec2    bar;
    layout (offset = 32)  vec4    foo;
	layout (offset = 48)  vec3    baz;
}myBlock;

获取一致区块的信息

const GLchar* unifromName = "manuallyLaidOutBlock.bar";
GLuint uniformindex = -1;
glGetUniformIndices(nanosuitShader.ID, 1, &unifromName, &uniformindex);//获取bar的索引
GLint uniformOffset = -1;
glGetActiveUniformsiv(nanosuitShader.ID,1,&uniformindex,GL_UNIFORM_OFFSET,&uniformOffset);//siv---系统信息显示
cout << uniformOffset << " " << endl;

uniformOffset保存了manuallyLaidOutBlock.bar的偏移量,输入如下:
在这里插入图片描述
进一步说明了align = 16的作用。

共享布局shared

利用shared布局,可以使缓存中的数据根据OpenGL确定的最佳运行性能和最佳着色器访问进行布局。但必须获取区块信息。
通过glGetActiveUniformsiv()查询的统一变量参数类型,可查看书P84页。

之后便可在内存构建一致区块,然后使用glBufferSubData()将其加载到缓存或glMapBufferRange()获取内存指针,并直接将数据组装到该内存。

统一变量绑定

方法一

程序中每一个一致区块都有一个分配了编译程序的索引。
获取程序中一致区块的索引,可以调用:

GLuint glGetUniformBlockIndex(GLuint program, const GLchar * uniformBlockName);

为一致区块赋予绑定点,调用:

void glUniformBlockBinding(	GLuint program,
							GLuint uniformBlockIndex,//要赋予绑定点的一致区块索引
							GLuint uniformBlockBinding);//一致区块绑定点的索引			

可使用glGetintegerv()获取绑定点数量上限,glGetintegerv()其他功能见P86页。
OpenGL保证一致区块至少为64K,至少可以在一个程序中引用14个区块。

方法二

直接在着色器中设置binding

layout(std140, align = 16, binding = 2) uniform manuallyLaidOutBlock
{
    layout (offset = 8)  vec2    bar;
    layout (offset = 32)  vec4    foo;
	layout (offset = 48)  vec3    baz;
}myBlock;

将缓存绑定到绑定点

glBindBufferBase(GL_UNIFORM_BUFFER,index,buffer);

GL_UNIFORM_BUFFER指定绑定点为统一变量。
index绑定点的索引
buffer想要绑定的缓存对象的名称

补充

std140结构与c++结构体struct结构的不同???

std140结构如下

layout(std140,binding = 0) uniform manuallyLaidOutBlock
{
    vec2    bar;//0
    vec4    foo;//16
	vec3    baz;//32
}myBlock;

使用函数调用查看std140数据偏移量

//查看std140结构内部数据排列
    int uniformn = 3;
    const GLchar* unifromName[4] = { "manuallyLaidOutBlock.bar" ,
                                     "manuallyLaidOutBlock.foo" ,
                                     "manuallyLaidOutBlock.baz" ,
                                     ""};
    GLuint uniformindex[4];
    glGetUniformIndices(shader.ID, uniformn, unifromName, uniformindex);//获取bar的索引
    GLint uniformOffset[4];
    glGetActiveUniformsiv(shader.ID, uniformn,uniformindex,GL_UNIFORM_OFFSET,uniformOffset);//siv---系统信息显示
    for (int i = 0; i < uniformn; i++) {
        cout << uniformOffset[i] << " " << endl;
    }

c++结构体struct结构如下

 struct Block {
        glm::vec2    bar;//0
        glm::vec4    foo;//8
        glm::vec3    baz;//24
    }block;

使用函数调用查看struct数据偏移量

	 cout << offsetof(Block, bar) << " " << endl;
     cout << offsetof(Block, foo) << " " << endl;
     cout << offsetof(Block, baz) << " " << endl;

输出

在这里插入图片描述
可以看出,structstd140两种区块结构中的各数据的偏移量不同。可能与glm::vec4与GLSL中的vec4表达方式不同有关。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Elsa的迷弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值