具有可分离程序的 OpenGL 统一块绑定

Posted

技术标签:

【中文标题】具有可分离程序的 OpenGL 统一块绑定【英文标题】:OpenGL Uniform block bindings with separarable programs 【发布时间】:2020-04-13 04:31:08 【问题描述】:

我正在尝试设置统一块,但对 glUniformBlockBinding()glBindBufferRange() 感到非常困惑。问题是我试图一次将单个 UBO 缓冲区共享给多个可分离的程序。想想:glBindProgramPipeline()glUniformBlockBinding()。我正在使用 OpenGL 4.5 Core 配置文件功能。

例如有三个着色器阶段,一个顶点和两个片段用于后期处理:

//Vertex shader A:
#version 450 core
layout(std140) uniform Camera 
    mat4 Projection;
    mat4 Modelview;
;
const vec2 TexCoords[] = 
     0.f, 0.f ,
     1.f, 0.f ,
     1.f, 1.f ,
     0.f, 1.f ;
out VertexData 
    smooth vec2 TexCoord;
 vs;
void main() 
    float xw = 400.0, yh = 300.0;
    vec2 vertices[] = 
         -xw, -yh ,
         xw, -yh ,
         xw, yh ,
         -xw, yh ;
    vec4 vpos = vec4(vertices[gl_VertexID % 4], 0.0, 1.0);
    gl_Position = Projection * Modelview * vpos;
    vs.TexCoord = TexCoords[gl_VertexID % 4];


// Post processing Fragment shader skeleton:
#version 450 core
in VertexData 
    smooth vec2 TexCoord;
 fs;
layout(location=0) out vec4 FragData[2];
uniform sampler2D Texture[2];
layout(std140) uniform Effect 
    int FragIndex;
    int MaxWeights;
    float Weights[64];
    vec2 BlurXY;
;
void main() 
    FragData[FragIndex] = texture(Texture[1 - FragIndex], fs.TexCoord);

如何仅使用单个 UBO 缓冲区设置统一块?

【问题讨论】:

【参考方案1】:

你不能。或者至少,不是你说的那样。

实际上,您可以将这三个着色器的所有统一数据放在同一个缓冲区对象中。你必须确保the alignment for the start of each block's data matches the implementation-defined alignment requirements specified for UBOs(通过GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT查询),但除此之外,你很好。

但是,没有办法避免在每个着色器的使用之间调用glBindBufferRange。即使您将所有块的块绑定索引设置为相同的索引。即使您每次都绑定相同的缓冲区。原因是您必须从缓冲区中选择一个不同的范围,因为这些块都是不同的并且存储不同的数据。

【讨论】:

我可以在每次着色器使用之间调用glBindBufferRange。然而,代码还不能确保缓冲区范围对齐,最好检查一下这是否是问题...... 是的,在正确对齐缓冲区偏移后解决了问题!我还发现了另一个与 FBO 相关的黑屏错误。

以上是关于具有可分离程序的 OpenGL 统一块绑定的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL在可分离着色器程序中改变不同的位置

高级OPENGL, 利用uniform块接口

OpenGL中的统一块

OpenGL / GLSL - 统一块数据值不正确

OpenGL均匀采样器2D具有相同的图像

关于 OpenGL 布局 std140 统一块中的数组