gpt4 book ai didi

opengl - 动态长度数组作为着色器存储缓冲区对象

转载 作者:行者123 更新时间:2023-12-01 14:33:58 27 4
gpt4 key购买 nike

假设我要在OpenGL着色器中访问动态数量的“球”。在C++中,数据可能是这样的:

struct Ball
{
glm::vec3 position;
glm:vec3 colour;
float size;
};

std::vector<Ball> all_balls;

如果我想遍历片段着色器中的 all_balls,我相信我将需要一个着色器存储缓冲区对象。

This documentation涉及数组,但明显不完整。

我假设我可以像这样将数据发送到缓冲区
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, all_balls.size() * sizeof(Ball), &(all_balls[0]), usage);

在GLSL中,如何指定缓冲区为数组,并且我的着色器如何知道此数组的大小?

最佳答案

当使用长度不是编译时间常数的数组时,可以将SSBO Interface Block的成员声明为不确定的长度。

假设存在适合C++球结构的GLSL结构,代码看起来可能像这样:

struct GLSLBall {...};

layout(std430, binding = 0) buffer BallBuffer
{
GLSLBall ball_data[];
}


然后,您可以像这样对所有元素进行迭代:
for (int i = 0; i < ball_data.length(); ++i)
{
GLSLBall currentBall = ball_data[i];
}

当元素数量经常变化时,我建议不要每次都重新调整SSBO的大小/重新分配它,而是一次保留足够大的缓冲区,然后将实际使用的元素数量传递给着色器。这可以是一个独立的统一变量( uniform uint ballCount;),也可以将其打包到SSBO本身,如下所示:
struct GLSLBall {...};

layout(std430, binding = 0) buffer BallBuffer
{
uint ball_length;
GLSLBall ball_data[];
}


然后,您只能分配一次内存:
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, ENOUGH_MEMORY_FOR_ALL_CASES, null, usage);

并在每次内容更改时上传数据,如下所示:
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(unsigned int), (unsigned int)all_balls.size());
glBufferSubData(GL_SHADER_STORAGE_BUFFER, sizeof(unsigned int), all_balls.size() * sizeof(Ball), &(all_balls[0]));

然后,glsl循环类似于
for (int i = 0; i < BallBuffer.length; ++i)
{
GLSLBall currentBall = ball_data[i];
...
}

请注意,由于使用vec3,您当前的C++结构布局可能会导致某些对齐问题。您可能需要阅读 Should I ever use a vec3 inside of a uniform buffer or shader storage buffer object?(感谢Rabbid76的提示)

关于opengl - 动态长度数组作为着色器存储缓冲区对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57744826/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com