【问题标题】:What is an idiomatic and fast class for objects that can be rendered to screen?对于可以渲染到屏幕的对象,什么是惯用且快速的类?
【发布时间】:2015-09-02 01:39:46
【问题描述】:

我的游戏有非常特殊的图形,不适合 GPU 工作流程,所以我通过将屏幕存储为未装箱的矢量来在 CPU 上进行渲染:

type Pixel = Word32
data Image = Image { size :: V2 Int, buffer :: U.Vector Pixel }

有了这个,我需要一个可以在屏幕上呈现的对象的类。天真的解决方案是:

class Renderable obj where
    -- Receives the object, the render position, and the image.
    render :: obj -> V2 Int -> Image -> Image

但是,很明显,由于render 将复制整个图像,因此这种方法在每帧渲染数百个对象是不切实际的。一个更有效的解决方案是render :: obj -> V2 Int -> [(V2 Int, Pixel)] - 也就是说,您无需实际渲染,而是构建要渲染的像素列表。然后draw loop 只是连接这些列表并使用unboxed vector's bulk updates 一次性渲染所有列表。

但这仍然不理想:分配和连接这些列表的成本可能很高(想象一下具有 128x128 像素的对象),而在通常的语言中,您将拥有一个没有成本的可变函数。为了获得最佳性能,您可以使用类似:render :: (PrimMonad m) => obj -> V2 Int -> MVector (PrimState m) -> IO () - 也就是说,render 直接在可变向量中运行。绘制循环可以直接调用这个函数,不会发生分配。但这会使写render 变得很麻烦。

是否有任何惯用的方法将上一个版本的效率与前一个版本的简单性结合起来?

【问题讨论】:

    标签: performance haskell vector game-engine


    【解决方案1】:

    如果您的大多数对象不重叠,那么您可以为所有可渲染对象构建一个补丁向量(每个补丁是一个仅覆盖对象的图像,加上它在最终图像中的位置),然后使用Data.Vector.Unboxed.generate生成最终图像。 generate 中的函数将查找特定像素位置的最顶部可见补丁。在这种情况下,您分配了很多小向量,但使用的总内存将与最终图像的内存使用量相当(请记住,对象通常不会重叠。)

    如果对象重叠,那么您可以将它们的图像剪切成不重叠的部分。

    (但实际上可变实现并没有错 :))

    【讨论】:

      猜你喜欢
      • 2010-09-21
      • 1970-01-01
      • 2018-05-02
      • 1970-01-01
      • 2017-02-12
      • 2012-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多