我在Haskell中有这个功能(我正在使用Haskell-SDL库):
pixel :: Surface -> Int16 -> Int16 -> Pixel -> IO Bool
pixel screen x y color
我想使用它来获取2D数组(或其他类型的数据结构)并将其绘制到屏幕上,一次一个像素。我调查了forM_
,但无法弄清楚如何让它对x和y参数进行操作。
我对Haskell和一般的函数式编程都很陌生。我正在通过Yet Another Haskell Tutorial工作,但这个问题让我感到难过。
如果它与解决方案相关,我正在尝试编写光线跟踪器。它必须对每个像素执行计算,然后将该像素写入屏幕。
答案 0 :(得分:3)
如果您使用的是嵌套列表,请执行以下操作:
import Control.Monad
plot :: Surface -> [[Pixel]] -> IO ()
plot surf = zipWithM_ (\ y -> zipWithM_ (\ x c -> pixel surf x y c) [0..]) [0..]
答案 1 :(得分:2)
Haskell有各种各样的真实数组。对我来说,你似乎在做一些非常低效的事情,你想创建一个像素缓冲区并将其blit到另一个缓冲区?创建一个新的SDL表面(你可以获得/设置像素)并将其blit到另一个表面/屏幕或创建一个真实的像素阵列并创建SDL表面然后使用SDL的blit例程会更有效。如果你解释一下你想要做什么,我想我们可以向你展示更好的方法。
答案 2 :(得分:0)
你需要在这里分解两个问题。首先,您需要计算像素值。这应该是场景的纯函数以及射入其中的光线的坐标。然后你需要将该像素值写入屏幕。
首先你想要一个功能:
type Coord = (Int, Int)
raytrace :: Scene -> Coord -> (Coord, Colour)
-- You will see why it returns this pair in a few lines
然后你想为表面中的每个像素调用该函数,以获得坐标颜色对的列表:
allCoords :: Int -> Int -> [Coord]
allCoords width height = [(x,y) | x <- [0..width], y <- [0..height]]
allPixels :: Scene -> Int -> Int -> [(Coord, Colour)]
allPixels scene w h = map (raytrace scene) (allCoords w h)
最后使用“像素”功能将像素列表放在显示表面上。
writeScene :: Surface -> Scene -> Int -> Int -> IO ()
writeScene surface scene w h = mapM_ writePixel (allPixels scene w h)
where writePixel ((x,y),c) = pixel surface x y c
唯一的问题是,你的“像素”函数会返回“IO Bool”。我不知道为什么,所以我通过使用“mapM_”而不是“mapM”来忽略它。
这看起来它构建了一个非常低效的坐标颜色对列表,然后迭代它来绘制图片。但事实上,由于Haskell的惰性,它实际上编译成一个循环,生成每种颜色,然后在结果上调用“像素”。