将矩阵建模为单个统一缓冲区对象
Batch model matrixes to single Uniform Buffer Object
我决定看看统一的缓冲区对象。但我不确定何时何地不使用它。
我尝试将所有模型转换批处理到单个数组中,然后立即发送到着色器。但它有它的后果。我还必须发送到每个顶点的着色器 id 以匹配这些转换。
所以我的问题是:它值得吗?还是在这种特殊情况下,我应该更喜欢使用常规的glUniform调用?
下面是我的着色器程序。
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in int id;
layout (std140) uniform scene_data
{
mat4 ViewProjectionMatrix;
mat4 ModelMatrix[128];
};
void main()
{
gl_Position = ViewProjectionMatrix * ModelMatrix[id] * vec4(position,1.0);
}
以下是我创建统一缓冲区对象的方法:
Dot::UniformBuffer::UniformBuffer(const void*data, unsigned int size, unsigned int index)
:m_Index(index),m_size(size)
{
glGenBuffers(1, &m_UBO);
glBindBuffer(GL_UNIFORM_BUFFER, m_UBO);
glBufferData(GL_UNIFORM_BUFFER, size, data, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, index, m_UBO);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
Dot::UniformBuffer::~UniformBuffer()
{
glDeleteBuffers(1, &m_UBO);
}
void Dot::UniformBuffer::Update(const void* data)
{
glBindBuffer(GL_UNIFORM_BUFFER, m_UBO);
GLvoid* p = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY);
memcpy(p, data, m_size);
glUnmapBuffer(GL_UNIFORM_BUFFER);
}
一切都有其权衡,并且需要性能测量来验证。
将glUniform
视为按值传递,而 UBO 是按引用传递。 除了 GPU 着色器代码中 [通常] 没有性能损失,用于对 UBO 的额外间接寻址。
UBO的主要优点是在"绑定"阶段减少CPU开销,因为所有值都已经写入内存。渲染可以在加载时预先准备许多 UBO(每个"状态向量"一个 UBO),以避免在主渲染循环期间传输数据。 通常,您不希望在渲染器中就地修改 UBO,因为glMapBuffer
将等待使用该 UBO 的先前绘制完成。
在这个特定示例中,着色器使用输入属性id
执行"索引常量查找",这比统一常量查找慢。
其他注意事项:
layout (location = 1) in int id;
要求 CPU 准备额外的顶点缓冲区和索引缓冲区。 这也可能意味着制作原始几何图形的数据副本,这会占用更多的 CPU 和内存。glDrawArraysInstanced
或glDrawElementsInstanced
可以让OpenGL为您生成id
。 在着色器中,使用gl_InstanceID
。 无需额外的顶点缓冲区。 这将类似于 https://learnopengl.com/Advanced-OpenGL/InstancingglUniform
将导致数据在每次调用时从应用程序代码(>驱动程序)> GPU 传输。- UBO需要更多的对象管理和规划,但通常集中在性能最快的渲染器上。 Vulkan 和 D3D12 仅支持 UBO 风格的编程。
相关文章:
- Opengl 3/4 : 我可以将相同的缓冲区对象绑定到不同的目标吗?
- 使用 OpengGLES2(角度)从帧缓冲区对象读取
- 如何将统一缓冲区对象数组加载到着色器中?
- 将矩阵建模为单个统一缓冲区对象
- 如何使用 new 和 delete 与 OpenGL 的缓冲区对象一起使用?
- OpenGL:缓冲区对象/着色器超出范围
- 为什么我的顶点缓冲区对象出现访问冲突错误?
- 在 OpenGL 中,为什么除非我再次重新指定顶点属性,否则我的缓冲区对象不会绘制?
- 打开"GL着色器存储缓冲区对象"以替换"顶点属性"
- 在缓冲区对象上运行并通过着色器更改其数据?
- 使用统一缓冲区对象进行批处理渲染
- 为什么我的 openGL 顶点缓冲区对象不会绘制任何内容?
- 通过帧缓冲区对象渲染到纹理
- 使用索引缓冲区对象时出现奇怪的分段错误
- 帧缓冲区对象错误
- 为什么在调用 glDrawArray 之前不需要绑定顶点缓冲区对象?
- 通过统一缓冲区对象发送到 GLSL 的数据会泄漏到其他绘制调用中 (OpenGL 3.2)
- Boost.Asio如何创建一个大小等于数组大小的缓冲区对象
- 动态打包 OpenGL 顶点缓冲区对象的数据
- Opengl 通过使用顶点缓冲区对象