C++ 在OpenGL中,在保持良好帧速率的同时,VBO中有多少顶点是一个好的目标

C++ 在OpenGL中,在保持良好帧速率的同时,VBO中有多少顶点是一个好的目标,c++,opengl,C++,Opengl,我正在从头开始制作2D游戏引擎,主要是为了好玩。最近我非常关心整个发动机的性能。我一直在阅读关于要尝试达到的多边形的大量目标的文章,我看到了数以百万计的talk,同时我只获得了40000个,没有可怕的帧速率下降 我曾尝试使用图形卡中的映射缓冲区,而不是我自己的,但这实际上会使我的性能更差。我读过像三重缓冲区渲染这样的技术,我可以看到它在理论上是如何加速的,我无法想象它会将我的代码加速到我读过的数百万 我使用的格式是28字节的顶点(3个浮点数表示位置,2个浮点数表示纹理坐标,1个浮点数表示颜色,1

我正在从头开始制作2D游戏引擎,主要是为了好玩。最近我非常关心整个发动机的性能。我一直在阅读关于要尝试达到的多边形的大量目标的文章,我看到了数以百万计的talk,同时我只获得了40000个,没有可怕的帧速率下降

我曾尝试使用图形卡中的映射缓冲区,而不是我自己的,但这实际上会使我的性能更差。我读过像三重缓冲区渲染这样的技术,我可以看到它在理论上是如何加速的,我无法想象它会将我的代码加速到我读过的数百万

我使用的格式是28字节的顶点(3个浮点数表示位置,2个浮点数表示纹理坐标,1个浮点数表示颜色,1个浮点数表示从哪个纹理缓冲区读取)。我曾想过要把这件事删减,但又一次,这似乎不值得

查看我的代码几乎98%的时间都花在分配、填充和向图形卡提供VAO上。所以这是我目前唯一的瓶颈

所有的精灵都是四边形,我只是用GL_四边形来渲染整个对象。40000个精灵感觉很低落。我对他们只有一次平局,所以从我所读到的内容来看,我期望至少是10倍。我发现一些模型中有近40k个多边形,仅用于3D

以下是一些有关我如何呈现所有内容的相关代码:

//这是主渲染循环,目前每帧只调用一次
对于(int i=0;igetShader().getShaderProgram());
GLint loc=glGetUniformLocation(l_层[i]->getShader().GetShaderProgramm(),“MVT”);
glUniformMatrix4fv(位置1,GL_假,材料数据);
l_层[i]->getVertexBuffer().Bind();
glDrawArrays(GLU四边形、0、l_层[i]->getVertexBuffer().getSize());
l_Layers[i]->getVertexBuffer().Unbind();
}
//到目前为止,这些代码行占用的计算时间最多
void OP::VertexBuffer::startBuffer(整数大小)
{
冲洗();
顶点=新顶点[大小*4];
}
void OP::VertexBuffer::submit(顶点)
{
顶点[索引]=顶点;
索引++;
}
void Layer::Render(){
l_VertexBuffer.startBuffer(l_Sprites.size());
对于(size_t i=0;igetVertexArray();
l_VertexBuffer.submit(vert[0]);
l_VertexBuffer.submit(vert[1]);
l_VertexBuffer.submit(vert[2]);
l_VertexBuffer.submit(vert[3]);
}
}
我不知道我做错了什么,但我只是不明白人们是如何在屏幕上看到更多数量级的多边形的。尤其是当他们的模型比我的GL_四边形复杂得多的时候

98%的时间用于分配、填充和向图形卡提供VAO。所以这是我目前唯一的瓶颈

创建VAO并填充它实际上只应该发生一次,因此不应该影响帧速率,在调用render之前,您应该只需要绑定VAO

显然,我看不到您的所有代码,所以我可能有错误的想法,但每次调用Render时,您似乎都在创建一个新的顶点数组

你把所有的时间都花在这里并不奇怪:

//These lines of code take up by far the most compute time
void OP::VertexBuffer::startBuffer(int size)
{
    flush();
    Vertices = new Vertex[size * 4];
}
对大型阵列的每次渲染调用调用new都会极大地影响性能,您还需要花费时间为该阵列分配每一帧

除此之外,您似乎正在泄漏内存

每次你打电话:

Vertices = new Vertex[size * 4];
无法释放在上一次渲染调用中分配的数组。您所做的与下面的示例类似:

foo = new Foo();
foo = new Foo();
内存在第一次调用中分配给foo,创建的第一个foo从未解构或解除分配,现在没有办法这样做,因为foo已被重新分配,因此第一个foo已泄漏


因此,我认为您在这里遇到了一系列问题。

我鼓励您查找几年前的AZDO(接近零驱动开销)谈话,这应该会让您开始。它的要旨是减少状态更改,通过批处理减少(但更大)绘制调用。在多少绘制调用中,“我只获得了40000个,没有可怕的帧速率下降”?在任何给定的16毫秒内,您通常只能得到1000-4000个绘制调用。@genpfault该程序设置为以后允许每帧进行多个绘制调用(对于多个着色器),但现在,我只有一个绘制调用。您基本上是对的。不过,我会在每一帧删除缓冲区,因此不会出现内存泄漏(目前)。我不确定每次如何释放缓冲区中的内存。所以我想删除它并创建一个新的会比每次调用都用0填充更快。但是为什么要在每一帧重新创建缓冲区?啊,我可以指定在绘制调用的最后一帧中绘制了多少元素。阵列创建占用了我大量的渲染时间,但仍有50%多一点的时间用于将数据复制到阵列,有没有办法帮助加快速度?抱歉,如果我不理解你的意思,但你会加快速度,但不会每帧重新创建缓冲区。。。没有理由每次渲染时都必须不断重新创建缓冲区。一旦您创建了缓冲区并将其绑定到VAO,您不需要对其进行任何操作,直到您使用完这些缓冲区,例如,您不再需要渲染它们,在这种情况下,您只需释放它们。我想另一种情况是,如果它们的顶点不断变化,你需要一直重新创建缓冲区。是的,我的顶点每帧都会变化。我可能可以重用相同的数组,但我不确定opengl如何处理始终获得相同缓冲区的问题。