add syntax
This commit is contained in:
121
posts/20251218-glsl-edsl-p1.md
Normal file
121
posts/20251218-glsl-edsl-p1.md
Normal file
@@ -0,0 +1,121 @@
|
||||
---
|
||||
layout: default.liquid
|
||||
|
||||
title: 2025-12-18 GLSL EDSL in Haskell part 1
|
||||
description: first part of GLSL EDSL development series. We initialize the project and do some planning.
|
||||
is_draft: true
|
||||
---
|
||||
|
||||
all code for this project is available [here](https://git.mtgmonkey.net/Andromeda/hs-glsl). Please contact me if you want an account for contribution or to file issues.
|
||||
|
||||
#### goals of this project
|
||||
|
||||
I want to generate [GLSL]() from the type-safe environment of Haskell with an [EDSL](). Specifically, I want to functionally declare the glsl shader code I use in my [game](https://git.mtgmonkey.net/Andromeda/hs-game).
|
||||
|
||||
At the moment, that's quite a lot. Let's start with a practically bare Haskell/OpenGL project. Let's build our development environment.
|
||||
|
||||
``` bash
|
||||
mkdir hs-glsl
|
||||
cd hs-glsl
|
||||
|
||||
# get initial dependencies
|
||||
nix-shell -p cabal-install ghc
|
||||
cabal init
|
||||
# all defaults are ok for our needs EXCEPT the following:
|
||||
# Application directory: I chose 4 then put `src`
|
||||
# Version: I chose 0.1.0, breaking with PVP in
|
||||
# favor of Semantic Versioning
|
||||
# Category: Graphics
|
||||
# I also entered my contact, username, and homepage
|
||||
```
|
||||
|
||||
Great, now we have a `hs-glsl.cabal`, the file that defines our project. Cabal also created a number of other files and directories, namely `src/Main.hs` and `LICENSE`. Running the command `cabal run` will run the project, but it isn't reproducable; how can we do it with Nix? We can create a nix flake as follows:
|
||||
|
||||
``` nix
|
||||
# flake.nix
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "nixpkgs/nixpkgs-unstable";
|
||||
};
|
||||
outputs = {
|
||||
nixpkgs, self, ...
|
||||
}: let
|
||||
system = "x86_64-linux";
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
in {
|
||||
packages.${system} = {
|
||||
default =
|
||||
pkgs.haskellPackages.callCabal2nix "hs-glsl" {};
|
||||
};
|
||||
devShells.${system} = {
|
||||
default = pkgs.mkShell {
|
||||
packages = [
|
||||
pkgs.cabal-install
|
||||
];
|
||||
inputsFrom = [
|
||||
self.packages.${system}.default
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
now `nix develop` puts us in a shell with all of out dependencies, and `nix run` should run the program. Let's use [GLFW-b]() to create a window:
|
||||
|
||||
``` yaml
|
||||
# hs-glsl.cabal
|
||||
...
|
||||
executable hs-glsl
|
||||
...
|
||||
build-depends:
|
||||
base ^>=4.20.2.0
|
||||
, GLFW-b <1000
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
``` hs
|
||||
-- | src/Main.hs
|
||||
module Main (main) where
|
||||
|
||||
-- | windowing library
|
||||
import qualified Graphics.UI.GLFW as GLFW
|
||||
|
||||
-- | main
|
||||
main :: IO ()
|
||||
main = do
|
||||
-- initialize GLFW
|
||||
_ <- GLFW.init
|
||||
GLFW.defaultWindowHints
|
||||
|
||||
-- we use GLSL version 3.3 Core here
|
||||
GLFW.windowHint $ GLFW.WindowHint'ContextVersionMajor 3
|
||||
GLFW.windowHint $ GLFW.WindowHint'ContextVersionMinor 3
|
||||
GLFW.windowHint $ GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core
|
||||
|
||||
-- monitor required to fullscreen at start
|
||||
monitor <- GLFW.getPrimaryMonitor
|
||||
|
||||
-- actually create the window
|
||||
Just window <- GLFW.createWindow 256 256 "hs-glsl" monitor Nothing
|
||||
GLFW.makeContextCurrent $ Just window
|
||||
|
||||
-- enter loop
|
||||
loop window
|
||||
|
||||
-- | loop that runs every frame
|
||||
loop :: GLFW.Window -> IO ()
|
||||
loop window = do
|
||||
-- swap to next framebuffer
|
||||
GLFW.swapBuffers window
|
||||
|
||||
-- call next frame
|
||||
loop window
|
||||
```
|
||||
|
||||
Great, a fullscreen window that never closes! I'll go ahead and add a quick key callback so that pressing `esc` closes the program.
|
||||
|
||||
```
|
||||
-- | src/Main.hs
|
||||
Reference in New Issue
Block a user