Compare commits
4 Commits
732a4efd33
...
v0.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f836081564 | ||
|
|
38c7580cc4 | ||
|
|
67202e0f41 | ||
|
|
298a13b60d |
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
result
|
||||||
|
dist-newstyle
|
||||||
44
CHANGELOG.md
Normal file
44
CHANGELOG.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Eventual]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
## [0.2.0] - 2025-12-25
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- 100% documentation coverage
|
||||||
|
- `haskellPackages.hlint` in `flake.nix` dev shell
|
||||||
|
- `README.md`
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- split into the following modules
|
||||||
|
- `GLSL`
|
||||||
|
- `GLSL.Compile`
|
||||||
|
- `GLSL.Internal`
|
||||||
|
- `GLSL.Internal.Compile`
|
||||||
|
- only the former 2 have type-safe gurantees for generated code
|
||||||
|
- most projects should only import the former 2
|
||||||
|
- see sample in `Main.hs`
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- issue where user was expected to correctly type variable declarations
|
||||||
|
- user must now only use the correct constructor
|
||||||
|
- old: `someVar = var (id "some_var") T'float :: Exp T'float`
|
||||||
|
- new: `someVar = var'float $ id "some_var"`
|
||||||
|
|
||||||
|
## [0.1.0] - 2025-12-21
|
||||||
|
|
||||||
|
- initialized project
|
||||||
|
- added `CHANGELOG.md`
|
||||||
29
LICENSE
Normal file
29
LICENSE
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
Copyright (c) 2025, andromeda
|
||||||
|
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
31
README.md
31
README.md
@@ -1 +1,30 @@
|
|||||||
generate type-safe GLSL with this Haskell grammar. Under heavy development.
|
## installation
|
||||||
|
|
||||||
|
#### with Nix:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix run git+https://git.mtgmonkey.net/Andromeda/hs-glsl
|
||||||
|
```
|
||||||
|
|
||||||
|
#### without Nix:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://git.mtgmonkey.net/Andromeda/hs-glsl
|
||||||
|
cd hs-glsl
|
||||||
|
cabal build
|
||||||
|
```
|
||||||
|
|
||||||
|
## usage
|
||||||
|
|
||||||
|
see `src/Main.hs` for an example
|
||||||
|
|
||||||
|
## development
|
||||||
|
|
||||||
|
#### with Nix
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://git.mtgmonkey.net/Andromeda/hs-glsl
|
||||||
|
cd hs-glsl
|
||||||
|
nix develop
|
||||||
|
```
|
||||||
|
|
||||||
|
|||||||
8
flake.lock
generated
8
flake.lock
generated
@@ -2,16 +2,16 @@
|
|||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1764242076,
|
"lastModified": 1766125104,
|
||||||
"narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=",
|
"narHash": "sha256-l/YGrEpLromL4viUo5GmFH3K5M1j0Mb9O+LiaeCPWEM=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "2fad6eac6077f03fe109c4d4eb171cf96791faa4",
|
"rev": "7d853e518814cca2a657b72eeba67ae20ebf7059",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"id": "nixpkgs",
|
"id": "nixpkgs",
|
||||||
"ref": "nixos-unstable",
|
"ref": "nixpkgs-unstable",
|
||||||
"type": "indirect"
|
"type": "indirect"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
22
flake.nix
22
flake.nix
@@ -1,13 +1,29 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "nixpkgs/nixos-unstable";
|
nixpkgs.url = "nixpkgs/nixpkgs-unstable";
|
||||||
};
|
};
|
||||||
outputs = {nixpkgs, ...}: let
|
outputs = {
|
||||||
|
nixpkgs,
|
||||||
|
self,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
in {
|
in {
|
||||||
packages.${system} = {
|
packages.${system} = {
|
||||||
default = pkgs.callPackage ./package.nix {};
|
default =
|
||||||
|
pkgs.haskellPackages.callCabal2nix "hs-glsl" ./. {};
|
||||||
|
};
|
||||||
|
devShells.${system} = {
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
packages = [
|
||||||
|
pkgs.cabal-install
|
||||||
|
pkgs.haskellPackages.hlint
|
||||||
|
];
|
||||||
|
inputsFrom = [
|
||||||
|
self.packages.${system}.default
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
33
hs-glsl.cabal
Normal file
33
hs-glsl.cabal
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
cabal-version: 3.0
|
||||||
|
name: hs-glsl
|
||||||
|
version: 0.2.0
|
||||||
|
homepage: https://git.mtgmonkey.net/Andromeda/hs-glsl
|
||||||
|
license: BSD-3-Clause
|
||||||
|
license-file: LICENSE
|
||||||
|
author: andromeda
|
||||||
|
maintainer: @Andromeda:tchncs.de
|
||||||
|
category: Graphics
|
||||||
|
build-type: Simple
|
||||||
|
common warnings
|
||||||
|
ghc-options:
|
||||||
|
-Wall
|
||||||
|
-Werror
|
||||||
|
library
|
||||||
|
import: warnings
|
||||||
|
build-depends: base >=4.20
|
||||||
|
hs-source-dirs: src
|
||||||
|
exposed-modules: GLSL
|
||||||
|
, GLSL.Compile
|
||||||
|
, GLSL.Internal
|
||||||
|
, GLSL.Internal.Compile
|
||||||
|
default-language: Haskell2010
|
||||||
|
executable hs-glsl
|
||||||
|
import: warnings
|
||||||
|
main-is: Main.hs
|
||||||
|
build-depends: base >=4.20
|
||||||
|
hs-source-dirs: src
|
||||||
|
other-modules: GLSL
|
||||||
|
, GLSL.Compile
|
||||||
|
, GLSL.Internal
|
||||||
|
, GLSL.Internal.Compile
|
||||||
|
default-language: Haskell2010
|
||||||
38
package.nix
38
package.nix
@@ -1,38 +0,0 @@
|
|||||||
{
|
|
||||||
haskellPackages,
|
|
||||||
lib,
|
|
||||||
stdenv,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
ghcExeOptions = "-O -Wall -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N -main-is Language.GLSL.Examples.main";
|
|
||||||
ghcPackages = p: [
|
|
||||||
p.relude
|
|
||||||
p.pretty-simple
|
|
||||||
];
|
|
||||||
in
|
|
||||||
stdenv.mkDerivation {
|
|
||||||
pname = "hs-glsl";
|
|
||||||
version = "0.1.0";
|
|
||||||
src = ./src;
|
|
||||||
nativeBuildInputs = [
|
|
||||||
(haskellPackages.ghcWithPackages ghcPackages)
|
|
||||||
];
|
|
||||||
buildInputs = [
|
|
||||||
];
|
|
||||||
configurePhase = ''
|
|
||||||
'';
|
|
||||||
buildPhase = ''
|
|
||||||
ghc ${ghcExeOptions} ./Language/GLSL/Examples.hs -o ./Main
|
|
||||||
'';
|
|
||||||
installPhase = ''
|
|
||||||
mkdir -p $out/bin
|
|
||||||
cp ./Main $out/bin/hs-glsl
|
|
||||||
'';
|
|
||||||
|
|
||||||
meta = {
|
|
||||||
homepage = "https://mtgmonkey.net";
|
|
||||||
license = lib.licenses.wtfpl;
|
|
||||||
mainProgram = "hs-glsl";
|
|
||||||
platforms = ["x86_64-linux"];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
261
src/GLSL.hs
Normal file
261
src/GLSL.hs
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE FunctionalDependencies #-}
|
||||||
|
{- |
|
||||||
|
- Module : GLSL
|
||||||
|
- Description : DSEL of GLSL
|
||||||
|
- Copyright : 2025 Andromeda
|
||||||
|
- License : BSD 3-Clause
|
||||||
|
- Maintainer : @Andromeda:tchncs.de
|
||||||
|
- Stability : Experimental
|
||||||
|
-}
|
||||||
|
module GLSL
|
||||||
|
( float
|
||||||
|
, bool
|
||||||
|
, vec2
|
||||||
|
, vec3
|
||||||
|
, vec4
|
||||||
|
, normalize
|
||||||
|
, mul
|
||||||
|
, add
|
||||||
|
, dec_var
|
||||||
|
, var'float
|
||||||
|
, var'bool
|
||||||
|
, var'vec2
|
||||||
|
, var'vec3
|
||||||
|
, var'vec4
|
||||||
|
, var'mat4
|
||||||
|
, GLSL.id
|
||||||
|
, mkShaders
|
||||||
|
|
||||||
|
, Type (..)
|
||||||
|
, T'float
|
||||||
|
, T'bool
|
||||||
|
, T'vec2
|
||||||
|
, T'vec3
|
||||||
|
, T'vec4
|
||||||
|
, T'mat4
|
||||||
|
, Exp
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
import GLSL.Internal
|
||||||
|
import Prelude hiding (id)
|
||||||
|
|
||||||
|
-- | statically typed expression; typed wrapper of a dynamic expression
|
||||||
|
-- only exposed through smart constructors
|
||||||
|
newtype Exp a = E DExp deriving Show
|
||||||
|
type E'float = Exp T'float
|
||||||
|
type E'bool = Exp T'bool
|
||||||
|
type E'vec2 = Exp T'vec2
|
||||||
|
type E'vec3 = Exp T'vec3
|
||||||
|
type E'vec4 = Exp T'vec4
|
||||||
|
type E'mat4 = Exp T'mat4
|
||||||
|
|
||||||
|
class Vec2 a where
|
||||||
|
-- | converts some input to a vec2
|
||||||
|
-- some inpu' should be a single value or a tuple of values
|
||||||
|
vec2 :: a -> E'vec2
|
||||||
|
instance Vec2 (E'float, E'float) where
|
||||||
|
vec2
|
||||||
|
( E a
|
||||||
|
, E b)
|
||||||
|
= E $ Lit'vec2 $ E'vec2_2 a b
|
||||||
|
|
||||||
|
class Vec3 a where
|
||||||
|
-- | converts some input to a vec3
|
||||||
|
-- some input should be a single value or a tuple of values
|
||||||
|
vec3 :: a -> E'vec3
|
||||||
|
instance Vec3 (E'float, E'float, E'float) where
|
||||||
|
vec3
|
||||||
|
( E a
|
||||||
|
, E b
|
||||||
|
, E c)
|
||||||
|
= E $ Lit'vec3 $ E'vec3_3 a b c
|
||||||
|
instance Vec3 (E'vec2, E'float) where
|
||||||
|
vec3
|
||||||
|
( E a
|
||||||
|
, E b)
|
||||||
|
= E $ Lit'vec3 $ E'vec3_2 a b
|
||||||
|
instance Vec3 (E'float, E'vec2) where
|
||||||
|
vec3
|
||||||
|
( E a
|
||||||
|
, E b)
|
||||||
|
= E $ Lit'vec3 $ E'vec3_2 a b
|
||||||
|
|
||||||
|
class Vec4 a where
|
||||||
|
-- | converts some input to a vec4
|
||||||
|
-- some input should be a single value or a tuple of values
|
||||||
|
vec4 :: a -> E'vec4
|
||||||
|
instance Vec4 (E'float, E'float, E'float, E'float) where
|
||||||
|
vec4
|
||||||
|
( E a
|
||||||
|
, E b
|
||||||
|
, E c
|
||||||
|
, E d)
|
||||||
|
= E $ Lit'vec4 $ E'vec4_4 a b c d
|
||||||
|
instance Vec4 (E'vec3, E'float) where
|
||||||
|
vec4
|
||||||
|
( E a
|
||||||
|
, E b)
|
||||||
|
= E $ Lit'vec4 $ E'vec4_2 a b
|
||||||
|
instance Vec4 (E'float, E'vec3) where
|
||||||
|
vec4
|
||||||
|
( E a
|
||||||
|
, E b)
|
||||||
|
= E $ Lit'vec4 $ E'vec4_2 a b
|
||||||
|
instance Vec4 (E'vec2, E'float, E'float) where
|
||||||
|
vec4
|
||||||
|
( E a
|
||||||
|
, E b
|
||||||
|
, E c)
|
||||||
|
= E $ Lit'vec4 $ E'vec4_3 a b c
|
||||||
|
instance Vec4 (E'float, E'vec2, E'float) where
|
||||||
|
vec4
|
||||||
|
( E a
|
||||||
|
, E b
|
||||||
|
, E c)
|
||||||
|
= E $ Lit'vec4 $ E'vec4_3 a b c
|
||||||
|
instance Vec4 (E'float, E'float, E'vec2) where
|
||||||
|
vec4
|
||||||
|
( E a
|
||||||
|
, E b
|
||||||
|
, E c)
|
||||||
|
= E $ Lit'vec4 $ E'vec4_3 a b c
|
||||||
|
instance Vec4 (E'vec2, E'vec2) where
|
||||||
|
vec4
|
||||||
|
( E a
|
||||||
|
, E b)
|
||||||
|
= E $ Lit'vec4 $ E'vec4_2 a b
|
||||||
|
|
||||||
|
class Normalize a b | a -> b where
|
||||||
|
-- | wraps some expression in the normalize glsl builtin
|
||||||
|
-- a is the same type as b
|
||||||
|
normalize :: a -> b
|
||||||
|
instance Normalize E'vec2 E'vec2 where
|
||||||
|
normalize (E v) = E $ E'normalize v
|
||||||
|
instance Normalize E'vec3 E'vec3 where
|
||||||
|
normalize (E v) = E $ E'normalize v
|
||||||
|
instance Normalize E'vec4 E'vec4 where
|
||||||
|
normalize (E v) = E $ E'normalize v
|
||||||
|
|
||||||
|
class Add a b c | a b -> c where
|
||||||
|
-- | puts a + between two expressions
|
||||||
|
add :: a -> b -> c
|
||||||
|
instance Add E'float E'float E'float where
|
||||||
|
add (E a) (E b) = E $ E'add a b
|
||||||
|
instance Add E'float E'vec2 E'vec2 where
|
||||||
|
add (E a) (E b) = E $ E'add a b
|
||||||
|
instance Add E'float E'vec3 E'vec3 where
|
||||||
|
add (E a) (E b) = E $ E'add a b
|
||||||
|
instance Add E'float E'vec4 E'vec4 where
|
||||||
|
add (E a) (E b) = E $ E'add a b
|
||||||
|
|
||||||
|
class Mul a b c | a b -> c where
|
||||||
|
-- | puts a * between two expressions
|
||||||
|
mul :: a -> b -> c
|
||||||
|
instance Mul E'float E'float E'float where
|
||||||
|
mul (E a) (E b) = E $ E'mul a b
|
||||||
|
instance Mul E'float E'vec2 E'vec2 where
|
||||||
|
mul (E a) (E b) = E $ E'mul a b
|
||||||
|
instance Mul E'float E'vec3 E'vec3 where
|
||||||
|
mul (E a) (E b) = E $ E'mul a b
|
||||||
|
instance Mul E'float E'vec4 E'vec4 where
|
||||||
|
mul (E a) (E b) = E $ E'mul a b
|
||||||
|
instance Mul E'mat4 E'vec4 E'vec4 where
|
||||||
|
mul (E a) (E b) = E $ E'mul a b
|
||||||
|
|
||||||
|
-- | creates a boolean literal expression
|
||||||
|
bool :: Bool -> E'bool
|
||||||
|
bool x = E $ Lit'bool x
|
||||||
|
|
||||||
|
-- | creates a typed float literal expression
|
||||||
|
float :: Float -> E'float
|
||||||
|
float x = E $ Lit'float x
|
||||||
|
|
||||||
|
-- | creates a variable with type float
|
||||||
|
var'float :: Id -> E'float
|
||||||
|
var'float name = var name T'float
|
||||||
|
|
||||||
|
-- | creates a variable with type bool
|
||||||
|
var'bool :: Id -> E'bool
|
||||||
|
var'bool name = var name T'bool
|
||||||
|
|
||||||
|
-- | creates a variable with type vec2
|
||||||
|
var'vec2 :: Id -> E'vec2
|
||||||
|
var'vec2 name = var name T'vec2
|
||||||
|
|
||||||
|
-- | creates a variable with type vec3
|
||||||
|
var'vec3 :: Id -> E'vec3
|
||||||
|
var'vec3 name = var name T'vec3
|
||||||
|
|
||||||
|
-- | creates a variable with type vec4
|
||||||
|
var'vec4 :: Id -> E'vec4
|
||||||
|
var'vec4 name = var name T'vec4
|
||||||
|
|
||||||
|
-- | creates a variable with type mat4
|
||||||
|
var'mat4 :: Id -> E'mat4
|
||||||
|
var'mat4 name = var name T'mat4
|
||||||
|
|
||||||
|
-- | creates a literal variable object to pass to mkShaders
|
||||||
|
dec_var :: Id -> Type -> Var
|
||||||
|
dec_var name t = Var name t
|
||||||
|
|
||||||
|
-- | creates an Id from a String
|
||||||
|
id :: String -> Id
|
||||||
|
id (c:cs) =
|
||||||
|
let
|
||||||
|
nondigits = ['a'..'z'] ++ ['A'..'Z'] ++ ['_']
|
||||||
|
digits = ['0'..'9']
|
||||||
|
in
|
||||||
|
if elem c nondigits && [] == filter (\e -> notElem e (digits ++ nondigits)) cs
|
||||||
|
then
|
||||||
|
Id (c:cs)
|
||||||
|
else
|
||||||
|
error $ "invalid identifier <" ++ (c:cs) ++ ">"
|
||||||
|
id "" = error "invalid blank identifier <>"
|
||||||
|
|
||||||
|
-- | creates shaders that fulfill the desired behaviour
|
||||||
|
mkShaders
|
||||||
|
:: [Var] -- ^ uniforms
|
||||||
|
-> [(Int, Var)] -- ^ vertex shader inputs
|
||||||
|
-> E'vec4 -- ^ vertex shader gl_Position expression
|
||||||
|
-> [(Var, Exp t)] -- ^ passthrough variables from vertex to fragment shader
|
||||||
|
-> Id -- ^ fragment shader output variable name
|
||||||
|
-> E'vec4 -- ^ fragment shader expression
|
||||||
|
-> (Shader, Shader) -- ^ (vert, frag)
|
||||||
|
mkShaders
|
||||||
|
uniforms
|
||||||
|
vertex_inputs
|
||||||
|
(E gl_Position_expr)
|
||||||
|
passthroughs
|
||||||
|
out_id
|
||||||
|
(E out_expr)
|
||||||
|
=
|
||||||
|
let
|
||||||
|
passthroughVars = map fst passthroughs
|
||||||
|
in
|
||||||
|
( VertexShader
|
||||||
|
Version'330_core
|
||||||
|
vertex_inputs
|
||||||
|
passthroughVars
|
||||||
|
uniforms
|
||||||
|
(E'let (Var (Id "gl_Position") T'vec4) gl_Position_expr
|
||||||
|
: map (\(ft, sd) -> E'let ft (unE sd)) passthroughs)
|
||||||
|
, FragmentShader
|
||||||
|
Version'330_core
|
||||||
|
passthroughVars
|
||||||
|
[Var out_id T'vec4]
|
||||||
|
uniforms
|
||||||
|
[E'let (Var out_id T'vec4) out_expr]
|
||||||
|
)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- internal constructors TODO remove
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
unE :: Exp t -> DExp
|
||||||
|
unE (E a) = a
|
||||||
|
|
||||||
|
var :: Id -> Type -> Exp t
|
||||||
|
var name t = E $ E'var $ Var name t
|
||||||
62
src/GLSL/Compile.hs
Normal file
62
src/GLSL/Compile.hs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
|
{- |
|
||||||
|
- Module : GLSL.Compile
|
||||||
|
- Description : lets prints
|
||||||
|
- Copyright : 2025 Andromeda
|
||||||
|
- License : BSD 3-Clause
|
||||||
|
- Maintainer : @Andromeda:tchncs.de
|
||||||
|
- Stability : Experimental
|
||||||
|
- TODO add internal module
|
||||||
|
-}
|
||||||
|
module GLSL.Compile
|
||||||
|
( uncheckedCompileShader )
|
||||||
|
where
|
||||||
|
|
||||||
|
import GLSL.Internal
|
||||||
|
import GLSL.Internal.Compile
|
||||||
|
|
||||||
|
-- | TODO indents, pretty/ugly printing
|
||||||
|
uncheckedCompileShader :: Shader -> String
|
||||||
|
uncheckedCompileShader
|
||||||
|
(FragmentShader
|
||||||
|
version
|
||||||
|
inputs
|
||||||
|
outputs
|
||||||
|
uniforms
|
||||||
|
body
|
||||||
|
)
|
||||||
|
=
|
||||||
|
(showVersion version) ++
|
||||||
|
"\n" ++
|
||||||
|
(unlines $
|
||||||
|
(map (\a -> a ++ ";") (
|
||||||
|
map showUniform uniforms
|
||||||
|
++ map showIn inputs
|
||||||
|
++ map showOut outputs
|
||||||
|
))
|
||||||
|
++ [ "void main() {" ]
|
||||||
|
++ map (\a -> showDExp a ++ ";") body
|
||||||
|
++ [ "}" ]
|
||||||
|
)
|
||||||
|
uncheckedCompileShader
|
||||||
|
(VertexShader
|
||||||
|
version
|
||||||
|
inputs
|
||||||
|
outputs
|
||||||
|
uniforms
|
||||||
|
body
|
||||||
|
)
|
||||||
|
=
|
||||||
|
showVersion version ++ "\n" ++
|
||||||
|
(unlines $
|
||||||
|
map (\a -> a ++ ";") (
|
||||||
|
map showUniform uniforms
|
||||||
|
++ map showLayoutIn inputs
|
||||||
|
++ map showOut outputs
|
||||||
|
)
|
||||||
|
++ [ "void main() {" ]
|
||||||
|
++ map (\a -> showDExp a ++ ";") body
|
||||||
|
++ [ "}" ]
|
||||||
|
)
|
||||||
93
src/GLSL/Internal.hs
Normal file
93
src/GLSL/Internal.hs
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
|
{-# LANGUAGE FunctionalDependencies #-}
|
||||||
|
{- |
|
||||||
|
- Module : GLSL.Internal
|
||||||
|
- Description : internal (dynamic) representation of GLSL
|
||||||
|
- Copyright : 2025 Andromeda
|
||||||
|
- License : BSD 3-Clause
|
||||||
|
- Maintainer : @Andromeda:tchncs.de
|
||||||
|
- Stability : Experimental
|
||||||
|
-}
|
||||||
|
module GLSL.Internal where
|
||||||
|
|
||||||
|
-- | literal shaders
|
||||||
|
data Shader
|
||||||
|
= VertexShader
|
||||||
|
Version -- ^ version
|
||||||
|
[(Int, Var)] -- ^ inputs in form (layoutIndex, input)
|
||||||
|
[Var] -- ^ outputs
|
||||||
|
[Var] -- ^ uniforms
|
||||||
|
[DExp] -- ^ body
|
||||||
|
| FragmentShader
|
||||||
|
Version -- ^ version
|
||||||
|
[Var] -- ^ inputs
|
||||||
|
[Var] -- ^ outputs
|
||||||
|
[Var] -- ^ uniforms
|
||||||
|
[DExp] -- ^ body
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
-- | version adt
|
||||||
|
data Version
|
||||||
|
= Version'330_core
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
-- | dynamically typed expressions
|
||||||
|
data DExp
|
||||||
|
= Lit'float Float
|
||||||
|
| Lit'bool Bool
|
||||||
|
| Lit'vec2 DExp
|
||||||
|
| Lit'vec3 DExp
|
||||||
|
| Lit'vec4 DExp
|
||||||
|
| E'var Var
|
||||||
|
| E'let Var DExp
|
||||||
|
| E'if DExp DExp DExp
|
||||||
|
| E'add DExp DExp
|
||||||
|
| E'mul DExp DExp
|
||||||
|
| E'normalize DExp
|
||||||
|
|
||||||
|
-- TODO move these somewhere else? maybe
|
||||||
|
| E'vec2_2 DExp DExp
|
||||||
|
| E'vec3_2 DExp DExp
|
||||||
|
| E'vec3_3 DExp DExp DExp
|
||||||
|
| E'vec4_2 DExp DExp
|
||||||
|
| E'vec4_3 DExp DExp DExp
|
||||||
|
| E'vec4_4 DExp DExp DExp DExp
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
-- | stores variable declaration
|
||||||
|
data Var
|
||||||
|
= Var Id Type
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
-- | GLSL types
|
||||||
|
data Type
|
||||||
|
= T'bool
|
||||||
|
| T'float
|
||||||
|
| T'vec2
|
||||||
|
| T'vec3
|
||||||
|
| T'vec4
|
||||||
|
| T'mat4
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
-- | float
|
||||||
|
data T'float
|
||||||
|
|
||||||
|
-- | bool
|
||||||
|
data T'bool
|
||||||
|
|
||||||
|
-- | vec2
|
||||||
|
data T'vec2
|
||||||
|
|
||||||
|
-- | vec3
|
||||||
|
data T'vec3
|
||||||
|
|
||||||
|
-- | vec4
|
||||||
|
data T'vec4
|
||||||
|
|
||||||
|
-- | mat4
|
||||||
|
data T'mat4
|
||||||
|
|
||||||
|
-- | identifier for variables
|
||||||
|
newtype Id = Id String deriving Show
|
||||||
72
src/GLSL/Internal/Compile.hs
Normal file
72
src/GLSL/Internal/Compile.hs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
|
{-# LANGUAGE FunctionalDependencies #-}
|
||||||
|
{- |
|
||||||
|
- Module : GLSL.Internal.Compile
|
||||||
|
- Description : prints
|
||||||
|
- Copyright : 2025 Andromeda
|
||||||
|
- License : BSD 3-Clause
|
||||||
|
- Maintainer : @Andromeda:tchncs.de
|
||||||
|
- Stability : Experimental
|
||||||
|
-}
|
||||||
|
module GLSL.Internal.Compile where
|
||||||
|
|
||||||
|
import GLSL.Internal
|
||||||
|
|
||||||
|
-- | prints version as version header
|
||||||
|
showVersion :: Version -> String
|
||||||
|
showVersion Version'330_core = "#version 330 core"
|
||||||
|
|
||||||
|
-- | prints variable with uniform qualifier
|
||||||
|
showUniform :: Var -> String
|
||||||
|
showUniform var = "uniform " ++ showVar var
|
||||||
|
|
||||||
|
-- | prints variable with in qualifier
|
||||||
|
showIn :: Var -> String
|
||||||
|
showIn var = "in " ++ showVar var
|
||||||
|
|
||||||
|
-- | prints variable with layout (location = <>) in qualifier
|
||||||
|
showLayoutIn :: (Int, Var) -> String
|
||||||
|
showLayoutIn (i, var) = "layout (location = " ++ show i ++ ") in " ++ showVar var
|
||||||
|
|
||||||
|
-- | prints variable with out qualifier
|
||||||
|
showOut :: Var -> String
|
||||||
|
showOut var = "out " ++ showVar var
|
||||||
|
|
||||||
|
-- | prints variable declaration <typ> <name>
|
||||||
|
showVar :: Var -> String
|
||||||
|
showVar (Var name typ) = showType typ ++ " " ++ showId name
|
||||||
|
|
||||||
|
-- | prints a dynamic expression
|
||||||
|
showDExp :: DExp -> String
|
||||||
|
showDExp (Lit'float f) = show f
|
||||||
|
showDExp (E'var (Var name _)) = showId name
|
||||||
|
showDExp (E'let (Var name _) exp0) = showId name ++ " = " ++ showDExp exp0
|
||||||
|
showDExp (E'if cond exp0 exp1) = "if " ++ showDExp cond ++ "\nthen\n" ++ showDExp exp0 ++ "\nelse\n" ++ showDExp exp1
|
||||||
|
showDExp (E'add exp0 exp1) = showDExp exp0 ++ " + " ++ showDExp exp1
|
||||||
|
showDExp (E'mul exp0 exp1) = showDExp exp0 ++ " * " ++ showDExp exp1
|
||||||
|
showDExp (E'normalize exp0) = "normalize(" ++ showDExp exp0 ++ ")"
|
||||||
|
showDExp (Lit'bool cond) = if cond then "true" else "false"
|
||||||
|
showDExp (Lit'vec2 exp0) = showDExp exp0
|
||||||
|
showDExp (Lit'vec3 exp0) = showDExp exp0
|
||||||
|
showDExp (Lit'vec4 exp0) = showDExp exp0
|
||||||
|
showDExp (E'vec2_2 f0 f1) = "vec2(" ++ showDExp f0 ++ ", " ++ showDExp f1 ++ ")"
|
||||||
|
showDExp (E'vec3_2 f0 f1) = "vec3(" ++ showDExp f0 ++ ", " ++ showDExp f1 ++ ")"
|
||||||
|
showDExp (E'vec4_2 f0 f1) = "vec4(" ++ showDExp f0 ++ ", " ++ showDExp f1 ++ ")"
|
||||||
|
showDExp (E'vec3_3 f0 f1 f2) = "vec3(" ++ showDExp f0 ++ ", " ++ showDExp f1 ++ ", " ++ showDExp f2 ++ ")"
|
||||||
|
showDExp (E'vec4_3 f0 f1 f2) = "vec4(" ++ showDExp f0 ++ ", " ++ showDExp f1 ++ ", " ++ showDExp f2 ++ ")"
|
||||||
|
showDExp (E'vec4_4 f0 f1 f2 f3) = "vec4(" ++ showDExp f0 ++ ", " ++ showDExp f1 ++ ", " ++ showDExp f2 ++ ", " ++ showDExp f3 ++ ")"
|
||||||
|
|
||||||
|
-- | toString for Type
|
||||||
|
showType :: Type -> String
|
||||||
|
showType T'bool = "bool"
|
||||||
|
showType T'float = "float"
|
||||||
|
showType T'vec2 = "vec2"
|
||||||
|
showType T'vec3 = "vec3"
|
||||||
|
showType T'vec4 = "vec4"
|
||||||
|
showType T'mat4 = "mat4"
|
||||||
|
|
||||||
|
-- | prints verbatim identifier
|
||||||
|
showId :: Id -> String
|
||||||
|
showId (Id s) = s
|
||||||
@@ -1,271 +0,0 @@
|
|||||||
{-# LANGUAGE NoImplicitPrelude #-}
|
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
|
||||||
|
|
||||||
module Language.GLSL
|
|
||||||
( Program
|
|
||||||
, Expressions
|
|
||||||
, Expression(..)
|
|
||||||
, RequestedGLVersion
|
|
||||||
, RequestedGLType(..)
|
|
||||||
, ParameterQualifier(..)
|
|
||||||
, LayoutQualifier(..)
|
|
||||||
, Variables
|
|
||||||
, VariableName
|
|
||||||
, Variable(..)
|
|
||||||
, GLSLType(..)
|
|
||||||
, generateGLSL
|
|
||||||
, generateCheckedGLSL
|
|
||||||
)
|
|
||||||
where
|
|
||||||
|
|
||||||
-- TODO
|
|
||||||
--
|
|
||||||
-- -[ ] Add support for multiple shaders in sequence
|
|
||||||
-- -[ ] Add check if the previous shader output the next shader's inputs
|
|
||||||
|
|
||||||
-- IMPORTS --
|
|
||||||
|
|
||||||
import Relude
|
|
||||||
|
|
||||||
-- CLASSES --
|
|
||||||
|
|
||||||
class GLSLExpression a where
|
|
||||||
-- should display the token that the type represents
|
|
||||||
toGLSLText :: a -> Text
|
|
||||||
|
|
||||||
instance GLSLExpression Program where
|
|
||||||
toGLSLText expressions =
|
|
||||||
foldr ((<>)) "}\n" $ map (toGLSLText) expressions
|
|
||||||
|
|
||||||
instance GLSLExpression Expression where
|
|
||||||
toGLSLText
|
|
||||||
(VersionDeclaration requestedGLVersion requestedGLType) =
|
|
||||||
"#version " <>
|
|
||||||
(toGLSLText requestedGLVersion) <>
|
|
||||||
" " <>
|
|
||||||
(toGLSLText requestedGLType) <>
|
|
||||||
"\n"
|
|
||||||
toGLSLText
|
|
||||||
(VariableDeclaration
|
|
||||||
(Just (Location location))
|
|
||||||
parameterQualifier
|
|
||||||
(Variable variableName glslType)) =
|
|
||||||
"layout (location = " <>
|
|
||||||
(toGLSLText location) <>
|
|
||||||
") " <>
|
|
||||||
(toGLSLText parameterQualifier) <>
|
|
||||||
" " <>
|
|
||||||
(toGLSLText glslType) <>
|
|
||||||
" " <>
|
|
||||||
variableName <>
|
|
||||||
";\n"
|
|
||||||
toGLSLText
|
|
||||||
(VariableDeclaration
|
|
||||||
Nothing
|
|
||||||
parameterQualifier
|
|
||||||
(Variable variableName glslType)) =
|
|
||||||
(toGLSLText parameterQualifier) <>
|
|
||||||
" " <>
|
|
||||||
(toGLSLText glslType) <>
|
|
||||||
" " <>
|
|
||||||
variableName <>
|
|
||||||
";\n"
|
|
||||||
toGLSLText
|
|
||||||
MainStart =
|
|
||||||
"void main()\n{\n"
|
|
||||||
toGLSLText
|
|
||||||
(VariableAssignment
|
|
||||||
variable0
|
|
||||||
variable1) =
|
|
||||||
(toGLSLText variable0) <>
|
|
||||||
" = " <>
|
|
||||||
(toGLSLText variable1) <>
|
|
||||||
";\n"
|
|
||||||
toGLSLText
|
|
||||||
(DangerousExpression text) =
|
|
||||||
text <>
|
|
||||||
"\n"
|
|
||||||
|
|
||||||
instance GLSLExpression RequestedGLVersion where
|
|
||||||
toGLSLText i = show i
|
|
||||||
|
|
||||||
instance GLSLExpression RequestedGLType where
|
|
||||||
toGLSLText Core = "core"
|
|
||||||
|
|
||||||
instance GLSLExpression ParameterQualifier where
|
|
||||||
toGLSLText In = "in"
|
|
||||||
toGLSLText Out = "out"
|
|
||||||
toGLSLText Uniform = "uniform"
|
|
||||||
|
|
||||||
instance GLSLExpression Variable where
|
|
||||||
toGLSLText GL_POSITION = "gl_Position"
|
|
||||||
toGLSLText (Variable name _) = name
|
|
||||||
|
|
||||||
instance GLSLExpression GLSLType where
|
|
||||||
toGLSLText (GLSLVec4 _) = "vec4"
|
|
||||||
toGLSLText (GLSLVec3 _) = "vec3"
|
|
||||||
toGLSLText (GLSLVec2 _) = "vec2"
|
|
||||||
toGLSLText (GLSLMat4 _) = "mat4"
|
|
||||||
toGLSLText GLSLFloat = "float"
|
|
||||||
|
|
||||||
-- TYPES --
|
|
||||||
|
|
||||||
type Program = Expressions
|
|
||||||
|
|
||||||
-- version declaration
|
|
||||||
|
|
||||||
type RequestedGLVersion = Int
|
|
||||||
data RequestedGLType
|
|
||||||
= Core
|
|
||||||
deriving Show
|
|
||||||
|
|
||||||
-- variables
|
|
||||||
|
|
||||||
data ParameterQualifier
|
|
||||||
= In
|
|
||||||
| Out
|
|
||||||
| Uniform
|
|
||||||
deriving (Eq, Show)
|
|
||||||
|
|
||||||
data LayoutQualifier
|
|
||||||
= Location Int
|
|
||||||
deriving Show
|
|
||||||
|
|
||||||
type Variables = [Variable]
|
|
||||||
type VariableName = Text
|
|
||||||
|
|
||||||
data Variable
|
|
||||||
= Variable
|
|
||||||
VariableName
|
|
||||||
GLSLType
|
|
||||||
| GL_POSITION
|
|
||||||
deriving (Eq, Show)
|
|
||||||
|
|
||||||
data GLSLType
|
|
||||||
= GLSLFloat
|
|
||||||
| GLSLVec4 GLSLType
|
|
||||||
| GLSLVec3 GLSLType
|
|
||||||
| GLSLVec2 GLSLType
|
|
||||||
| GLSLMat4 GLSLType
|
|
||||||
deriving (Eq, Show)
|
|
||||||
|
|
||||||
-- expressions
|
|
||||||
|
|
||||||
type Expressions = [Expression]
|
|
||||||
|
|
||||||
data Expression
|
|
||||||
= VersionDeclaration
|
|
||||||
RequestedGLVersion
|
|
||||||
RequestedGLType
|
|
||||||
| VariableDeclaration
|
|
||||||
(Maybe LayoutQualifier)
|
|
||||||
ParameterQualifier
|
|
||||||
Variable
|
|
||||||
| MainStart
|
|
||||||
| VariableAssignment
|
|
||||||
Variable
|
|
||||||
Variable
|
|
||||||
| DangerousExpression
|
|
||||||
Text
|
|
||||||
deriving Show
|
|
||||||
|
|
||||||
-- errors
|
|
||||||
|
|
||||||
type Check = CheckSuccess -> CheckResult
|
|
||||||
type CheckResult = Either CheckFailure CheckSuccess
|
|
||||||
type CheckSuccess = (Program, [Warn])
|
|
||||||
type CheckFailure = (Error, [Warn])
|
|
||||||
|
|
||||||
data Error
|
|
||||||
= ErrUnimplementedCheckProgram
|
|
||||||
| ErrVariableDeclaredMultipleTimes Variables
|
|
||||||
| ErrVariableOutputUnassigned Variables
|
|
||||||
deriving Show
|
|
||||||
|
|
||||||
data Warn
|
|
||||||
= WarnVariableAssignedMultipleTimes Variable Int
|
|
||||||
| WarnVariableUnassigned Variable
|
|
||||||
deriving Show
|
|
||||||
|
|
||||||
generateGLSL :: Program -> Text
|
|
||||||
generateGLSL = toGLSLText
|
|
||||||
|
|
||||||
generateCheckedGLSL :: Program -> Either CheckFailure (Text, [Warn])
|
|
||||||
generateCheckedGLSL program =
|
|
||||||
case checkProgram (program, []) of
|
|
||||||
Left (e, warnings) -> Left (e, warnings)
|
|
||||||
Right (program, warnings) -> Right (toGLSLText program, warnings)
|
|
||||||
|
|
||||||
checkProgram :: Check
|
|
||||||
checkProgram program
|
|
||||||
= checkVariableDeclaredMultipleTimes program
|
|
||||||
>>= checkVariableOutputUnassigned
|
|
||||||
>>= checkVariableAssignedMultipleTimes
|
|
||||||
>>= checkVariableUnassigned
|
|
||||||
|
|
||||||
-- throws error if variable declared multiple times
|
|
||||||
checkVariableDeclaredMultipleTimes :: Check
|
|
||||||
checkVariableDeclaredMultipleTimes (program, warnings)
|
|
||||||
= case [var | (var, ct) <- counts [v | VariableDeclaration _ _ v <- program]
|
|
||||||
, ct > 1
|
|
||||||
] of
|
|
||||||
[] -> Right (program, warnings)
|
|
||||||
a -> Left (ErrVariableDeclaredMultipleTimes a, warnings)
|
|
||||||
|
|
||||||
-- throws error if `out` variable unassigned
|
|
||||||
checkVariableOutputUnassigned :: Check
|
|
||||||
checkVariableOutputUnassigned (program, warnings)
|
|
||||||
= case
|
|
||||||
[v | v <- [var | VariableDeclaration _ Out var <- program]
|
|
||||||
, not $ elem v [var | VariableAssignment var _ <- program]
|
|
||||||
] of
|
|
||||||
[] -> Right (program, warnings)
|
|
||||||
a -> Left (ErrVariableOutputUnassigned a, warnings)
|
|
||||||
|
|
||||||
-- throws warning if variable assigned multiple times
|
|
||||||
checkVariableAssignedMultipleTimes :: Check
|
|
||||||
checkVariableAssignedMultipleTimes (program, warnings)
|
|
||||||
= case [(var, ct) | (var, ct) <- counts [v | VariableAssignment v _ <- program]
|
|
||||||
, ct > 1
|
|
||||||
] of
|
|
||||||
[] -> Right (program, warnings)
|
|
||||||
a -> Right
|
|
||||||
(program
|
|
||||||
, (map
|
|
||||||
(\(var, ct) -> WarnVariableAssignedMultipleTimes var ct)
|
|
||||||
a) ++ warnings
|
|
||||||
)
|
|
||||||
|
|
||||||
-- throws warning if non-input variable unassigned
|
|
||||||
checkVariableUnassigned :: Check
|
|
||||||
checkVariableUnassigned (program, warnings)
|
|
||||||
= case
|
|
||||||
[WarnVariableUnassigned var | VariableDeclaration _ parameterQualifier var <- program
|
|
||||||
, parameterQualifier /= In
|
|
||||||
, not $ elem var [var | VariableAssignment var _ <- program]
|
|
||||||
] of
|
|
||||||
[] -> Right (program, warnings)
|
|
||||||
a -> Right (program, a ++ warnings)
|
|
||||||
|
|
||||||
-- utilities
|
|
||||||
|
|
||||||
counts :: (Eq a) => [a] -> [(a, Int)]
|
|
||||||
counts arr = counts' arr []
|
|
||||||
|
|
||||||
counts' :: (Eq a) => [a] -> [(a, Int)] -> [(a, Int)]
|
|
||||||
counts' [] cts = cts
|
|
||||||
counts' (x:xs) cts =
|
|
||||||
counts'
|
|
||||||
xs
|
|
||||||
$ if [] == [0 | (a, _) <- cts
|
|
||||||
, a == x
|
|
||||||
]
|
|
||||||
then
|
|
||||||
(x, 1):cts
|
|
||||||
else
|
|
||||||
[(a, ct + 1) | (a, ct) <- cts
|
|
||||||
, a == x
|
|
||||||
] ++
|
|
||||||
[t | t@(a, _) <- cts
|
|
||||||
, a /= x
|
|
||||||
]
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
{-# LANGUAGE NoImplicitPrelude #-}
|
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
|
||||||
|
|
||||||
module Language.GLSL.Examples (main) where
|
|
||||||
|
|
||||||
-- IMPORTS --
|
|
||||||
|
|
||||||
import Text.Pretty.Simple
|
|
||||||
|
|
||||||
import Relude
|
|
||||||
|
|
||||||
import Language.GLSL
|
|
||||||
|
|
||||||
-- MAIN --
|
|
||||||
|
|
||||||
main :: IO ()
|
|
||||||
main = do
|
|
||||||
let a = generateCheckedGLSL fragShader
|
|
||||||
let b = generateCheckedGLSL vertShader
|
|
||||||
pPrint a
|
|
||||||
pPrint b
|
|
||||||
return ()
|
|
||||||
|
|
||||||
fragShader :: Program
|
|
||||||
fragShader =
|
|
||||||
[ VersionDeclaration 450 Core
|
|
||||||
, VariableDeclaration Nothing In fragColorOut
|
|
||||||
, VariableDeclaration Nothing Out fragColor
|
|
||||||
, MainStart
|
|
||||||
, VariableAssignment fragColor fragColorOut
|
|
||||||
]
|
|
||||||
|
|
||||||
vertShader :: Program
|
|
||||||
vertShader =
|
|
||||||
[ VersionDeclaration 450 Core
|
|
||||||
, VariableDeclaration (Just $ Location 0) In vertexPosition
|
|
||||||
, VariableDeclaration (Just $ Location 1) In vertexColor
|
|
||||||
, VariableDeclaration Nothing Out fragColorOut
|
|
||||||
, MainStart
|
|
||||||
, VariableAssignment GL_POSITION vertexPosition
|
|
||||||
, VariableAssignment fragColorOut vertexColor
|
|
||||||
]
|
|
||||||
|
|
||||||
fragColor = Variable "fragColor" $ GLSLVec4 GLSLFloat
|
|
||||||
fragColorOut = Variable "fragColorOut" $ GLSLVec4 GLSLFloat
|
|
||||||
vertexPosition = Variable "vertexPosition" $ GLSLVec4 GLSLFloat
|
|
||||||
vertexColor = Variable "vertexColor" $ GLSLVec4 GLSLFloat
|
|
||||||
50
src/Main.hs
Normal file
50
src/Main.hs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
module Main (main) where
|
||||||
|
|
||||||
|
import Prelude hiding (id)
|
||||||
|
import GLSL
|
||||||
|
import GLSL.Compile
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
let
|
||||||
|
-- variables
|
||||||
|
a_vPos = var'vec3 $ id "a_vPos"
|
||||||
|
v_pos = var'vec3 $ id "v_pos"
|
||||||
|
u_view = var'mat4 $ id "u_view"
|
||||||
|
u_projection = var'mat4 $ id "u_projection"
|
||||||
|
|
||||||
|
-- variable declarations
|
||||||
|
a_vPos' = dec_var (id "a_vPos") T'vec3
|
||||||
|
v_pos' = dec_var (id "v_pos") T'vec3
|
||||||
|
u_view' = dec_var (id "u_view") T'mat4
|
||||||
|
u_projection' = dec_var (id "u_projection") T'mat4
|
||||||
|
|
||||||
|
-- shaders
|
||||||
|
(vert, frag) = mkShaders
|
||||||
|
-- uniforms
|
||||||
|
[ u_view'
|
||||||
|
, u_projection']
|
||||||
|
-- vertex inputs
|
||||||
|
[ (0, a_vPos')]
|
||||||
|
-- gl_Position expression
|
||||||
|
(
|
||||||
|
u_projection `mul` (u_view `mul` vec4 (v_pos, float 1))
|
||||||
|
)
|
||||||
|
-- passthrough
|
||||||
|
[ (v_pos', a_vPos) ]
|
||||||
|
-- output name
|
||||||
|
(id "o_vColor")
|
||||||
|
-- output expression
|
||||||
|
(
|
||||||
|
vec4
|
||||||
|
( float 0.5 `add`
|
||||||
|
float 0.5 `mul`
|
||||||
|
normalize v_pos :: Exp T'vec3
|
||||||
|
, float 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
putStrLn $ show vert
|
||||||
|
putStrLn $ show frag
|
||||||
|
putStrLn $ uncheckedCompileShader vert
|
||||||
|
putStrLn $ uncheckedCompileShader frag
|
||||||
Reference in New Issue
Block a user