sda*_*das 3 opengl 3d graphics haskell projection
我目前正在使用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)
Run Code Online (Sandbox Code Playgroud)
问题(我相信)是我手动将每个三维点转换为二维,然后使用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
Run Code Online (Sandbox Code Playgroud)
正如您猜对的那样,推出自己的投影算法可能会非常缓慢.此外,除非你正在做一些非常复杂的事情,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.
Run Code Online (Sandbox Code Playgroud)
该lookAt功能改变摄像机的位置和方向,给出摄像机属性.该perspective功能可以获取有关摄像机和窗口的信息,并创建正确的透视投影.如果你发现它不提供关于投影足够的控制,你可以使用frustum来自Graphics.Rendering.OpenGL.GL.CoordTrans代替.
PS.:正确的方法是setup设置一个功能,设置投影矩阵,并在必要时使显示功能改变模型视图矩阵.但是,上面的代码应该可行.
PS2:正如评论中所指出的,实现这一点的方式在很大程度上取决于OpenGL版本,而且我不知道OpenGL支持哪些版本的OpenGL.此实现基于OpenGL 2.1及更低版本.