packages feed

glsl-0.0.1.0: src/Language/GLSL/Runtime/PrimFuns.hs

module Language.GLSL.Runtime.PrimFuns where

import           Control.Monad               ((>=>))
import           Language.GLSL.AST           (FunName (..), Type (..))
import           Language.GLSL.PrettyPrint   (pp, ppFunName)
import           Language.GLSL.Runtime.Math  (floor, fract, mod, smoothstep,
                                              step)
import           Language.GLSL.Runtime.Value (Eval, Value (..), evalCoerce)
import           Linear
import           Prelude                     hiding (floor, mod)

flt :: Value -> Eval Float
flt = evalCoerce TyFloat >=> convert
  where
    convert (FloatValue v) = pure v
    convert v              = fail $ "not a Float value: " <> show v

v4 :: Value -> Eval (V4 Float)
v4 = evalCoerce (TyVec 4) >=> convert
  where
    convert (Vec4Value v) = pure v
    convert v             = fail $ "not a V4 value: " <> show v


eval :: FunName -> [Value] -> Eval Value
eval PrimVec2 [x, y] =
  fmap Vec2Value $ V2
    <$> flt x
    <*> flt y
eval PrimVec3 [x, y, z] =
  fmap Vec3Value $ V3
    <$> flt x
    <*> flt y
    <*> flt z
eval PrimVec4 [x, y, z, w] =
  fmap Vec4Value $ V4
    <$> flt x
    <*> flt y
    <*> flt z
    <*> flt w

eval PrimMat4x4 [x, y, z, w] =
  fmap Mat4x4Value $ V4
    <$> v4 x
    <*> v4 y
    <*> v4 z
    <*> v4 w

eval PrimLength [Vec2Value a] = pure $ FloatValue $ norm a
eval PrimLength [Vec3Value a] = pure $ FloatValue $ norm a
eval PrimLength [Vec4Value a] = pure $ FloatValue $ norm a

eval PrimNormalize [Vec2Value a] = pure $ Vec2Value $ signorm a
eval PrimNormalize [Vec3Value a] = pure $ Vec3Value $ signorm a
eval PrimNormalize [Vec4Value a] = pure $ Vec4Value $ signorm a

eval PrimSqrt   [a] = FloatValue      . sqrt   <$> flt a
eval PrimSin    [a] = FloatValue      . sin    <$> flt a
eval PrimAsin   [a] = FloatValue      . asin   <$> flt a
eval PrimCos    [a] = FloatValue      . cos    <$> flt a
eval PrimAbs    [a] = FloatValue      . abs    <$> flt a
eval PrimFloor  [a] = FloatValue      . floor  <$> flt a
eval PrimFract  [a] = FloatValue      . fract  <$> flt a
eval PrimMod  [a,b] = fmap FloatValue $ mod    <$> flt a <*> flt b
eval PrimAtan [a,b] = fmap FloatValue $ atan2  <$> flt a <*> flt b

eval PrimSmoothstep [a,b,c] = fmap FloatValue $ smoothstep <$> flt a <*> flt b <*> flt c
eval PrimStep         [a,b] = fmap FloatValue $ step <$> flt a <*> flt b

-- eval _ (a:_) = pure a
eval fun _ = fail $ "primfun not implemented: " <> pp ppFunName fun