我有一个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它实际上并没有真正崩溃,只是花了很多时间。
答案 0 :(得分:9)
存储缓冲区与统一缓冲区的工作方式非常相似。为了了解这些工作的原因,我建议使用this之类的东西。主要区别在于存储缓冲区可以容纳更多的数据,您可以从中随机读取并写入。
有多种角度可以解决这个问题,但我会从最基本的角度开始 - 着色器中的界面块。我将仅描述使用接口块时可能性的一部分,但它应足以让您入门。
与“普通”变量相比,您无法在全局范围中指定buffer
个变量。您需要按照第4.3.7节 - GLSL 4.40规范使用接口块(第4.3.9节 - GLSL 4.40规范):
缓冲区限定符可用于声明接口块(第4.3.9节“接口块”),然后将其称为着色器存储块。在全局范围(块外)声明缓冲区变量是一个编译时错误。
请注意,上述部分与ARB extension略有不同。
因此,要访问存储缓冲区中的内容,您需要在片段着色器(或任何其他适用的阶段)中定义buffer
接口块:
layout (binding = 0) buffer BlockName
{
float values[]; // just as an example
};
与没有实例名称的任何其他块一样,您将引用缓冲区存储,就像values
处于全局范围一样,例如:
void main()
{
// ...
values[0] = 1.f;
// ...
}
在应用程序级别上,您现在唯一需要知道的是buffer
接口块 BlockName 在程序成功链接后具有绑定0
。< / p>
使用应用程序创建存储缓冲区对象后,首先使用
将缓冲区绑定到为相应接口块指定的绑定glBindBufferBase(GLenum target, GLuint index, GLuint buffer);
用于将完整的缓冲区绑定到索引或
glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
用于将偏移量和一些缓冲区指定的子集绑定到索引。
请注意,index
是指binding
中为相应接口块指定的layout
。
基本上就是这样。请注意,存储缓冲区大小,绑定点数,最大存储块大小等存在某些限制。我将向您介绍GL和GLSL规范中的相应部分。
此外,ARB extension中有一个最小的例子。阅读扩展的问题部分还经常提供对暴露的功能及其背后的基本原理的进一步了解。我建议你仔细阅读。
如果遇到问题,请发表评论。