Review
Well we've made it to the end of the first arc. From here on out you should be able to make your own projects if you want. I'll try to do more lesson conversions and go over them, but now that you've seen the basics of how to use the Foreign module and the gl package a lot of it should be obvious enough.
Remember that opengl is a very stateful protocol and you have to pay more attention to it because GHC can't watch things for you as much as it normally can. OGL will happily let you pass a Vertex Buffer Object to a function that needs a Vertex Array Object instead and you'll get a blank screen or possibly a crash. Then you have to put glGetError all over to try and figure out what went wrong, or press "undo" in the editor over and over until you're back at a point where things did work and try again. It's not the best, it's just what we've got.
Also, I didn't do too much of it so far, but don't be afraid to create your own abstractions over top of gl according to the needs of your program. Remember that newtype is a "zero cost" abstraction, and it can make your life a lot easier than having everything be GLuint
. It takes a little work to set up, but it's usually worth it once your project gets above even just a few hundred lines.
You can also make the FFI portion of things easier by building upon the with
functions that help you manage memory bits. Here's a sample:
safeGenBuffers :: MonadIO m => Int -> m [GLuint]
safeGenBuffers n = do
liftIO $ allocaArray n $ \arrP -> do
glGenBuffers (fromIntegral n) arrP
(peekArray n arrP)
safeGenVertexArrays :: MonadIO m => Int -> m [GLuint]
safeGenVertexArrays n = do
liftIO $ allocaArray n $ \arrP -> do
glGenVertexArrays (fromIntegral n) arrP
(peekArray n arrP)
safeGenTextures :: MonadIO m => Int -> m [GLuint]
safeGenTextures n = do
liftIO $ allocaArray n $ \arrP -> do
glGenTextures (fromIntegral n) arrP
(peekArray n arrP)
We could also use newtype and stuff to make them each return a distinct type, instead of all being a GLuint, but we're already doing a lot better than a raw gl call I think. You can't always have the types save you. Immediately below glGetError
in the gl
docs, for example, is glGetFloatv, and it has 387 valid possible enums that you can pass it. So you can't always be perfectly type safe, but some safety is still better than none.
And check out the Learn OpenGL - Review page for a glossary of terms if you forget what anything's about.
There's a finalized "release" of all the code so far on Github
Extras
I also found a really sweet looking site called TheBookOfShaders.com, which goes into all sorts of detail about shader programming. I haven't tried it out myself yet, but it seems like a great next place to look if shaders are what you're after. It's got an ambitious table of contents laid out, and only some of their complete plan is done, but there's already a good number of articles available.