3

我有一个 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

1 回答 1

12

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

有多种工作角度,但我将从最基本的角度开始 - 着色器内的界面块。我将仅描述使用接口块时的一部分可能性,但这应该足以让您入门。

与“普通”变量相比,您不能buffer在全局范围内指定变量。您需要按照第 4.3.7 节 - GLSL 4.40 规范使用接口块(第 4.3.9 节 - GLSL 4.40 规范):

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

请注意,上述部分与ARB 扩展略有不同。

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

layout (binding = 0) buffer BlockName
{
  float values[]; // just as an example
}; 

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

void main()
{
  // ...

  values[0] = 1.f;

  // ...
}    

在应用程序级别上,您现在唯一需要知道的是,在程序成功链接后,buffer接口块BlockName具有绑定。0

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

glBindBufferBase(GLenum target​, GLuint index​, GLuint buffer​);

用于将完整缓冲区绑定到索引

glBindBufferRange(GLenum target​, GLuint index​, GLuint buffer​, GLintptr offset​, GLsizeiptr size​);

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

注意是indexbinding在你layout的对应接口块中指定的。

基本上就是这样。请注意,存储缓冲区大小、绑定点数量、最大存储块大小等都有一定的限制。我建议您参考 GL 和 GLSL 规范中的相应部分。

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

如果遇到问题,请发表评论。

于 2014-07-31T14:01:53.190 回答