hylogen 0.1.0.5 → 0.1.0.6
raw patch · 7 files changed
+467/−103 lines, 7 filesdep +vector-spacePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: vector-space
API changes (from Hackage documentation)
+ Hylogen.Globals: backBuffer :: Texture
+ Hylogen.Globals: ceil_ :: (HyloPrim a) => a -> a
+ Hylogen.Globals: clamp :: (HyloPrim a) => a -> a -> a -> a
+ Hylogen.Globals: eq :: (HyloPrim v) => v -> v -> Booly
+ Hylogen.Globals: false :: Booly
+ Hylogen.Globals: floor_ :: (HyloPrim a) => a -> a
+ Hylogen.Globals: geq :: (HyloPrim v) => v -> v -> Booly
+ Hylogen.Globals: gt :: (HyloPrim v) => v -> v -> Booly
+ Hylogen.Globals: inverseSqrt :: (HyloPrim a) => a -> a
+ Hylogen.Globals: leq :: (HyloPrim v) => v -> v -> Booly
+ Hylogen.Globals: linexp :: (Floating a) => (a, a, a, a) -> a -> a
+ Hylogen.Globals: linlin :: (Floating a) => (a, a, a, a) -> a -> a
+ Hylogen.Globals: lt :: (HyloPrim v) => v -> v -> Booly
+ Hylogen.Globals: max_ :: (HyloPrim a) => a -> a -> a
+ Hylogen.Globals: min_ :: (HyloPrim a) => a -> a -> a
+ Hylogen.Globals: neq :: (HyloPrim v) => v -> v -> Booly
+ Hylogen.Globals: true :: Booly
+ Hylogen.Globals: uvN :: Vec2
+ Hylogen.Types: Bbop :: String -> Booly -> Booly -> Booly
+ Hylogen.Types: Bcomp :: String -> a -> a -> Booly
+ Hylogen.Types: Bu :: String -> Booly
+ Hylogen.Types: Buop :: String -> Booly -> Booly
+ Hylogen.Types: Buoppre :: String -> Booly -> Booly
+ Hylogen.Types: Texture2D :: Texture -> Vec2 -> Vec4
+ Hylogen.Types: Tu :: String -> Texture
+ Hylogen.Types: V1select :: Booly -> Vec1 -> Vec1 -> Vec1
+ Hylogen.Types: V2bop :: String -> Vec2 -> Vec2 -> Vec2
+ Hylogen.Types: V2boppre :: String -> Vec2 -> Vec2 -> Vec2
+ Hylogen.Types: V2bops :: String -> Vec1 -> Vec2 -> Vec2
+ Hylogen.Types: V2select :: Booly -> Vec2 -> Vec2 -> Vec2
+ Hylogen.Types: V2uop :: String -> Vec2 -> Vec2
+ Hylogen.Types: V2uoppre :: String -> Vec2 -> Vec2
+ Hylogen.Types: V3bop :: String -> Vec3 -> Vec3 -> Vec3
+ Hylogen.Types: V3boppre :: String -> Vec3 -> Vec3 -> Vec3
+ Hylogen.Types: V3bops :: String -> Vec1 -> Vec3 -> Vec3
+ Hylogen.Types: V3select :: Booly -> Vec3 -> Vec3 -> Vec3
+ Hylogen.Types: V3uop :: String -> Vec3 -> Vec3
+ Hylogen.Types: V3uoppre :: String -> Vec3 -> Vec3
+ Hylogen.Types: V4bop :: String -> Vec4 -> Vec4 -> Vec4
+ Hylogen.Types: V4boppre :: String -> Vec4 -> Vec4 -> Vec4
+ Hylogen.Types: V4bops :: String -> Vec1 -> Vec4 -> Vec4
+ Hylogen.Types: V4select :: Booly -> Vec4 -> Vec4 -> Vec4
+ Hylogen.Types: V4uop :: String -> Vec4 -> Vec4
+ Hylogen.Types: V4uoppre :: String -> Vec4 -> Vec4
+ Hylogen.Types: class (Show v) => HyloPrim v
+ Hylogen.Types: data Booly
+ Hylogen.Types: data Texture
+ Hylogen.Types: fromVec1 :: HyloPrim v => Vec1 -> v
+ Hylogen.Types: instance Data.AdditiveGroup.AdditiveGroup Hylogen.Types.Vec1
+ Hylogen.Types: instance Data.AdditiveGroup.AdditiveGroup Hylogen.Types.Vec2
+ Hylogen.Types: instance Data.AdditiveGroup.AdditiveGroup Hylogen.Types.Vec3
+ Hylogen.Types: instance Data.AdditiveGroup.AdditiveGroup Hylogen.Types.Vec4
+ Hylogen.Types: instance Data.VectorSpace.VectorSpace Hylogen.Types.Vec1
+ Hylogen.Types: instance Data.VectorSpace.VectorSpace Hylogen.Types.Vec2
+ Hylogen.Types: instance Data.VectorSpace.VectorSpace Hylogen.Types.Vec3
+ Hylogen.Types: instance Data.VectorSpace.VectorSpace Hylogen.Types.Vec4
+ Hylogen.Types: instance GHC.Float.Floating Hylogen.Types.Vec2
+ Hylogen.Types: instance GHC.Float.Floating Hylogen.Types.Vec3
+ Hylogen.Types: instance GHC.Float.Floating Hylogen.Types.Vec4
+ Hylogen.Types: instance GHC.Num.Num Hylogen.Types.Booly
+ Hylogen.Types: instance GHC.Num.Num Hylogen.Types.Vec2
+ Hylogen.Types: instance GHC.Num.Num Hylogen.Types.Vec3
+ Hylogen.Types: instance GHC.Num.Num Hylogen.Types.Vec4
+ Hylogen.Types: instance GHC.Real.Fractional Hylogen.Types.Vec2
+ Hylogen.Types: instance GHC.Real.Fractional Hylogen.Types.Vec3
+ Hylogen.Types: instance GHC.Real.Fractional Hylogen.Types.Vec4
+ Hylogen.Types: instance GHC.Show.Show Hylogen.Types.Booly
+ Hylogen.Types: instance GHC.Show.Show Hylogen.Types.Texture
+ Hylogen.Types: instance Hylogen.Types.HyloPrim Hylogen.Types.Vec1
+ Hylogen.Types: instance Hylogen.Types.HyloPrim Hylogen.Types.Vec2
+ Hylogen.Types: instance Hylogen.Types.HyloPrim Hylogen.Types.Vec3
+ Hylogen.Types: instance Hylogen.Types.HyloPrim Hylogen.Types.Vec4
+ Hylogen.Types: select :: HyloPrim v => Booly -> v -> v -> v
+ Hylogen.Types: vbop :: HyloPrim v => String -> v -> v -> v
+ Hylogen.Types: vboppre :: HyloPrim v => String -> v -> v -> v
+ Hylogen.Types: vec :: HyloPrim v => HyloConstructor v -> v
+ Hylogen.Types: vu :: HyloPrim v => String -> v
+ Hylogen.Types: vuop :: HyloPrim v => String -> v -> v
+ Hylogen.Types: vuoppre :: HyloPrim v => String -> v -> v
- Hylogen.Globals: fract :: Vec1 -> Vec1
+ Hylogen.Globals: fract :: (HyloPrim a) => a -> a
Files
- README.md +14/−9
- app/Main.hs +8/−21
- app/index.html +79/−22
- hylogen.cabal +4/−3
- src/Hylogen.hs +1/−10
- src/Hylogen/Globals.hs +61/−10
- src/Hylogen/Types.hs +300/−28
README.md view
@@ -1,38 +1,43 @@-# [*H Y L O G E N*](http://hylogen.com)+# [*H Y L O G E N*](https://hylogen.com) -Hylogen is a tiny language [embedded in Haskell](https://wiki.haskell.org/Embedded_domain_specific_language) for live-coding visuals.+Hylogen is a language [embedded in Haskell](https://wiki.haskell.org/Embedded_domain_specific_language) for live-coding visuals in WebGL. ## Setup ``` cabal update cabal install hylogen ```+ ## Usage ```haskell -- ./Main.hs module Main where- import Hylogen +main = putStrLn $ toGLSL $ color -main = putStrLn . toGLSL $ Vec4 (a, a, a, 1)+color = vec (a, a, a, 1) where- a = cos(X uv * sin(time/ 10) * 10 + X mouse)- + sin(Y uv * sin(time / 10) * 10 + Y mouse)+ a = cos(X uvN * sin(time/ 10) * 10 + X mouse)+ + sin(Y uvN * sin(time / 10) * 10 + Y mouse) ``` -#### run hylogen+#### 1. run hylogen ``` hylogen Main.hs ``` -#### play!+#### 2. play! Go to [localhost:5678](http://localhost:5678) in your browser. Changes in `Main.hs` will now be propagated in realtime to your shader! ## inspiration-- [The_Force](https://github.com/shawnlawson/The_Force).+- [The_Force](https://github.com/shawnlawson/The_Force) +## resources+[hackage](https://hackage.haskell.org/package/hylogen)++[examples](https://github.com/sleexyz/hylogen-yay)
app/Main.hs view
@@ -23,11 +23,14 @@ main :: IO () main = getArgs >>= \case- [pathToWatch] -> do- _ <- forkIO $ serveIndex- runServer "127.0.0.1" 8080 $ handleConnection pathToWatch- _ -> error "Name a file to watch!"+ [pathToWatch] -> main' pathToWatch+ _ -> error "Name a file to watch!" +main' :: FilePath -> IO ()+main' pathToWatch = do+ _ <- forkIO $ serveIndex+ runServer "127.0.0.1" 8080 $ handleConnection pathToWatch+ handleConnection :: FilePath -> PendingConnection -> IO () handleConnection pathToWatch pending = do let (dirToWatch, fileToWatch) = splitFileName pathToWatch@@ -55,24 +58,8 @@ "-i"++dirToWatch , pathToWatch ] ""- putStrLn c+ putStrLn "updated" return c-{-- color <- randomRIO (0::Float, 1)-- return $ unlines [- "precision mediump float;"- , "uniform float time;"- , "uniform vec3 mouse;"- , "const float PI = 3.141592653589793238462643383;"- , "varying vec3 uv;"- , ""- , "void main() {"- , " gl_FragColor = vec4("++show color++", 0.0, 0.0, 1.0);"- , "}"- ]--}- serveIndex :: IO () serveIndex = withSocketsDo $ do
app/index.html view
@@ -64,11 +64,13 @@ } a { text-decoration: inherit;+ color: white; } a:visited { color: inherit; }+ </style> </head> <body>@@ -85,20 +87,28 @@ <script> const vsSource = ` attribute vec3 aPosition;-varying vec3 uv;+varying vec2 uvN; void main() { gl_Position = vec4(aPosition, 1.0);- uv = aPosition;+ uvN = aPosition.xy; } `;-- const initialFsSource = `+ const fsHeader=` precision mediump float;+const float pi = 3.141592653589793238462643383; uniform float time;-uniform vec3 mouse;-const float PI = 3.141592653589793238462643383;-varying vec3 uv;+uniform vec2 mouse;+uniform vec4 audio;+uniform sampler2D backBuffer;+varying vec2 uvN; +vec2 uv() {+ return 0.5 * uvN + 0.5;+}++`++ const initialFsSource = ` void main() { gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); }@@ -121,6 +131,7 @@ let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS); if (!success) {+ console.log(source); throw "could not compile shader:" + gl.getShaderInfoLog(shader); } @@ -152,15 +163,45 @@ gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -1,1,0, 1,1,0, -1,-1,0, 1,-1,0 ]), gl.STATIC_DRAW); + // Assign attribute aPosition to each of the square's vertices. gl.aPosition = gl.getAttribLocation(program, "aPosition"); gl.enableVertexAttribArray(gl.aPosition); gl.vertexAttribPointer(gl.aPosition, 3, gl.FLOAT, false, 0, 0); + // backBuffer stuff+ function createTarget() {+ let target = {+ texture: gl.createTexture(),+ framebuffer: gl.createFramebuffer()+ };+ // set up framebuffer+ gl.bindTexture( gl.TEXTURE_2D, target.texture);+ gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, WIDTH, HEIGHT, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);++ gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);+ gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);++ gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);+ gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);++ gl.bindFramebuffer( gl.FRAMEBUFFER, target.framebuffer);+ gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, target.texture, 0);++ // clean up+ gl.bindTexture( gl.TEXTURE_2D, null);+ gl.bindFramebuffer( gl.FRAMEBUFFER, null);++ return target;+ }+ state.fb[0] = createTarget();+ state.fb[1] = createTarget();+ // remember the address within the fragment shader of each of my uniforms variables gl.time = gl.getUniformLocation(program, "time"); gl.mouse = gl.getUniformLocation(program, "mouse"); gl.audio = gl.getUniformLocation(program, "audio");+ gl.backBuffer = gl.getUniformLocation(program, "backBuffer"); draw(gl, state); @@ -170,12 +211,26 @@ } function draw (gl, state) {- gl.uniform1f(gl.time, (new Date().getTime() / 1000 - state.time0));- gl.uniform3f(gl.mouse, state.mouse.x, state.mouse.y, state.mouse.z);+ gl.uniform2f(gl.mouse, state.mouse.x, state.mouse.y); gl.uniform4f(gl.audio, state.audio.low, state.audio.mid, state.audio.upper, state.audio.high); + gl.uniform1i(gl.backBuffer, 0); // Do I need to check for null?++ gl.activeTexture(gl.TEXTURE0);+ gl.bindTexture(gl.TEXTURE_2D, state.fb[state.bit].texture);+ state.bit = (state.bit + 1) % 2;+ gl.bindFramebuffer( gl.FRAMEBUFFER, state.fb[state.bit].framebuffer);+ gl.clear(gl.COLOR_BUFFER_BIT);+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);++ gl.activeTexture(gl.TEXTURE0);+ gl.bindTexture(gl.TEXTURE_2D, state.fb[state.bit].texture);+ gl.bindFramebuffer( gl.FRAMEBUFFER, null);+ gl.clear(gl.COLOR_BUFFER_BIT);++ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); }; function animate (gl, state) {@@ -188,22 +243,22 @@ function setupState (state, canvas){ state.animationFrameRequest = null; + state.bit = 0+ state.fb = [null, null];+ state.time0 = new Date() / 1000; - function setMouse (event, z) {+ function setMouse (event) { let r = event.target.getBoundingClientRect(); state.mouse.x = (event.clientX - r.left) / (r.right - r.left) * 2 -1; state.mouse.y = (event.clientY - r.bottom) / (r.top - r.bottom) * 2 - 1;-- if (z !== undefined) {- state.mouse.z = z;- } };- canvas.onmousedown = (event) => setMouse(event, 1);+ /* canvas.onmousedown = (event) => setMouse(event, 1); */+ /* canvas.onmouseup = (event) => setMouse(event, 0); */+ canvas.onmousemove = (event) => setMouse(event);- canvas.onmouseup = (event) => setMouse(event, 0);- state.mouse = {x: 0, y: 0, z: 0};+ state.mouse = {x: 0, y: 0}; state.audio = {low: 0.0, mid: 0.0, upper: 0.0, high: 0.0};@@ -268,7 +323,7 @@ function onFail(e) { console.error(e); }- navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;+ navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; navigator.getUserMedia({audio: true}, onAccept, onFail); } @@ -278,8 +333,10 @@ // stateful variables const canvas = document.getElementById("canvas");- canvas.width = Math.max(window.innerHeight, window.innerWidth);- canvas.height = Math.max(window.innerHeight, window.innerWidth);+ let WIDTH = Math.max(window.innerHeight, window.innerWidth);+ let HEIGHT = Math.max(window.innerHeight, window.innerWidth);+ canvas.width = WIDTH;+ canvas.height = HEIGHT; const gl = canvas.getContext("webgl"); @@ -288,7 +345,7 @@ setupState(state, canvas); - loadProgram (gl, state, vsSource, initialFsSource);+ loadProgram (gl, state, vsSource, fsHeader + initialFsSource); function fadeOut(elem) {@@ -318,7 +375,7 @@ wsConn.onmessage = function (m) { console.log(m.data);- loadProgram(gl, state, vsSource, m.data);+ loadProgram(gl, state, vsSource, fsHeader + m.data); }; }
hylogen.cabal view
@@ -1,7 +1,7 @@ name: hylogen-version: 0.1.0.5-synopsis: a tiny EDSL for live-coding fragment shaders-description: a tiny EDSL for live-coding fragment shaders+version: 0.1.0.6+synopsis: an EDSL for live-coding fragment shaders+description: an EDSL for live-coding fragment shaders homepage: https://github.com/sleexyz/hylogen author: Sean Lee license: MIT@@ -19,6 +19,7 @@ , Hylogen.Types , Hylogen.Globals build-depends: base >=4.8 && <4.9+ , vector-space hs-source-dirs: src default-language: Haskell2010
src/Hylogen.hs view
@@ -24,16 +24,7 @@ import Hylogen.Globals toGLSL :: Vec4 -> String-toGLSL x = unlines $ [ boiler- , "void main() {"+toGLSL x = unlines $ [ "void main() {" , " gl_FragColor = " <> show x <> ";" , "}" ]- where- boiler = unlines $ [ "precision mediump float;"- , "uniform float time;"- , "uniform vec3 mouse;"- , "uniform vec4 audio;"- , "const float PI = 3.141592653589793238462643383; "- , "varying vec3 uv;"- ]
src/Hylogen/Globals.hs view
@@ -5,25 +5,76 @@ import Hylogen.Types --- | Vec1:+inverseSqrt :: (HyloPrim a) => a -> a+inverseSqrt = vuop "inversesqrt" -time :: Vec1-time = V1u "time"--- rand_ = V1uop "rand"+fract :: (HyloPrim a) => a -> a+fract = vuop "fract" +floor_ :: (HyloPrim a) => a -> a+floor_ = vuop "floor" -fract :: Vec1 -> Vec1-fract = V1uop "fract"+ceil_ :: (HyloPrim a) => a -> a+ceil_ = vuop "ceil" +min_ :: (HyloPrim a) => a -> a -> a+min_ = vboppre "min" +max_:: (HyloPrim a) => a -> a -> a+max_ = vboppre "max" +clamp :: (HyloPrim a) => a -> a -> a -> a+clamp x y z = (z `min_` y) `max_` x --- | Vec2: -uv, mouse :: Vec2-uv = V2u "uv"+linexp :: (Floating a) => (a, a, a, a) -> a -> a+linexp (a, b, c, d) x = c * ((d / c) ** ((x - a) / (b - a)))++linlin :: (Floating a) => (a, a, a, a) -> a -> a+linlin (a, b, c, d) x = c + (d - c) * ((x - a) / (b - a))+++time :: Vec1+time = V1u "time"++uv :: Vec2+uv = V2u "uv()"++uvN :: Vec2+uvN = V2u "uvN"++mouse :: Vec2 mouse = V2u "mouse" --- coord_ = V4u "gl_FragCoord"+audio :: Vec4 audio = V4u "audio"++backBuffer :: Texture+backBuffer = Tu "backBuffer"++-- | Booly's++true :: Booly+true = Bu "true"++false :: Booly+false = Bu "false"++eq :: (HyloPrim v) => v -> v -> Booly+eq = Bcomp "=="++neq :: (HyloPrim v) => v -> v -> Booly+neq = Bcomp "!="++lt :: (HyloPrim v) => v -> v -> Booly+lt = Bcomp "<"++gt :: (HyloPrim v) => v -> v -> Booly+gt = Bcomp ">"++leq :: (HyloPrim v) => v -> v -> Booly+leq = Bcomp "<="++geq :: (HyloPrim v) => v -> v -> Booly+geq = Bcomp ">="
src/Hylogen/Types.hs view
@@ -1,30 +1,41 @@-{-# LANGUAGE DeriveFunctor#-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE ExplicitForAll #-}-{-# LANGUAGE PolyKinds #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE NoMonoLocalBinds #-} {-# LANGUAGE ExtendedDefaultRules #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE InstanceSigs #-}-{-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-} module Hylogen.Types where import Data.Monoid+import Data.VectorSpace +-- | Darn I need injective type families.. waiting for GHC8+type family HyloConstructor v where+ HyloConstructor Vec1 = Float+ HyloConstructor Vec2 = (Vec1, Vec1)+ HyloConstructor Vec3 = (Vec1, Vec1, Vec1)+ HyloConstructor Vec4 = (Vec1, Vec1, Vec1, Vec1) +class (Show v) => HyloPrim v where+ vec :: HyloConstructor v -> v+ vu :: String -> v+ vuop :: String -> v -> v+ vuoppre :: String -> v -> v+ vbop :: String -> v -> v -> v+ vboppre :: String -> v -> v -> v+ select :: Booly -> v -> v -> v+ fromVec1 :: Vec1 -> v++ class Show a => HasX a class HasX a => HasY a class HasY a => HasZ a class HasZ a => HasW a + data Vec1 where Vec1 :: Float -> Vec1 V1u :: String -> Vec1@@ -32,11 +43,14 @@ V1uoppre :: String -> Vec1 -> Vec1 V1bop :: String -> Vec1 -> Vec1 -> Vec1 V1boppre :: String -> Vec1 -> Vec1 -> Vec1+ V1select :: Booly -> Vec1 -> Vec1 -> Vec1 X :: (HasX a) => a -> Vec1 Y :: (HasY a) => a -> Vec1 Z :: (HasZ a) => a -> Vec1 W :: (HasW a) => a -> Vec1 ++ instance Show Vec1 where show expr = case expr of Vec1 x -> show x@@ -45,38 +59,49 @@ V1uoppre u x -> "(" <> u <> show x <> ")" V1bop b x y -> "(" <> show x <> " " <> b <> " " <> show y <> ")" V1boppre b x y -> b <> "(" <> show x <> ", " <> show y <> ")"+ V1select b x y -> "( " <> show b <> " ? " <> show x <> " : " <> show y <> ")" X x -> show x <> ".x" Y x -> show x <> ".y" Z x -> show x <> ".z" W x -> show x <> ".w" -instance Num Vec1 where- (+) = V1bop "+"- (*) = V1bop "*"- negate = V1uoppre "-"- abs = V1uop "abs"- signum = V1uop "sign"- fromInteger = Vec1 . fromInteger+instance HyloPrim Vec1 where+ vec = Vec1+ vu = V1u+ vuop = V1uop+ vuoppre = V1uoppre+ vbop = V1bop+ vboppre = V1boppre+ select = V1select+ fromVec1 = id +instance Num Vec1 where+ (+) = vbop "+"+ (*) = vbop "*"+ negate = vuoppre "-"+ abs = vuop "abs"+ signum = vuop "sign"+ fromInteger = Vec1 . fromInteger instance Fractional Vec1 where- (/) = V1bop "/"- recip = V1bop "/" 1+ (/) = vbop "/"+ recip = vbop "/" 1 fromRational = Vec1 . fromRational + instance Floating Vec1 where- pi = V1u "pi"- exp = V1uop "exp"- log = V1uop "log"- sqrt = V1uop "sqrt"- (**) = V1boppre "pow"- sin = V1uop "sin"- cos = V1uop "cos"- tan = V1uop "tan"- asin = V1uop "asin"- acos = V1uop "acos"- atan = V1uop "atan"+ pi = vu "pi"+ exp = vuop "exp"+ log = vuop "log"+ sqrt = vuop "sqrt"+ (**) = vboppre "pow"+ sin = vuop "sin"+ cos = vuop "cos"+ tan = vuop "tan"+ asin = vuop "asin"+ acos = vuop "acos"+ atan = vuop "atan" sinh x = (exp x - exp (negate x))/2 cosh x = (exp x + exp (negate x))/2 tanh x = sinh x / cosh x@@ -84,18 +109,93 @@ acosh x = log $ x + sqrt(x**2 - 1) atanh x = 0.5 * log ((1 + x)/(1 - x)) +instance AdditiveGroup Vec1 where+ zeroV = 0+ (^+^) = (+)+ negateV = negate+ (^-^) = (-) +instance VectorSpace Vec1 where+ type Scalar Vec1 = Vec1+ a *^ b = a * b+ -- | Vec2: data Vec2 where Vec2 :: (Vec1, Vec1) -> Vec2 V2u :: String -> Vec2+ V2uop :: String -> Vec2 -> Vec2+ V2uoppre :: String -> Vec2 -> Vec2+ V2bop :: String -> Vec2 -> Vec2 -> Vec2+ V2boppre :: String -> Vec2 -> Vec2 -> Vec2+ V2bops :: String -> Vec1 -> Vec2 -> Vec2+ V2select :: Booly -> Vec2 -> Vec2 -> Vec2 +instance HyloPrim Vec2 where+ vec = Vec2+ vu = V2u+ vuop = V2uop+ vuoppre = V2uoppre+ vbop = V2bop+ vboppre = V2boppre+ select = V2select+ fromVec1 x = Vec2 (x, x)++ instance Show Vec2 where show expr = case expr of Vec2 (x, y) -> "vec2(" <> show x <> ", " <> show y <> ")" V2u x -> x+ V2uop u x -> u <> "(" <> show x <> ")"+ V2uoppre u x -> "(" <> u <> show x <> ")"+ V2bop b x y -> "(" <> show x <> " " <> b <> " " <> show y <> ")"+ V2boppre b x y -> b <> "(" <> show x <> ", " <> show y <> ")"+ V2bops b x y -> "(" <> show x <> " " <> b <> " " <> show y <> ")"+ V2select b x y -> "( " <> show b <> " ? " <> show x <> " : " <> show y <> ")" +instance Num Vec2 where+ (+) = vbop "+"+ (*) = vbop "*"+ negate = vuoppre "-"+ abs = vuop "abs"+ signum = vuop "sign"+ fromInteger = fromVec1 . fromInteger++instance Fractional Vec2 where+ (/) = vbop "/"+ recip = vbop "/" 1+ fromRational = fromVec1 . fromRational+++instance Floating Vec2 where+ pi = vu "pi"+ exp = vuop "exp"+ log = vuop "log"+ sqrt = vuop "sqrt"+ (**) = vboppre "pow"+ sin = vuop "sin"+ cos = vuop "cos"+ tan = vuop "tan"+ asin = vuop "asin"+ acos = vuop "acos"+ atan = vuop "atan"+ sinh x = (exp x - exp (negate x))/2+ cosh x = (exp x + exp (negate x))/2+ tanh x = sinh x / cosh x+ asinh x = log $ x + sqrt(x**2 + 1)+ acosh x = log $ x + sqrt(x**2 - 1)+ atanh x = 0.5 * log ((1 + x)/(1 - x))++instance AdditiveGroup Vec2 where+ zeroV = 0+ (^+^) = (+)+ negateV = negate+ (^-^) = (-)++instance VectorSpace Vec2 where+ type Scalar Vec2 = Vec1+ a *^ b = V2bops "*" a b+ instance HasX Vec2 instance HasY Vec2 @@ -105,29 +205,201 @@ data Vec3 where Vec3 :: (Vec1, Vec1, Vec1) -> Vec3 V3u :: String -> Vec3+ V3uop :: String -> Vec3 -> Vec3+ V3uoppre :: String -> Vec3 -> Vec3+ V3bop :: String -> Vec3 -> Vec3 -> Vec3+ V3boppre :: String -> Vec3 -> Vec3 -> Vec3+ V3bops :: String -> Vec1 -> Vec3 -> Vec3+ V3select :: Booly -> Vec3 -> Vec3 -> Vec3 +instance HyloPrim Vec3 where+ vec = Vec3+ vu = V3u+ vuop = V3uop+ vuoppre = V3uoppre+ vbop = V3bop+ vboppre = V3boppre+ select = V3select+ fromVec1 x = Vec3 (x, x, x)+ instance Show Vec3 where show expr = case expr of Vec3 (x, y, z) -> "vec3(" <> show x <> ", " <> show y <> ", " <> show z <> ")" V3u x -> x+ V3uop u x -> u <> "(" <> show x <> ")"+ V3uoppre u x -> "(" <> u <> show x <> ")"+ V3bop b x y -> "(" <> show x <> " " <> b <> " " <> show y <> ")"+ V3boppre b x y -> b <> "(" <> show x <> ", " <> show y <> ")"+ V3bops b x y -> "(" <> show x <> " " <> b <> " " <> show y <> ")"+ V3select b x y -> "( " <> show b <> " ? " <> show x <> " : " <> show y <> ")" +instance Num Vec3 where+ (+) = vbop "+"+ (*) = vbop "*"+ negate = vuoppre "-"+ abs = vuop "abs"+ signum = vuop "sign"+ fromInteger = fromVec1 . fromInteger++instance Fractional Vec3 where+ (/) = vbop "/"+ recip = vbop "/" 1+ fromRational = fromVec1 . fromRational+++instance Floating Vec3 where+ pi = vu "pi"+ exp = vuop "exp"+ log = vuop "log"+ sqrt = vuop "sqrt"+ (**) = vboppre "pow"+ sin = vuop "sin"+ cos = vuop "cos"+ tan = vuop "tan"+ asin = vuop "asin"+ acos = vuop "acos"+ atan = vuop "atan"+ sinh x = (exp x - exp (negate x))/2+ cosh x = (exp x + exp (negate x))/2+ tanh x = sinh x / cosh x+ asinh x = log $ x + sqrt(x**2 + 1)+ acosh x = log $ x + sqrt(x**2 - 1)+ atanh x = 0.5 * log ((1 + x)/(1 - x))++instance AdditiveGroup Vec3 where+ zeroV = 0+ (^+^) = (+)+ negateV = negate+ (^-^) = (-)++instance VectorSpace Vec3 where+ type Scalar Vec3 = Vec1+ a *^ b = V3bops "*" a b+ instance HasX Vec3 instance HasY Vec3 instance HasZ Vec3 + -- | Vec4: data Vec4 where Vec4 :: (Vec1, Vec1, Vec1, Vec1) -> Vec4 V4u :: String -> Vec4+ V4uop :: String -> Vec4 -> Vec4+ V4uoppre :: String -> Vec4 -> Vec4+ V4bop :: String -> Vec4 -> Vec4 -> Vec4+ V4boppre :: String -> Vec4 -> Vec4 -> Vec4+ V4bops :: String -> Vec1 -> Vec4 -> Vec4+ V4select :: Booly -> Vec4 -> Vec4 -> Vec4+ Texture2D :: Texture -> Vec2 -> Vec4 ++instance HyloPrim Vec4 where+ vec = Vec4+ vu = V4u+ vuop = V4uop+ vuoppre = V4uoppre+ vbop = V4bop+ vboppre = V4boppre+ select = V4select+ fromVec1 x = Vec4 (x, x, x, x)+ instance Show Vec4 where show expr = case expr of Vec4 (x, y, z, w) -> "vec4(" <> show x <> ", " <> show y <> ", " <> show z <> ", " <> show w <> ")" V4u x -> x+ V4uop u x -> u <> "(" <> show x <> ")"+ V4uoppre u x -> "(" <> u <> show x <> ")"+ V4bop b x y -> "(" <> show x <> " " <> b <> " " <> show y <> ")"+ V4boppre b x y -> b <> "(" <> show x <> ", " <> show y <> ")"+ V4bops b x y -> "(" <> show x <> " " <> b <> " " <> show y <> ")"+ V4select b x y -> "( " <> show b <> " ? " <> show x <> " : " <> show y <> ")"+ Texture2D t v -> "texture2D(" <> show t <> ", " <> show v <> ")" +instance Num Vec4 where+ (+) = vbop "+"+ (*) = vbop "*"+ negate = vuoppre "-"+ abs = vuop "abs"+ signum = vuop "sign"+ fromInteger = fromVec1 . fromInteger++instance Fractional Vec4 where+ (/) = vbop "/"+ recip = vbop "/" 1+ fromRational = fromVec1 . fromRational+++instance Floating Vec4 where+ pi = vu "pi"+ exp = vuop "exp"+ log = vuop "log"+ sqrt = vuop "sqrt"+ (**) = vboppre "pow"+ sin = vuop "sin"+ cos = vuop "cos"+ tan = vuop "tan"+ asin = vuop "asin"+ acos = vuop "acos"+ atan = vuop "atan"+ sinh x = (exp x - exp (negate x))/2+ cosh x = (exp x + exp (negate x))/2+ tanh x = sinh x / cosh x+ asinh x = log $ x + sqrt(x**2 + 1)+ acosh x = log $ x + sqrt(x**2 - 1)+ atanh x = 0.5 * log ((1 + x)/(1 - x))++instance AdditiveGroup Vec4 where+ zeroV = 0+ (^+^) = (+)+ negateV = negate+ (^-^) = (-)++instance VectorSpace Vec4 where+ type Scalar Vec4 = Vec1+ a *^ b = V4bops "*" a b+ instance HasX Vec4 instance HasY Vec4 instance HasZ Vec4 instance HasW Vec4+++data Texture where+ Tu :: String -> Texture++instance Show Texture where+ show (Tu xs) = xs++-- | We implement Bool as a Num++data Booly where+ Bu:: String -> Booly+ Buop :: String -> Booly -> Booly+ Buoppre :: String -> Booly -> Booly+ Bbop :: String -> Booly -> Booly -> Booly+ Bcomp :: (HyloPrim a) => String -> a -> a -> Booly++instance Show Booly where+ show expr = case expr of+ Bu x -> x+ Buop u x -> u <> "(" <> show x <> ")"+ Buoppre u x -> "(" <> u <> show x <> ")"+ Bbop u x y -> "(" <> show x <> " " <> u <> " " <> show y <> ")"+ Bcomp u x y -> "(" <> show x <> " " <> u <> " " <> show y <> ")"++instance Num Booly where+ (+) = Bbop "||"+ (*) = Bbop "&&"+ negate = Buoppre "!"+ abs = id+ signum = id+ fromInteger x+ | x > 0 = Bu "true"+ | otherwise = Bu "false"+++-- data Expr a where+-- Node a :: ID -> a