Performance opengl3 20k精灵慢帧速率?

Performance opengl3 20k精灵慢帧速率?,performance,opengl,graphics,go,game-engine,Performance,Opengl,Graphics,Go,Game Engine,我已经成功地在golang制作了opengl 3.x动画。然而;仅在渲染20k纹理后,逐帧更新速度明显较慢。精灵所做的只是从屏幕的左侧移动到右侧。请记住,它们都是相互重叠的,因为我懒得随机化位置 我有一台更新的电脑,可以在高设置下运行GTA5,但不能在opengl3环境下显示20k精灵(带纹理的四边形) 我一定是做错了什么。也许我需要在一个VBO中打包所有顶点,而不是为每个对象打包一个新的VBO?我也喜欢每个对象。我不确定是什么导致了这个瓶颈。有人能帮我吗?我不知道该怎么办 我已附上我的代码,供

我已经成功地在golang制作了opengl 3.x动画。然而;仅在渲染20k纹理后,逐帧更新速度明显较慢。精灵所做的只是从屏幕的左侧移动到右侧。请记住,它们都是相互重叠的,因为我懒得随机化位置

我有一台更新的电脑,可以在高设置下运行GTA5,但不能在opengl3环境下显示20k精灵(带纹理的四边形)

我一定是做错了什么。也许我需要在一个VBO中打包所有顶点,而不是为每个对象打包一个新的VBO?我也喜欢每个对象。我不确定是什么导致了这个瓶颈。有人能帮我吗?我不知道该怎么办

我已附上我的代码,供任何人参考,这些人可以提供一些加速opengl3中20k精灵渲染的技巧:

在不查看源代码的情况下,您应该使用一个VBO并为共享纹理的所有精灵组合几何体,并使用一个绘制调用绘制它们。

在不查看源代码的情况下,您应该使用一个VBO并为共享纹理的所有精灵组合几何体,并使用一个绘制调用来绘制它们。

我看到的一个问题是,每帧创建一个VBO。我不知道你想做什么。如果试图更新vbo,请改用glBufferSubData()。glBufferData()每次调用时都会创建一个新的缓冲区,因此它肯定比glBufferSubData()更昂贵。glBufferSubData()只是修改/更新vbo。这将提高fps。

我看到的一个问题是,每帧都会产生一个vbo。我不知道你想做什么。如果试图更新vbo,请改用glBufferSubData()。glBufferData()每次调用时都会创建一个新的缓冲区,因此它肯定比glBufferSubData()更昂贵。glBufferSubData()只是修改/更新vbo。这将提高您的fps。

OpenGL调用非常昂贵。在每一帧中,你都会做很多次。相反,如果可能的话,你想进行一次大抽签。如果不是,则每个纹理+程序组合一次绘制调用

您可以为绘制的每个对象传递矩阵,而不是将矩阵作为均匀矩阵传递

这段代码并没有它可能的那么好,但它的性能比您的好几个数量级

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()
}

OpenGL调用非常昂贵。在每一帧中,你都会做很多次。相反,如果可能的话,你想进行一次大抽签。如果不是,则每个纹理+程序组合一次绘制调用

您可以为绘制的每个对象传递矩阵,而不是将矩阵作为均匀矩阵传递

这段代码并没有它可能的那么好,但它的性能比您的好几个数量级

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()
}

如果所有内容都在一个vbo中,如何将转换应用于每个对象?我是否将统一传递给包含矩阵的顶点着色器?或者我是否使用客户端更新每个顶点,以便着色器获得已转换的顶点?我还觉得将较大的VBO传输到着色器的时间量会抵消较小的传输到着色器的时间量,从而抵消任何性能优势?如果您仔细操作,数据传输在后台进行,而您的程序正在执行其他操作。如果所有内容都在一个vbo中,如何对每个对象应用转换?我是否将统一传递给包含矩阵的顶点着色器?或者我是否使用客户端更新每个顶点,以便着色器获得已转换的顶点?我还觉得将较大的VBO传输到着色器的时间量会抵消较小的传输到着色器的时间量,从而抵消任何性能优势?如果您仔细操作,数据传输发生在后台,而您的程序正在执行其他操作。因此,对于我的每个VBO(uv、颜色、顶点),我应该调用glbuffersubdata,并且在循环开始之前只调用glbuffer一次?我说的对吗。使用glBufferData()分配内存,如果需要修改,只需使用glBufferSubData(),谢谢。这真的会给我那么多的fps提升吗。。。我的意思是,它只滞后于20k四边形(4个顶点)。。用我的图形卡/cpu,它应该在每一帧上做数十万个顶点?不能肯定。这只是增加开销的一件事。如果修改vbo只是为了应用变换(平移、旋转或缩放),那么实际上应该只将矩阵传递给着色器。我认为这将比glBufferSubData()更能提高fps。因此,对于我的每个VBO(uv、颜色、顶点),我应该调用glBufferSubData,并且在循环开始之前只调用glbuffer一次?我说的对吗。使用glBufferData()分配内存,如果需要修改,只需使用glBufferSubData(),谢谢。这真的会给我那么多的fps提升吗。。。我的意思是,它只滞后于20k四边形(4个顶点)。。用我的图形卡/cpu,它应该在每一帧上做数十万个顶点?不能肯定。这只是增加开销的一件事。如果修改vbo只是为了应用变换(平移、旋转或缩放),那么实际上应该只将矩阵传递给着色器。我认为这将比glBufferSubData()更能提高fps。