Opengl 将SSBO绑定到片段着色器

Opengl 将SSBO绑定到片段着色器,opengl,glsl,fragment-shader,compute-shader,Opengl,Glsl,Fragment Shader,Compute Shader,我有一个SSBO,它为屏幕上的每个像素存储vec4颜色值,并在主循环之前由计算着色器预先填充值 我现在尝试在屏幕上获取这些数据,我想这涉及到使用片段着色器(尽管如果你知道更好的方法,我愿意接受建议) 所以我试图把缓冲区或者至少是其中的数据放到片段着色器中,这样我就可以将每个片段的颜色设置为缓冲区中相应的值,但是我找不到任何方法来做到这一点 有人告诉我,我可以将SSBO绑定到片段着色器,但我不知道怎么做?我的另一个想法是将数据从SSBO移动到纹理中,但我也无法解决这个问题 更新: 作为对thokr

我有一个SSBO,它为屏幕上的每个像素存储vec4颜色值,并在主循环之前由计算着色器预先填充值

我现在尝试在屏幕上获取这些数据,我想这涉及到使用片段着色器(尽管如果你知道更好的方法,我愿意接受建议)

所以我试图把缓冲区或者至少是其中的数据放到片段着色器中,这样我就可以将每个片段的颜色设置为缓冲区中相应的值,但是我找不到任何方法来做到这一点

有人告诉我,我可以将SSBO绑定到片段着色器,但我不知道怎么做?我的另一个想法是将数据从SSBO移动到纹理中,但我也无法解决这个问题

更新:

作为对thokra出色回答和以下评论的回应,这里是设置缓冲区的代码:

//Create the buffer
GLuint pixelBufferID;
glGenBuffers(1, &pixelBufferID);

//Bind it
glBindBuffer(GL_SHADER_STORAGE_BUFFER, pixelBufferID);

//Set the data of the buffer
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(vec4) * window.getNumberOfPixels, new vec4[window.getNumberOfPixels], GL_DYNAMIC_DRAW);

//Bind the buffer to the correct interface block number
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, pixelBufferID);
然后我调用计算着色器,这部分工作正常,我检查数据是否正确填充。然后在我的片段着色器中,作为测试:

layout(std430, binding=0) buffer PixelBuffer
{
    vec4 data[];
} pixelBuffer

void main()
{
    gl_FragColor = pixelBuffer.data[660000];
}

我注意到,索引越高,所需的时间似乎越来越长,因此在660000处,它实际上不会崩溃,只是花费了很长的时间。

存储缓冲区的工作方式与统一缓冲区非常相似。为了弄清楚它们是如何工作的,我建议这样做。主要区别在于,存储缓冲区可以容纳大量的数据,并且您可以随机地读取和写入这些数据

这有多种角度,但我将从最基本的角度开始——着色器中的接口块。我将只描述使用接口块时的一部分可能性,但它应该足以让您开始

与“正常”变量不同,您不能在全局范围内指定
缓冲区
变量。您需要按照第4.3.7节-GLSL 4.40规范使用接口块(第4.3.9节-GLSL 4.40规范):

缓冲区限定符可用于声明接口块(第4.3.9节“接口块”),然后将其称为着色器存储块。在全局范围(块外部)声明缓冲区变量是编译时错误

请注意,上述章节与之前的章节略有不同

因此,要访问存储缓冲区中的内容,您需要在片段着色器(或任何其他适用的阶段)内定义一个
缓冲区
接口块:

与任何其他没有实例名称的块一样,您将引用缓冲区存储,就好像
在全局范围内一样,例如:

void main()
{
  // ...

  values[0] = 1.f;

  // ...
}    
在应用程序级别,您现在需要知道的唯一一件事是,成功链接程序后,
缓冲区
接口块块名具有绑定
0

使用应用程序创建存储缓冲区对象后,首先使用为相应接口块指定的绑定绑定缓冲区

glBindBufferBase(GLenum target​, GLuint index​, GLuint buffer​);
用于将完整缓冲区绑定到索引或

用于将由偏移量和缓冲区的数量指定的子集绑定到索引

请注意,
索引
是指在
布局
中为相应接口块指定的
绑定

基本上就是这样。请注意,存储缓冲区大小、绑定点数量、最大存储块大小等都有一定的限制。请参阅德国劳埃德船级社和德国劳埃德船级社规范中的相应章节

此外,在中还有一个最小的示例。阅读扩展部分的问题部分通常还可以进一步深入了解公开的功能及其背后的原理。我建议你通读一遍


如果遇到问题,请留下评论。

这太棒了,它有点有效:D我的问题是缓冲区存储像素值,因此对于高分辨率,这意味着缓冲区中有很多项。作为测试,我尝试访问索引660000,该索引应在范围内(分辨率为1200x741)但是当我这样做时,程序崩溃了?你能用缓冲区设置代码和指定接口块的片段着色器的子部分更新你的问题吗?我们谈论的时间是多少?你能在填充SSBO的地方发布计算着色器代码吗?
glBindBufferBase(GLenum target​, GLuint index​, GLuint buffer​);
glBindBufferRange(GLenum target​, GLuint index​, GLuint buffer​, GLintptr offset​, GLsizeiptr size​);