我想在ssbo数据之间切换以使用不同的设置绘制事物。为此,我需要使用glBindBufferRange()
及其适当的偏移量。
我已经读过,对于ubo,偏移量必须是GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
的倍数,但是由于使用std430而不是std140,所以ssbo可能会改变某些情况。
我尝试过最简单的方法
struct Color
{
float r, g, b, a;
};
struct V2
{
float x, y;
};
struct Uniform
{
Color c1;
Color c2;
V2 v2;
float r;
float f;
int t;
};
GLuint ssbo = 0;
std::vector<Uniform> uniform;
int main()
{
//create window, context etc.
glCreateBuffers(1, &ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
Uniform u;
u.c1 = {255, 0, 255, 255 };
u.c2 = {255, 0, 255, 255 };
u.v2 = { 0.0f, 0.0f };
u.r = 0.0f;
u.f = 100.0f;
u.t = 0;
uniform.push_back(u);
u.c1 = {255, 255, 0, 255 };
u.c2 = {255, 255, 0, 255 };
u.v2 = { 0.0f, 0.0f };
u.r = 100.0f;
u.f = 100.0f;
u.t = 1;
uniform.push_back(u);
u.c1 = {255, 0, 0, 255 };
u.c2 = {255, 0, 0, 255 };
u.v2 = { 0.0f, 0.0f };
u.r = 100.0f;
u.f = 0.0f;
u.t = 0;
uniform.push_back(u);
glNamedBufferData(ssbo, sizeof(Uniform) * uniform.size(), uniform.data(), GL_STREAM_DRAW);
for(int i = 0; i < uniform.size(); ++i) {
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 1, ssbo, sizeof(Uniform) * i, sizeof(Uniform));
glDrawArrays(...);
}
//swap buffer etc.
return 0;
}
#version 460 core
layout(location = 0) out vec4 f_color;
layout(std430, binding = 1) buffer Unif
{
vec4 c1;
vec4 c2;
vec2 v2;
float r;
float f;
int t;
};
void main()
{
f_color = vec4(t, 0, 0, 1);
}
当然有vao,vbo,顶点结构等,但它们不会影响ssbo。
不过,我遇到了GL_INVALID_VALUE
glBindBufferRange()
错误。而且这必须来自偏移量,因为我的下一次尝试将传输数据,但是顺序错误。
我的下一个态度是使用GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT
还有我在互联网上找到的公式
int align = 4;
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &align);
int ssboSize = sizeof(Uniform) + align - sizeof(Uniform) % align;
所以只需更改glNamedBufferData
和glBindBufferRange
就像这样
glNamedBufferData(ssbo, ssboSize * uniform.size(), uniform.data(), GL_STREAM_DRAW);
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 1, ssbo, ssboSize * i, sizeof(Uniform));
这样,它几乎起作用了。如您所见,t
是
0;
1;
0;
所以opengl应该用颜色绘制3种形状-
vec4(0, 0, 0, 1);
vec4(1, 0, 0, 1);
vec4(0, 0, 0, 1);
它会给他们错误的顺序
vec4(1, 0, 0, 1);
vec4(0, 0, 0, 1);
vec4(0, 0, 0, 1);
如何使它正确传输数据?
答案 0 :(得分:1)
OpenGL spec (Version 4.6)在“ 6.1.1将缓冲区对象绑定到已索引的目标点”一节中声明了以下内容,以补充glBindBufferRange
的错误条件:
- 如果
INVALID_VALUE
为BindBufferRange
,则会产生buffer
错误 非零和offset
或size
分别不满足为指定目标的那些参数描述的约束,如第6.7.1节所述。
SSBO的第6.7.1节“索引缓冲区对象限制和绑定查询”状态:
- 起始偏移量:
SHADER_STORAGE_BUFFER_START
- 偏移量限制:
SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT
的值的倍数- 绑定大小
SHADER_STORAGE_BUFFER_SIZE
根据表23.64“依赖于实现的总体明暗器限制”:
256 [带有以下脚注]:
SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT
的值是允许的最大值,而不是最小值。
因此,如果偏移量不是256的倍数(不是)的倍数,则根本无法保证该代码完全起作用。您可以通过运行的实现查询实际的限制,并相应地调整缓冲区内容,但是必须准备好它高达256个字节。
答案 1 :(得分:0)
我最终使用了struct alignas(128) Uniform
。我想我的下一个目标是不使用硬编码对齐。