OpenGL - Getting Started
This portion of the guide will walk you through implementing the Learn OpenGL lessons in Haskell.
Now, although there is a package on Hackage that's literally called OpenGL, it's actually got a lot of abstractions built over the direct OGL operations, so we don't want to use that. It will be a lot harder to learn what's going on at first if we can't make one-to-one comparisons between the C++ code and our Haskell code whenever possible. Once we know what we're doing, then we can pile on more abstraction layers if we want.
The OpenGL package is built on top of a lower level package called OpenGLRaw, which is much closer to what we want.
However, there's also a package that is simply called gl, which is also a set of low level and direct bindings to the C version of things. You might wonder why gl was developed if there's also OpenGLRaw, and I'll let the author of gl explain the history of that. There is also a ~20min lightning talk about the motivations of gl, and design within Haskell in general, if you're interested.
So we'll be using the gl package. There's a catch though: The OpenGL standard is essentially only for the video card stuff. It doesn't give us a window to display within, or the ability to get user input. For that part of things, you use a wrapper library of some sort. The wrapper library interfaces with whatever OS your program is running on to make a window and generate an OpenGL "Context" for you to work with.
There's a few major options for this (GLUT, SDL, GLFW), and we'll use one called GLFW-b, which is a Haskell package that wraps around the 3.1 version of the GLFW C library. GLFW-b puts everything into a single module, and all the Haskell function names match with the C names of the same function, so it's pretty easy to figure out what's going on. The first lesson of this series will cover all the windowing basics, and after that we'll pretty much focus in on using gl to draw cool things.
Other packages we'll use as they come up, and when they do I'll put a comment in the import section about what packages different imports are from, so you'll be able to check what imports you need when new imports show up. Like this:
-- JuicyPixels import Codec.Picture (readImage, generateImage, convertRGB8, DynamicImage(..), Image(..), PixelRGB8(..))
Note that package names are case sensitive, so in this case you'd have to add "JuicyPixels" specifically, not just "juicypixels".
- Note the capitalization when you try to install GLFW-b in your project, you have to capitalize it "GLFW-b" just like that or stack won't be able to find the package for you.
- Also note that you want the "-b" version of the package, because that's the one that supports the newer version of the GLFW C library.
- If you're on Windows, you'll need to be sure to use GHC 8.0.2 or later (which means lts-8.0 or above, if you're using stack). This is because earlier versions of GHC had some sort of mixup in their packaged version of msys which makes it so GLFW-b can't compile. This is fixed in 8.0.2, so it should work without any trouble.
- GLFW-b is a FFI package, so you'll need the C files for it as well to build it.
- If you're on windows you can use the
pacmanprogram bundled with stack's version of msys2. First update your pacman package list if you haven't done that before, and then install the glfw package. Something like this:
stack exec -- pacman -Syu
stack exec -- pacman -S mingw-w64-x86_64-glfw
- If you're on linux you can probably install those through your package manager. Look for a package named
- If you're on Mac I don't know for sure. Probably use that Homebrew thing that I hear about a lot. This stack overflow says that it should be something like:
brew tap homebrew/versions
brew install --build-bottle --static glfw3
- If you're on windows you can use the
- The gl package itself doesn't depend on any special files you don't already have, since your graphics drivers already provide the OpenGL libraries it will link against. It takes a while to build when you first install it, because it supports the OpenGL so throughly via a lot of automated code generation. Once you've built the package for the first time though you can compile your own programs at normal speed, so it's fine.
Lastly, it's not strictly to do with installation, but I'll note here that if you're on Windows you can use the
-optl-mwindows GHC option to prevent your program from opening a terminal window in the background when it runs. Doing so disables all use of stdout though, even when you do run your program via a terminal, so you probably don't want that flag while you're debugging your program. Just for the final release.