Python minecraft pyglet glClear() 跳帧

标签 python opengl frame minecraft pyglet

我最近从 https://github.com/fogleman/Craft 下载了 fogleman 出色的“Minecraft in 500 lines”演示.我使用了 2to3 工具并手动更正了一些细节,使其可以在 python3 下运行。我现在想知道在渲染方法中调用 self.clear() 的事情。这是我修改后的渲染方法,由 pyglet 调用每一帧:

def on_draw(self):
    """ Called by pyglet to draw the canvas.

    """
    frameStart = time.time()
    self.clear()
    clearTime = time.time()
    self.set_3d()
    glColor3d(1, 1, 1)
    self.model.batch.draw()
    self.draw_focused_block()
    self.set_2d()
    self.draw_label()
    self.draw_reticle()
    renderTime = time.time()

    self.clearBuffer.append(str(clearTime - frameStart))
    self.renderBuffer.append(str(renderTime - clearTime))

如您所见,我计算了 self.clear() 和其余渲染方法的执行时间。 self.clear()的调用调用了pyglet的这个方法,可以在.../pyglet/window/__init__.py找到:

def clear(self):
    '''Clear the window.

    This is a convenience method for clearing the color and depth
    buffer.  The window must be the active context (see `switch_to`).
    '''
    gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)

所以我基本上调用了 glClear()
我在测试游戏时(以 60 FPS)注意到一些帧丢失,所以我添加了上面的代码来测量命令的执行时间,尤其是 glClear() 的执行时间。我发现渲染本身不会超过 10 毫秒。但是 glClear() 的持续时间有点不同,这里是 3 次测量在不同条件下的分布:
Duration of glClear() under different conditions.

洋红色线条表示一帧的时间限制。所以第一行后面的所有内容都意味着丢帧。
glClear() 的执行时间似乎在第一帧过期后有某种“回声”。你能解释一下为什么吗?我怎样才能使通话更快?
不幸的是我不是 OpenGL 专家,所以我感谢大家的每一个建议。 ;)

最佳答案

你的图表是错误的。好吧,至少它不是用于衡量性能的合适图表。永远不要相信 gl*函数在您告诉它时执行,永远不要相信它会像您期望的那样快速执行。

大多数gl*功能不会立即执行,它们不可能。请记住,我们正在与 GPU 打交道,告诉它直接做事很慢。因此,我们改为为 GPU 编写待办事项列表(命令队列),并在我们确实需要 GPU 输出内容时将其转储到 VRAM 中。这个“转储”是称为同步的过程的一部分,我们可以用 glFlush 触发一个。 .不过,OpenGL 是用户友好的(至少与 Vulkan 相比),因此它不依赖于我们显式刷新命令队列。许多gl*完全取决于您的图形驱动程序的函数将隐式同步 CPU 和 GPU 状态,其中包括刷新。

glClear通常会启动一个帧,您的驱动程序可能认为执行这种隐式同步会很好。正如您想象的那样,同步是一个非常缓慢的过程,并且会阻塞 CPU 执行直到完成。

这可能就是这里发生的事情。同步过程的一部分是执行内存事务(如 glBufferDataglTexImage* ),这些事务可能会排队等待,直到它们被您的 glClear 刷新。称呼。这在你的例子中是有意义的;我们可以观察到的尖峰可能是您上传大量 block 数据后的帧数。

但请记住,这只是纯粹的猜测,我也不是这类事情的专家,所以不要相信我的确切细节。 This page在 OpenGL wiki 上是关于这类事情的一个很好的资源。

虽然有一件事是肯定的,但您的 glClear只要您的探查器说它需要,调用就不会花费。您应该使用专用于分析图形的分析器。

关于Python minecraft pyglet glClear() 跳帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38699416/

相关文章:

c++ - 使用着色器绘制多个对象 (GLEW)

java - 如何修复由于加载图像而导致的屏幕闪烁?

python - 对数千个坐标进行反向地理编码以仅获取国家/地区

python - 如何使用 HiddenField 强制转换 WTForms 中的整数数据?

Python Audio Tools 安装问题

java - Jbutton Action 监听器

swift - 如何将 UIView 子类化并在其中添加另一个具有相同框架的 UIView

python - Pickle-加载超过1行的pkl模型文件

qt - 全新 Qt 安装不会运行 Qt 项目,包括许多 Qt 示例项目,如 “shader program not linked” 所示

opengl - 什么样的声音处理算法可以让你做出这样的可视化?