OpenGL深入探索——OpenGL/GLSL数据传递小记(3.x) 【包含UBO详解】

举报
ShaderJoy 发表于 2021/12/30 01:53:03 2021/12/30
【摘要】 OpenGL/GLSL规范在不断演进着,我们渐渐走进可编程管道的时代的同时,崭新的功能接口也让我们有点缭乱的感觉。本文再次从OpenGL和GLSL之间数据的传递这一点,记录和介绍基于OpenGL3.x的新方式,也会适时介绍Unform Buffer Objecct(UBO)这一重要特性。——ZwqXin.com 本文可视为大致一...







1. attribute变量





  
  1. glsl3.x代码 (Vertex Program)
  2. #version 330
  3. layout(location = 0) in vec3 attrib_position;
  4. layout(location = 1) in vec2 attrib_texcoord;
  5. layout(location = 2) in vec3 attrib_normal;
  6. layout(location = 3) in int attrib_clustercount;




废弃 in/out 用于显式标明该变量的一些布局属性



2.uniform变量





  
  1. glsl代码
  2. #version 330
  3. uniform sampler2D basetex1;
  4. uniform float fAlphaRestrictVal;
  5. uniform mat4 matModel;
  6. uniform mat4 matView;
  7. uniform mat4 matProj;


glGetUniformLocation 麻烦

glUseProgram glUseProgram glProgramUniform glUniform glUseProgram glProgramUniform glUseProgram

大量的 上限值 MD5模型的格式、导入与顶点蒙皮式骨骼动画II ] TBO 一维纹理的Buffe

Uniform Buffer Object(UBO)


学一学,VBO


  
  1. glsl代码
  2. #version 330
  3. layout(std140) uniform matVP
  4. {
  5. mat4 matProj;
  6. mat4 matView;
  7. };


Interface block




  
  1. OpenGL代码
  2. GLint nMatVPBlockIndex = glGetUniformBlockIndex(nProgramHandler, "matVP");
  3. //GLint nMatVPBlockIndex = glGetProgramResourceIndex(nProgramHandler, GL_UNIFORM_BLOCK, "matVP");
  4. if (GL_INVALID_INDEX != nMatVPBlockIndex)
  5. {
  6. GLint nBlockDataSize = 0;
  7. glGetActiveUniformBlockiv(nProgramHandler, nMatVPBlockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &nBlockDataSize);
  8. glGenBuffers(1, &m_nUBO);
  9. glBindBuffer(GL_UNIFORM_BUFFER, m_nUBO);
  10. glBufferData(GL_UNIFORM_BUFFER, nBlockDataSize, NULL, GL_DYNAMIC_DRAW);
  11. glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_nUBO, 0, nBlockDataSize);
  12. glUniformBlockBinding(nProgramHandler, nMatVPBlockIndex, 0);
  13. glBindBuffer(GL_UNIFORM_BUFFER, NULL);
  14. }


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


  
  1. OpenGL代码
  2. GLint nMatVPBlockIndex = glGetUniformBlockIndex(nProgramHandler, "matVP");
  3. GLint nCloudScaleIndex = glGetUniformBlockIndex(nProgramHandler, "Scale");
  4. if (GL_INVALID_INDEX != nMatVPBlockIndex && GL_INVALID_INDEX != nCloudScaleIndex)
  5. {
  6. int nUniformBufferAlignSize = 0;
  7. glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &nUniformBufferAlignSize);
  8. GLint nBlockDataSize1 = 0, nBlockDataSize2 = 0;
  9. glGetActiveUniformBlockiv(nProgramHandler, nMatVPBlockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &nBlockDataSize1);
  10. glGetActiveUniformBlockiv(nProgramHandler, nCloudScaleIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &nBlockDataSize2);
  11. glGenBuffers(1, &m_nUBO);
  12. glBindBuffer(GL_UNIFORM_BUFFER, m_nUBO);
  13. glBufferData(GL_UNIFORM_BUFFER, nUniformBufferAlignSize + nBlockDataSize2, NULL, GL_DYNAMIC_DRAW);
  14. glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_nUBO, 0, nBlockDataSize1);
  15. glUniformBlockBinding(nProgramHandler, nMatVPBlockIndex, 0);
  16. glBindBufferRange(GL_UNIFORM_BUFFER, 1, m_nUBO, nUniformBufferAlignSize, nBlockDataSize2);
  17. glUniformBlockBinding(nProgramHandler, nCloudScaleIndex, 1);
  18. }


