3

我正在制作一款游戏,我实际上是在生成地图。

该地图是使用一些算法程序生成的。这没有问题。

问题是我的地图可能很大。所以我考虑过将地图切成块。

我的块没问题,它们每个都是 512*512 像素,但唯一的问题是:我必须生成一个纹理(实际上是 SFML 的 RenderTexture)。生成大约需要 0.5 毫秒,因此每次生成块时游戏都会冻结。

我想了一种方法来解决这个问题:我用工厂制作了一种线程池。我只需要向它发送一个任务,它就会创建块。

现在它已经全部实现了,它会引发 opengl 警告,例如:

“RenderTarget.cpp (219) 中的内部 OpenGL 调用失败:GL_INVALID_OPERATION,当前状态下不允许指定的操作”。

我不知道这是否是处理块的好方法。我也考虑过将块保存到图像/文件中,但我担心保存/加载它们需要太多时间。

你知道处理这种“无限”地图的更好方法吗?

4

2 回答 2

2

things to try:

  • make your chunks smaller
  • generate the chunks in a separate thread, but pass to the gpu from the main thread
  • pass to the gpu a small piece at a time, taking a second or two
于 2013-12-16T02:01:06.417 回答
2

这是一个无效操作,因为您必须将上下文绑定到每个线程。更重要的是,所有 GL 窗口系统 API 都在线程和上下文之间强制执行严格的 1:1 映射……没有线程可以绑定多个上下文,也没有上下文可以绑定到多个线程。您需要做的是使用共享上下文(一个用于绘制的上下文,一个用于每个工作线程),缓冲区对象和纹理等内容将在所有共享上下文之间共享,但状态机和容器对象(如 FBO 和 VAO)不会。

您是在为这张地图使用平铺渲染,还是这只是一个巨大的纹理?

如果您不需要更新“块”图像的各个子区域,您可以简单地在工作线程中创建新纹理。工作线程可以创建新的纹理并在绘图线程执行其业务时为其提供数据。只有在工作线程完成后,您才会真正尝试使用其中一个块进行绘制。这可能会增加块开始加载和最终出现​​在完成场景中的时间之间的整体延迟,但您应该获得更一致的帧速率。

如果您需要为此使用单个纹理,我建议您对纹理进行双重缓冲。有一个在绘图线程中使用,另一个在您的工作线程上发布glTexSubImage2D (...)。当工作线程完成更新其纹理区域时,您可以交换用于绘制和更新的纹理。这将减少所需的同步量,但会再次增加更新最终出现在屏幕上之前的延迟。

于 2013-12-16T02:43:32.153 回答