【发布时间】: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