【问题标题】:How do I handle perspective projections in OpenGL?如何在 OpenGL 中处理透视投影?
【发布时间】:2013-11-12 04:20:20
【问题描述】:

我目前正在使用 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

【问题讨论】:

  • opengl 是一个光栅器,它会为你完成所有的投影。查看GLFW-b-demo 以获得相当简洁的演示
  • “我的问题是:我应该提供 OpenGL 三维点,然后使用 OpenGL 已经烘焙的任何投影吗?”很有可能,但由于缺乏细节,我很难说。你想要完成什么,你目前是如何做到的?您提供了一些粗略的伪代码,但告诉我们更多有关您正在使用的确切 API 调用的信息会有所帮助。也不清楚您要渲染什么。
  • @JasonDagit 我在我的代码示例中进行了编辑 - 希望这更有意义。我的目标是在三维空间中绘制一堆顶点(points)。然后,我想监听按键并在该空间内移动 Camera 对象。点应根据相机的位置和角度进行渲染。
  • 只是为了确定:您是否推出了自己的(基于 CPU 的)投影算法?
  • 是的,这可能非常慢。

标签: opengl haskell graphics 3d projection


【解决方案1】:

您猜对了,推出自己的投影算法可能会非常缓慢。此外,除非您正在做一些极其复杂的事情,否则 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 是一个函数,它获取有关相机和窗口的信息,并创建适当的透视投影。如果您发现它无法对投影进行足够的控制,您可以改用 Graphics.Rendering.OpenGL.GL.CoordTrans 中的 frustum

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

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

【讨论】:

  • 感谢您的回答。不过,我更愿意以 OpenGL 3+ 为目标。
  • @sdasdadas OpenGL 2.1 在大多数系统中默认启用,如果驱动程序允许,您可以使用其他版本。如果你真的想以它们为目标,你可以创建着色器并对它们进行所有转换。不过,对 API 的粗浅了解告诉我,haskell 并不(完全)支持它。
  • 我明白了 - 好吧,那么我会接受这个答案,因为它很有帮助。顺便说一句,我也发现这很有用(虽然我不知道它使用的是哪个版本的 OpenGL):yannesposito.com/Scratch/en/blog/Haskell-OpenGL-Mandelbrot
猜你喜欢
  • 2012-05-15
  • 2013-11-26
  • 2013-04-17
  • 2016-02-11
  • 2011-06-07
  • 1970-01-01
  • 1970-01-01
  • 2015-08-25
  • 1970-01-01
相关资源
最近更新 更多