gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 14:33:57 26 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/

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