我必须做什么布局和绑定才能使(工作的)着色器存储缓冲区在第二个着色器程序中可读?
我设置并填充了一个我成功绑定并用于几何着色器的SSBO。该着色器读取并写入该SSBO-到目前为止没有问题。在那里没有渲染。
在下一步中,我的渲染过程(第二个着色器程序)将有权访问此数据。这个想法是要有一个大数据集,而第二个程序的顶点着色器每个渲染调用仅使用一些索引来选择该SSBO的某些值。
我会错过某些特定的绑定命令还是将其放在错误的位置?
两个程序中的布局是否一致?我弄乱了实例吗?
我只是找不到在两个程序中使用的SSBO的任何示例。
创建,填充和绑定:
float data[48000];
data[0] = -1.0;
data[1] = 1.0;
data[2] = -1.0;
data[3] = -1.0;
data[4] = 1.0;
data[5] = -1.0;
data[6] = 1.0;
data[7] = 1.0;
data[16000] = 0.0;
data[16001] = 1.0;
data[16002] = 0.0;
data[16003] = 0.0;
data[16004] = 1.0;
data[16005] = 0.0;
data[16006] = 1.0;
data[16007] = 1.0;
GLuint ssbo;
glGenBuffers(1, &ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data, GL_DYNAMIC_COPY);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssbo);
实例化几何着色器
layout(std140, binding = 1) buffer mesh
{
vec2 points[8000];
vec2 texs[8000];
vec4 colors_and_errors[8000];
} mesh_data;
另一个程序的顶点着色器中的第二个实例
layout(std140, binding = 1) buffer mesh
{
vec2 points[8000];
vec2 texs[8000];
vec4 colors_and_errors[8000];
} mesh_data;
这些实例是否相互配合?
现在由于我不确定自己在做什么,所以现在还没有在渲染循环中发布我的绑定。我尝试在更改使用的程序之前/之后进行绑定;没有成功。
有人有主意吗?
编辑:我还必须将SSBO绑定到渲染循环之外的第二个程序吗?与第一次绑定的方式不同吗?
编辑:尽管我没有解决这个特定问题,但我发现了一种解决方法,从opengl的角度来看,它可能甚至更多。
我将第一个程序的SSBO用作第二个程序的顶点属性。这个和opengl的索引渲染功能解决了这个问题。
(应该将其标记为已解决吗?)
答案 0 :(得分:0)
似乎您已经走了很多路,但是您需要注意一些事项。
两个程序中的布局是否一致? 布局(std140,绑定= 1)缓冲网格
您需要注意这种布局。 std140将对vec4的对齐方式四舍五入,因此将不再与您从C代码提供的数据对齐。在这种情况下,std430应该适合您。
我还必须将SSBO绑定到渲染循环之外的第二个程序吗?与第一次绑定的方式不同吗?
绑定一次SSBO后,假设两个程序都使用相同的绑定点(在您的示例中为相同),则应该没问题。程序之间共享数据很好,但是需要同步。您可以使用内存屏障来强制执行此操作。
您没有提及VAO,但是只有在绑定VAO之后才能使用SSBO(默认情况下则不能使用)。
我认为最好用一个例子来解释。
第一个程序的顶点着色器。它使用缓冲区数据的位置和纹理坐标,然后在Y中翻转位置。
layout(std430, binding = 1) buffer mesh {
vec4 points[3];
vec2 texs[3];
} mesh_data;
out highp vec2 coords;
void main() {
coords = mesh_data.texs[gl_VertexID];
gl_Position = mesh_data.points[gl_VertexID];
mesh_data.points[gl_VertexID] = vec4(gl_Position.x, -gl_Position.y, gl_Position.zw);
}
为第二个程序验证着色器。它只是使用数据,而不修改数据。
layout(std430, binding = 1) buffer mesh {
vec4 points[3];
vec2 texs[3];
} mesh_data;
out highp vec2 coords;
void main() {
coords = mesh_data.texs[gl_VertexID];
gl_Position = mesh_data.points[gl_VertexID];
}
在应用程序中,您需要绑定VAO。
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
然后设置您的SSBO。
float const data[] = {
-0.5f, -0.5f, 0.0f, 1.0,
0.0f, 0.5f, 0.0f, 1.0,
0.5f, -0.5f, 0.0f, 1.0,
0.0f, 0.0f,
0.5f, 1.0f,
1.0f, 0.0f
};
glGenBuffers(1, &ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssbo);
使用第一个程序进行绘图调用。
glUseProgram(first_program);
glDrawArrays(GL_TRIANGLES, 0, 3);
插入一个内存屏障,以确保在下一个绘制调用尝试从缓冲区读取之前,完成上一个绘制调用的写操作。
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
使用第二个程序进行抽奖。
glUseProgram(second_program);
glDrawArrays(GL_TRIANGLES, 0, 3);
我希望这可以澄清一切!如果您还有其他问题,请告诉我。