opengl3 20k sprites 帧速率慢?
Posted
技术标签:
【中文标题】opengl3 20k sprites 帧速率慢?【英文标题】:opengl3 20k sprites slow framerate? 【发布时间】:2015-08-07 10:44:08 【问题描述】:我已经成功用golang制作了一个opengl 3.x动画。然而;仅在渲染 20k 纹理后,逐帧更新才明显变慢。所有精灵所做的只是简单地从屏幕左侧移动到右侧。请记住,它们都在彼此之上,因为我懒得随机定位。
我有一台更新的 PC,可以在高设置下运行 GTA5,但无法在 opengl3 环境中显示 20k 精灵(带纹理的四边形)??
我一定是在这里做错了什么。也许我需要将所有顶点打包在一个 VBO 中,而不是为每个对象打包一个新的 vbo?我也绑定了每个对象。我不确定是什么导致了这个瓶颈。有人可以帮忙吗,因为我不知道从这里去哪里?
我附上了我的代码作为参考,任何人都可以提供一些关于在 opengl3 中加速渲染 20k 精灵的提示: http://pastebin.com/SHQtRPn7
【问题讨论】:
【参考方案1】:在不查看源代码的情况下,您应该使用一个 VBO 并为所有共享纹理的精灵组合几何图形,并使用一次绘制调用来绘制它们。
【讨论】:
如果一切都在一个 vbo 中,我如何对每个对象应用转换?我是否将制服传递给包含矩阵的顶点着色器?或者我是否使用客户端更新每个顶点,以便着色器获取已经转换的顶点? 我还觉得将较大的 VBO 传输到着色器所需的时间会抵消较小的着色器传输,从而抵消任何性能优势? 如果您小心操作,数据传输会在后台发生,而您的程序已经在执行其他操作。【参考方案2】:OpenGL 调用很昂贵。你在每一帧中都做了很多一万次。相反,如果可能的话,你想做一个大的draw call。如果没有,每个纹理 + 程序组合一个绘制调用。
您可以为您绘制的每个对象传递一个矩阵,而不是将矩阵作为统一传递。
这段代码不如它应该的那么好,但它的性能比你的要好几个数量级。
func (drawer *SpriteDrawer) Draw(sprites []Sprite)
if len(sprites) == 0
return
drawer.Use()
drawer.Texture.Bind(gl.TEXTURE_2D_ARRAY)
tmp := drawer.GetTransform().To32()
drawer.camera_uniform.UniformMatrix2x3f(false, &tmp)
vertexbuffer := gl.GenBuffer()
defer vertexbuffer.Delete()
vertexbuffer.Bind(gl.ARRAY_BUFFER)
stride := int(unsafe.Sizeof(sprites[0]))
gl.BufferData(gl.ARRAY_BUFFER, stride*len(sprites), sprites, gl.STREAM_DRAW)
var transform1, transform2, texcoords, texlevel gl.AttribLocation
transform1 = 0
transform2 = 1
texcoords = 2
texlevel = 3
transform1.AttribPointer(3, gl.FLOAT, false, stride, unsafe.Offsetof(sprites[0].Transform))
transform2.AttribPointer(3, gl.FLOAT, false, stride, unsafe.Offsetof(sprites[0].Transform)+unsafe.Sizeof(sprites[0].Transform[0])*3)
texcoords.AttribPointer(4, gl.FLOAT, false, stride, unsafe.Offsetof(sprites[0].TextureLeft))
texlevel.AttribPointer(1, gl.FLOAT, false, stride, unsafe.Offsetof(sprites[0].Layer))
transform1.EnableArray()
transform2.EnableArray()
texcoords.EnableArray()
texlevel.EnableArray()
gl.DrawArrays(gl.POINTS, 0, len(sprites))
transform1.DisableArray()
transform2.DisableArray()
texcoords.DisableArray()
texlevel.DisableArray()
library this is from
【讨论】:
【参考方案3】:我看到的一个问题是您每帧都创建一个 vbo。我不确定您要做什么。如果您尝试更新您的 vbo,请改用 glBufferSubData()。 glBufferData() 每次调用它时都会创建一个新缓冲区,因此它肯定会比 glBufferSubData() 更昂贵。 glBufferSubData() 只是修改/更新你的 vbo。这应该可以提高您的 fps。
【讨论】:
所以对于我的每个 vbo(uv、颜色、顶点)我应该调用 glbuffersubdata 并且只在循环开始前调用 glbuffer 一次?我说的对吗? 是的 :)。您使用 glBufferData() 分配内存,然后如果需要修改它,只需使用 glBufferSubData() 谢谢。这真的会给我带来那么大的 fps 提升吗...我的意思是它仅落后于 20k 四边形(4 个顶点)。使用我的显卡/cpu 应该每帧处理数十万个顶点? 不能肯定地说。这只是增加开销的一件事。 如果您修改 vbo 只是为了应用转换(平移、旋转或缩放),那么您应该只将矩阵传递给着色器。我认为这将比 glBufferSubData() 提高 fps。以上是关于opengl3 20k sprites 帧速率慢?的主要内容,如果未能解决你的问题,请参考以下文章
从 onCameraFrame、OpenCV、Android/Java 调用 HoughCircles() 方法时改变慢帧速率