3

我目前正在使用 Haskell 的 OpenGL 绑定编写一个基本的渲染演示。问题是它几乎不能处理 2000 多个顶点。我的伪代码相当于:

terrain = The set of points generated from [-1...1] x [-1...1] x [-1...1].
camera = Camera at position (xc, yc) with angles (ax, ay, az).
while running:
    input = anything that moves the camera's position or angles
    projected = []
    for point in terrain:
        projected.append(camera.perspectiveProjection(point))
    renderPoints(projected)

问题(我相信)是我手动将我的三维点中的每一个转换为二维,然后使用 OpenGL 来绘制这些点。

我的问题是:我应该喂 OpenGL 三维点,然后使用 OpenGL 已经烘焙的任何投影吗?

(我觉得我理解透视投影的工作原理——我只是不确定我是否应该手动执行此操作。)

编辑:

以下大部分是我的代码。我已经省略了我认为不言自明的部分,只给出了函数定义。

main :: IO()
main = do
    (_progName, _args) <- getArgsAndInitialize
    initialDisplayMode $= [DoubleBuffered]
    _window <- createWindow "Hello, World"
    -- The camera position followed by pitch, yaw and roll.
    camera <- newIORef Camera [0,0,0] 0 0 0
    displayCallback $= display camera
    mainLoop

display :: IORef Camera -> DisplayCallback
display camIO = do
    camera <- get camIO
    clear [ColorBuffer, DepthBuffer]
    clear [ColorBuffer]
    renderPrimitive Points $ mapM_ vertex 
        $ map perspectiveProjection camera points
    swapBuffers
    postRedisplay Nothing
4

1 回答 1

5

正如您猜对的那样,推出自己的投影算法可能会非常慢。此外,除非您正在做一些极其复杂的事情,否则 OpenGL(或更具体地说是 GLU)有一组函数可以解决您的大部分问题。

进行传统透视投影的最简单方法是使用带有位置、观察点和向上矢量的相机。就个人而言,我发现这比使用旋转角度定义相机轴更简单。一旦你有了这个,你可以有你的显示功能是这样的:

import Graphics.Rendering.OpenGL.GLU.Matrix

display :: IORef Camera -> DisplayCallback
display camIO = do
    camera <- get camIO
    perspective fov aspect zNear zFar
    lookAt (position camera) (lookAt camera) (upVector camera)
    -- call clear functions
    -- call renderPrimitive with the untransformed points.

lookAt函数改变相机位置和方向,赋予相机属性。该perspective函数获取有关相机和窗口的信息,并创建适当的透视投影。如果您发现它没有对投影提供足够的控制,您可以使用frustumfromGraphics.Rendering.OpenGL.GL.CoordTrans代替。

PS.:正确的方法是有一个setup函数,它设置投影矩阵,并在必要时让显示函数改变模型视图矩阵。但是,上面的代码应该可以工作。

PS2.:正如评论中指出的那样,实现这一点的方式很大程度上取决于 OpenGL 版本,我不知道 OpenGL haskell 支持哪些版本。此实现基于 OpenGL 2.1 及更低版本。

于 2013-11-12T11:07:19.277 回答