如何使用gloss accelerate渲染Mandelbrot集及makePicture函数用法
库选型说明
你之前的判断是正确的,三个库的定位差异如下:
- 纯
accelerate:仅提供嵌入式并行数组计算接口,本身不包含任何图形渲染相关能力,需要自行对接输出逻辑 gloss-accelerate:是gloss和accelerate的基础绑定层,仅提供通用数据结构转换能力,没有针对光栅渲染场景做封装gloss-raster-accelerate:专门针对像素级光栅渲染场景做了封装,刚好适配你生成曼德博集合的需求,是当前场景的最优选择
makePicture函数参数详解 常用版本的函数签名如下:
makePicture :: Int -- 渲染图片的宽度,单位为像素 -> Int -- 渲染图片的高度,单位为像素 -> (Acc (Array DIM2 Word32) -> Acc (Array DIM2 (Word8, Word8, Word8, Word8))) -- 像素值转换函数:输入存储你自定义像素数据的accelerate二维数组,输出RGBA格式的像素数组,四个值分别对应红、绿、蓝、透明度,取值范围0-255 -> Acc (Array DIM2 Word32) -- 你通过accelerate计算得到的原始像素数据数组,这里你可以直接存每个像素的迭代次数 -> Picture -- 输出gloss可用的Picture对象,直接传入display/animate等函数即可展示
注:如果你的迭代次数最大值不超过255,可以把签名里的Word32替换为Word8,类型匹配即可
适配场景的可运行示例
依赖配置
你需要先在项目的cabal文件或stack配置中添加以下依赖:
accelerateaccelerate-llvm-native(CPU后端,所有设备通用)accelerate-llvm-ptx(可选,NVIDIA GPU后端,需要CUDA环境)glossgloss-raster-accelerate
完整代码
import Graphics.Gloss import Graphics.Gloss.Accelerate.Raster.Array import Data.Array.Accelerate as A -- 用CPU后端计算,要换GPU的话把下面的导入替换为 import Data.Array.Accelerate.LLVM.PTX as GPU import Data.Array.Accelerate.LLVM.Native as CPU -- 曼德博集合迭代逻辑,输入复平面坐标,输出迭代次数 mandelIter :: Exp (Float, Float) -> Exp Word8 mandelIter p = go 0 0 0 where go :: Exp Int -> Exp Float -> Exp Float -> Exp Word8 go n x y | n >= 255 || x*x + y*y > 4 = A.fromIntegral n | otherwise = go (n+1) (x*x - y*y + fst p) (2*x*y + snd p) -- 像素坐标转复平面坐标,这里的800、600对应渲染分辨率,可自行调整 pixelToComplex :: Exp DIM2 -> Exp (Float, Float) pixelToComplex ix = A.lift (x, y) where Z :. yPix :. xPix = A.unlift ix x = (A.fromIntegral xPix / 800 * 3.5) - 2.5 y = (A.fromIntegral yPix / 600 * 2.0) - 1.0 -- 迭代次数转RGBA颜色,可自行调整配色逻辑 iterToColor :: Exp Word8 -> Exp (Word8, Word8, Word8, Word8) iterToColor n = A.lift (r, g, b, 255) where r = n g = n * 2 b = n * 3 main :: IO () main = do let width = 800 height = 600 -- 并行生成所有像素的迭代次数数组 iterArr = A.generate (A.constant (Z :. height :. width)) (\ix -> mandelIter (pixelToComplex ix)) -- 构建gloss可用的Picture对象 pic = makePicture width height (A.map iterToColor) iterArr -- 窗口展示 display (InWindow "Mandelbrot" (width, height) (100, 100)) white pic
优化提示
- 所有计算逻辑都放在accelerate的
Acc上下文中实现,避免CPU和GPU之间的频繁数据拷贝,能最大化并行性能 - 如果需要实现交互式缩放、平移功能,只需将缩放比例、偏移量作为参数传入
pixelToComplex函数,配合gloss的play函数即可实现
内容的提问来源于stack exchange,提问作者Modi57
相关产品推荐
相关产品推荐

