OpenGL深入探索——OpenGL/GLSL数据传递小记(3.x) 【包含UBO详解】
【摘要】
OpenGL/GLSL规范在不断演进着,我们渐渐走进可编程管道的时代的同时,崭新的功能接口也让我们有点缭乱的感觉。本文再次从OpenGL和GLSL之间数据的传递这一点,记录和介绍基于OpenGL3.x的新方式,也会适时介绍Unform Buffer Objecct(UBO)这一重要特性。——ZwqXin.com
本文可视为大致一...
1. attribute变量
-
glsl3.x代码 (Vertex Program)
-
#version 330
-
-
layout(location = 0) in vec3 attrib_position;
-
layout(location = 1) in vec2 attrib_texcoord;
-
layout(location = 2) in vec3 attrib_normal;
-
layout(location = 3) in int attrib_clustercount;
废弃 in/out 用于显式标明该变量的一些布局属性
2.uniform变量
-
glsl代码
-
#version 330
-
-
uniform sampler2D basetex1;
-
uniform float fAlphaRestrictVal;
-
uniform mat4 matModel;
-
uniform mat4 matView;
-
uniform mat4 matProj;
glGetUniformLocation 麻烦
glUseProgram glUseProgram glProgramUniform glUniform glUseProgram glProgramUniform glUseProgram
大量的 上限值 MD5模型的格式、导入与顶点蒙皮式骨骼动画II ] TBO 一维纹理的Buffe
Uniform Buffer Object(UBO)
学一学,VBO
-
glsl代码
-
#version 330
-
-
layout(std140) uniform matVP
-
{
-
mat4 matProj;
-
mat4 matView;
-
};
Interface block
-
OpenGL代码
-
GLint nMatVPBlockIndex = glGetUniformBlockIndex(nProgramHandler, "matVP");
-
-
//GLint nMatVPBlockIndex = glGetProgramResourceIndex(nProgramHandler, GL_UNIFORM_BLOCK, "matVP");
-
-
if (GL_INVALID_INDEX != nMatVPBlockIndex)
-
{
-
GLint nBlockDataSize = 0;
-
-
glGetActiveUniformBlockiv(nProgramHandler, nMatVPBlockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &nBlockDataSize);
-
-
glGenBuffers(1, &m_nUBO);
-
-
glBindBuffer(GL_UNIFORM_BUFFER, m_nUBO);
-
-
glBufferData(GL_UNIFORM_BUFFER, nBlockDataSize, NULL, GL_DYNAMIC_DRAW);
-
-
glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_nUBO, 0, nBlockDataSize);
-
-
glUniformBlockBinding(nProgramHandler, nMatVPBlockIndex, 0);
-
-
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
-
}
glGetUniformBlockIndex glGetProgramResourceIndex glGetActiveUniformBlockiv
把它们都关联到同一个uniform buffer binding-point glBindBufferBase glBindBufferRange glUniformBlockBinding
binding-point 这个中间物件保存着能够直达具体某个UBO数据区的“方式”(不妨暂假想为该数据区的起始显存地址、长度等)
36 glBindBufferBase/glBindBufferRange glUniformBlockBinding glUniformBlockBinding
乱弹纪录IV:Transform Feedback ] Transform Feedback Buffer
单个UBO多个uniform-block 每个uniform block对应该UBO存储区域中不同的分区域 glBindBufferRange
-
OpenGL代码
-
GLint nMatVPBlockIndex = glGetUniformBlockIndex(nProgramHandler, "matVP");
-
-
GLint nCloudScaleIndex = glGetUniformBlockIndex(nProgramHandler, "Scale");
-
-
if (GL_INVALID_INDEX != nMatVPBlockIndex && GL_INVALID_INDEX != nCloudScaleIndex)
-
{
-
int nUniformBufferAlignSize = 0;
-
-
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &nUniformBufferAlignSize);
-
-
GLint nBlockDataSize1 = 0, nBlockDataSize2 = 0;
-
-
glGetActiveUniformBlockiv(nProgramHandler, nMatVPBlockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &nBlockDataSize1);
-
-
glGetActiveUniformBlockiv(nProgramHandler, nCloudScaleIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &nBlockDataSize2);
-
-
glGenBuffers(1, &m_nUBO);
-
-
glBindBuffer(GL_UNIFORM_BUFFER, m_nUBO);
-
-
glBufferData(GL_UNIFORM_BUFFER, nUniformBufferAlignSize + nBlockDataSize2, NULL, GL_DYNAMIC_DRAW);
-
-
glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_nUBO, 0, nBlockDataSize1);
-
-
glUniformBlockBinding(nProgramHandler, nMatVPBlockIndex, 0);
-
-
glBindBufferRange(GL_UNIFORM_BUFFER, 1, m_nUBO, nUniformBufferAlignSize, nBlockDataSize2);
-
-
glUniformBlockBinding(nProgramHandler, nCloudScaleIndex, 1);
-
}
同一个UBO的两个区域 数据对齐 记住了,block与block的数据不是紧紧pack在一起的
单个uniform-block里面的数据,也有字节对齐的机制
packed、shared、std140
【UBO的一个最显眼的好处就是实现数据共享。譬如我上面的matPV这个uniform block就是最好的例子:通常渲染场景时,只会有一个视图矩阵和一个投影矩阵([[乱弹OpenGL中的矩阵变换(上)] [乱弹OpenGL中的矩阵变换(下)] ),而且它们相对每一帧都是固定数据。而我们可能场景里物件用到的Shader不一样,但它们都得通过这两个矩阵计算最终的顶点输出啊?以前的话,我得每个Shader都传一次这些相同的矩阵数据,不仅时间上glUniform族函数会比较多而且空间上也分别占每个ShaderProgram本身的同等的存储资源。如今把它们统一在一个UBO中,每帧更新就只要更新UBO一次就可以了,而且也只占一份的资源空间(在显存上)。】
而shared(顺带一提,这个是默认layout)与std140不同之处在于 首选这类std
-
glsl代码
-
layout(std140) uniform matVP
-
{
-
float elapsedTime;
-
mat4 matProj;
-
mat4 matView;
-
};
-
layout(std140) uniform Scale
-
{
-
uniform float cloudScale;
-
};
-
C++代码
-
{
-
//Render
-
glBindBuffer(GL_UNIFORM_BUFFER, m_nUBO);
-
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GLfloat), &fElapsed);
-
-
//current std140 alignment(for base sclaer): 16
-
glBufferSubData(GL_UNIFORM_BUFFER, 16, sizeof(Matrix16), m_mtProj.mt);
-
glBufferSubData(GL_UNIFORM_BUFFER, 16 + sizeof(Matrix16), sizeof(Matrix16), m_mtView.mt);
-
-
//GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: 256
-
glBufferSubData(GL_UNIFORM_BUFFER, 256, sizeof(GLfloat), &fCScale);
-
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
-
}
两个重要优 glUniform
glUniform/glProgramUniform
3.varying变量
glShadeModel 需要光栅化时传入参数GL_SMOOTH,不需要时传入GL_FLAT
乱弹纪录I:Geometry Shader glProvokingVertex
flat
-
glsl代码
-
//vertex shader or geometry shadr
-
flat out float visibility;
-
-
//fragment shader
-
flat in float visibility;
乱弹纪录I:Geometry Shader ] 一个ShaderProgram中不能有两个同为输入的同名varing变量 也不能有两个同为输出的同名varing变量存在
-
glsl代码
-
//Vertex Shader
-
out vec2 varying_vg_texcoord;
-
-
//Geometry Shader
-
in vec2 varying_vg_texcoord[];
-
out vec2 varying_gf_texcoord;
-
-
//Fragment Shader
-
in vec2 varying_gf_texcoord;
interface block
-
//Vertex Shader
-
out Varying
-
{
-
vec2 texcoord;
-
}VaryingOut;
-
-
//Geometry Shader
-
in Varying
-
{
-
vec2 texcoord;
-
}VaryingIn[];
-
-
out Varying
-
{
-
vec2 texcoord;
-
}VaryingOut;
-
-
//Fragment Shader
-
in Varying
-
{
-
vec2 texcoord;
-
}VaryingIn;
-
glsl代码
-
//Geometry Shader Example
-
void main(void)
-
{
-
for(int i = 0; i < gl_in.length(); ++i)
-
{
-
gl_Position = gl_in[i].gl_Position;
-
-
VaryingOut.texcoord = VaryingIn[i].texcoord;
-
-
EmitVertex();
-
}
-
EndPrimitive();
-
}
-
glsl代码
-
//Geometry Shader Example
-
out Varying
-
{
-
vec3 position;
-
int cloudcount;
-
vec3 dimension;
-
}VaryingOut;
乱弹纪录IV:Transform Feedback
-
C++代码
-
//OpenGL Code Example
-
const GLchar *varyingOutCloudFeed[] = {"Varying.position", "Varying.cloudcount", "Varying.dimension"};
-
glTransformFeedbackVaryings(m_CloudFeedShader.GetProgramHandler(), 3, varyingOutCloudFeed, GL_SEPARATE_ATTRIBS);
-
m_CloudFeedShader.Link();
4.fragmentShader输出
学一学,FBO MRT glBindFragDataLocation
-
glsl代码 (fragemnt shader)
-
//单输出
-
layout(location = 0) out vec4 fragColor;
-
-
//MRT
-
layout(location = 0) out vec4 fragColor0;
-
layout(location = 1) out vec4 fragColor1;
layout里的关键字其实还有个index
-
glsl代码 (fragemnt shader)
-
layout(location = 0, index = 0) out vec4 fragColor;
-
layout(location = 0, index = 1) out vec4 src1Color;
-
C++代码
-
glEnable(GL_BLEND);
-
glBlendFunc(GL_SRC_ALPHA, GL_SRC1_COLOR);
文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。
原文链接:panda1234lee.blog.csdn.net/article/details/51498303
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)