同一个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




  
  1. glsl代码
  2. layout(std140) uniform matVP
  3. {
  4. float elapsedTime;
  5. mat4 matProj;
  6. mat4 matView;
  7. };
  8. layout(std140) uniform Scale
  9. {
  10. uniform float cloudScale;
  11. };





  
  1. C++代码
  2. {
  3. //Render
  4. glBindBuffer(GL_UNIFORM_BUFFER, m_nUBO);
  5. glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GLfloat), &fElapsed);
  6. //current std140 alignment(for base sclaer): 16
  7. glBufferSubData(GL_UNIFORM_BUFFER, 16, sizeof(Matrix16), m_mtProj.mt);
  8. glBufferSubData(GL_UNIFORM_BUFFER, 16 + sizeof(Matrix16), sizeof(Matrix16), m_mtView.mt);
  9. //GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: 256
  10. glBufferSubData(GL_UNIFORM_BUFFER, 256, sizeof(GLfloat), &fCScale);
  11. glBindBuffer(GL_UNIFORM_BUFFER, NULL);
  12. }


两个重要优 glUniform

glUniform/glProgramUniform

3.varying变量


glShadeModel 需要光栅化时传入参数GL_SMOOTH,不需要时传入GL_FLAT

乱弹纪录I:Geometry Shader glProvokingVertex

flat


  
  1. glsl代码
  2. //vertex shader or geometry shadr
  3. flat out float visibility;
  4. //fragment shader
  5. flat in float visibility;


乱弹纪录I:Geometry Shader ] 一个ShaderProgram中不能有两个同为输入的同名varing变量 也不能有两个同为输出的同名varing变量存在


  
  1. glsl代码
  2. //Vertex Shader
  3. out vec2 varying_vg_texcoord;
  4. //Geometry Shader
  5. in vec2 varying_vg_texcoord[];
  6. out vec2 varying_gf_texcoord;
  7. //Fragment Shader
  8. in vec2 varying_gf_texcoord;


interface block



  
  1. //Vertex Shader
  2. out Varying
  3. {
  4. vec2 texcoord;
  5. }VaryingOut;
  6. //Geometry Shader
  7. in Varying
  8. {
  9. vec2 texcoord;
  10. }VaryingIn[];
  11. out Varying
  12. {
  13. vec2 texcoord;
  14. }VaryingOut;
  15. //Fragment Shader
  16. in Varying
  17. {
  18. vec2 texcoord;
  19. }VaryingIn;





  
  1. glsl代码
  2. //Geometry Shader Example
  3. void main(void)
  4. {
  5. for(int i = 0; i < gl_in.length(); ++i)
  6. {
  7. gl_Position = gl_in[i].gl_Position;
  8. VaryingOut.texcoord = VaryingIn[i].texcoord;
  9. EmitVertex();
  10. }
  11. EndPrimitive();
  12. }





  
  1. glsl代码
  2. //Geometry Shader Example
  3. out Varying
  4. {
  5. vec3 position;
  6. int cloudcount;
  7. vec3 dimension;
  8. }VaryingOut;


乱弹纪录IV:Transform Feedback


  
  1. C++代码
  2. //OpenGL Code Example
  3. const GLchar *varyingOutCloudFeed[] = {"Varying.position", "Varying.cloudcount", "Varying.dimension"};
  4. glTransformFeedbackVaryings(m_CloudFeedShader.GetProgramHandler(), 3, varyingOutCloudFeed, GL_SEPARATE_ATTRIBS);
  5. m_CloudFeedShader.Link();


4.fragmentShader输出


学一学,FBO MRT glBindFragDataLocation


  
  1. glsl代码 (fragemnt shader)
  2. //单输出
  3. layout(location = 0) out vec4 fragColor;
  4. //MRT
  5. layout(location = 0) out vec4 fragColor0;
  6. layout(location = 1) out vec4 fragColor1;


layout里的关键字其实还有个index


  
  1. glsl代码 (fragemnt shader)
  2. layout(location = 0, index = 0) out vec4 fragColor;
  3. layout(location = 0, index = 1) out vec4 src1Color;





  
  1. C++代码
  2. glEnable(GL_BLEND);
  3. glBlendFunc(GL_SRC_ALPHA, GL_SRC1_COLOR);











文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。

原文链接:panda1234lee.blog.csdn.net/article/details/51498303

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。