Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 单个统一缓冲区对象的批处理模型矩阵_C++_Opengl_Glsl - Fatal编程技术网

C++ 单个统一缓冲区对象的批处理模型矩阵

C++ 单个统一缓冲区对象的批处理模型矩阵,c++,opengl,glsl,C++,Opengl,Glsl,我决定看看统一缓冲区对象。但我不确定什么时候不使用它 我尝试将所有模型转换批处理为一个数组,并立即发送到着色器。但它有它的后果。我还必须为每个顶点发送着色器id以匹配这些变换 所以我的问题是:它值得吗?或者在这种特殊情况下,我应该更喜欢使用常规的glUniform调用吗 下面是我的着色器程序 #版本330核心 vec3位置的布局(位置=0); int id中的布局(位置=1); 布局(std140)统一场景_数据 { mat4视图投影矩阵; mat4模型矩阵[128]; }; void main

我决定看看统一缓冲区对象。但我不确定什么时候不使用它

我尝试将所有模型转换批处理为一个数组,并立即发送到着色器。但它有它的后果。我还必须为每个顶点发送着色器id以匹配这些变换

所以我的问题是:它值得吗?或者在这种特殊情况下,我应该更喜欢使用常规的glUniform调用吗

下面是我的着色器程序

#版本330核心
vec3位置的布局(位置=0);
int id中的布局(位置=1);
布局(std140)统一场景_数据
{
mat4视图投影矩阵;
mat4模型矩阵[128];
};
void main()
{
gl_Position=ViewProjectionMatrix*ModelMatrix[id]*vec4(位置,1.0);
}
以下是创建统一缓冲区对象的方法:

Dot::UniformBuffer::UniformBuffer(常量void*数据、无符号整数大小、无符号整数索引)
:m_索引(索引),m_大小(大小)
{
glGenBuffers(1和m_UBO);
glBindBuffer(GL_统一缓冲区,m_UBO);
glBufferData(GLU统一缓冲区、大小、数据、GLU动态绘图);
glBindBufferBase(GL_统一缓冲区,索引,m_UBO);
glBindBuffer(GL_统一_缓冲区,0);
}
点::UniformBuffer::~UniformBuffer()
{
gldeletembuffers(1和m_UBO);
}
void点::UniformBuffer::更新(常量void*数据)
{
glBindBuffer(GL_统一缓冲区,m_UBO);
GLvoid*p=glMapBuffer(GLU统一缓冲区,仅GLU写缓冲区);
memcpy(p、数据、m_大小);
glUnmapBuffer(GLU统一缓冲区);
}

每件事都有其折衷之处,需要性能测量来验证

glUniform
视为传递值,而UBO是通过引用传递的。除此之外,GPU着色器代码中[通常]没有对UBO附加间接寻址的性能惩罚

UBOs的主要好处是减少“绑定”阶段的CPU开销,因为所有值都已写入内存。渲染可以在加载时预先准备多个UBO(每个“状态向量”一个UBO),以避免在主渲染循环期间传输数据。通常,您不希望在渲染器中就地修改UBO,因为
glMapBuffer
将等待使用该UBO的先前绘制完成

在此特定示例中,着色器正在使用输入属性
id
执行“索引常量查找”,这比统一常量查找慢

其他考虑:

  • int-id中的布局(位置=1)要求CPU准备额外的顶点缓冲区和索引缓冲区。这也可能意味着制作原始几何体的数据副本,这更需要CPU和内存
  • glDrawArraysInstanced
    glDrawerElementsInstanced
    可以让OpenGL为您生成
    id
    。从着色器中,使用
    gl\u InstanceID
    。不再需要额外的顶点缓冲区。这将类似于
  • glUniform
    将导致每次调用时从应用程序代码-->驱动程序-->GPU传输数据
  • UBO需要更多的对象管理和规划,但通常会汇聚到性能最快的渲染器上。Vulkan和D3D12只支持UBO风格的编程

我计划在带有顶点和其他数据的单个VBO中发送id,因此我不会创建新的VBO,而且我会在渲染阶段结束时每帧更新一次UBO中的矩阵…因此我想知道对许多对象更新单个UBO是否更有效,或者多次更新uniform。如果将
id
预烘焙到VBO数据中不是一个负担,那么唯一的次要问题是着色器中的索引常量查找(ModelMatrix[id]使用每个线程id)。如果顶点是按id分组的,它将趋于一致->也很好。每帧更新UBO仍可能导致不需要的CPU/GPU同步,因为OpenGL建立了一个“软件/硬件管道”,如[CPU]渲染线程-->[CPU]驱动程序线程-->GPU。Map调用创建一个互锁。