{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
-- | Module to describe bi-sampleable types

module Graphics.Rasterific.BiSampleable
    ( BiSampleable( .. )
    , bilinearInterpolation
    , sampledImageShader
    ) where

import Data.Fixed( mod' )
import Codec.Picture
    ( Image( .. )
    , Pixel8
    , Pixel( .. )
    , PixelRGBA8( .. ) )

import Graphics.Rasterific.Linear
import Graphics.Rasterific.Types
import Graphics.Rasterific.Compositor
import Graphics.Rasterific.Command
import Graphics.Rasterific.PatchTypes
import Graphics.Rasterific.Transformations

-- | Interpolate a 2D point in a given type

class BiSampleable sampled px | sampled -> px where
  -- | The interpolation function

  interpolate :: sampled -> Float -> Float -> px

-- | Basic bilinear interpolator

instance  (Pixel px, Modulable (PixelBaseComponent px))
    => BiSampleable (ParametricValues px) px where
  {-# INLINE interpolate #-}
  interpolate :: ParametricValues px -> Float -> Float -> px
interpolate = ParametricValues px -> Float -> Float -> px
forall px.
(Pixel px, Modulable (PixelBaseComponent px)) =>
ParametricValues px -> Float -> Float -> px
bilinearPixelInterpolation

-- | Bicubic interpolator

instance ( InterpolablePixel px
         , Num (Holder px Float)
         ) => BiSampleable (CubicCoefficient px) px where
  {-# INLINE interpolate #-}
  interpolate :: CubicCoefficient px -> Float -> Float -> px
interpolate = CubicCoefficient px -> Float -> Float -> px
forall px.
(InterpolablePixel px, Num (Holder px Float)) =>
CubicCoefficient px -> Float -> Float -> px
bicubicInterpolation

-- | Bilinear interpolation of an image

instance BiSampleable (ImageMesh PixelRGBA8) PixelRGBA8 where
  {-# INLINE interpolate #-}
  interpolate :: ImageMesh PixelRGBA8 -> Float -> Float -> PixelRGBA8
interpolate ImageMesh PixelRGBA8
imesh Float
xb Float
yb = Image PixelRGBA8 -> SamplerRepeat -> Float -> Float -> PixelRGBA8
forall px.
RenderablePixel px =>
Image px -> SamplerRepeat -> ShaderFunction px
sampledImageShader (ImageMesh PixelRGBA8 -> Image PixelRGBA8
forall px. ImageMesh px -> Image px
_meshImage ImageMesh PixelRGBA8
imesh) SamplerRepeat
SamplerPad Float
x Float
y
    where (V2 Float
x Float
y) = Transformation -> V2 Float -> V2 Float
applyTransformation (ImageMesh PixelRGBA8 -> Transformation
forall px. ImageMesh px -> Transformation
_meshTransform ImageMesh PixelRGBA8
imesh) (Float -> Float -> V2 Float
forall a. a -> a -> V2 a
V2 Float
xb Float
yb)

-- | Use another image as a texture for the filling.

-- Contrary to `imageTexture`, this function perform a bilinear

-- filtering on the texture.

--

sampledImageShader :: forall px. RenderablePixel px
                   => Image px -> SamplerRepeat -> ShaderFunction px
{-# SPECIALIZE
     sampledImageShader :: Image Pixel8 -> SamplerRepeat
                        -> ShaderFunction Pixel8 #-}
{-# SPECIALIZE
     sampledImageShader :: Image PixelRGBA8 -> SamplerRepeat
                        -> ShaderFunction PixelRGBA8 #-}
sampledImageShader :: Image px -> SamplerRepeat -> ShaderFunction px
sampledImageShader Image px
img SamplerRepeat
_ Float
_ Float
_
  | Image px -> Int
forall a. Image a -> Int
imageWidth Image px
img Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
|| Image px -> Int
forall a. Image a -> Int
imageHeight Image px
img Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = px
forall px. RenderablePixel px => px
emptyPx
sampledImageShader Image px
img SamplerRepeat
sampling Float
x Float
y =
  (Int -> Int -> px
at Int
px  Int
py px -> px -> px
`interpX` Int -> Int -> px
at Int
pxn Int
py)
             px -> px -> px
`interpY`
  (Int -> Int -> px
at Int
px Int
pyn px -> px -> px
`interpX` Int -> Int -> px
at Int
pxn Int
pyn)
  where
   coordSampler :: SamplerRepeat -> a -> a -> a
coordSampler SamplerRepeat
SamplerPad a
maxi a
v = a -> a -> a
forall a. Ord a => a -> a -> a
min (a
maxi a -> a -> a
forall a. Num a => a -> a -> a
- a
1) (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a -> a
forall a. Ord a => a -> a -> a
max a
0 (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ a -> a
forall a b. (RealFrac a, Integral b) => a -> b
floor a
v
   coordSampler SamplerRepeat
SamplerReflect a
maxi a
v =
      a -> a
forall a b. (RealFrac a, Integral b) => a -> b
floor (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ a -> a
forall a. Num a => a -> a
abs (a -> a
forall a. Num a => a -> a
abs (a
v a -> a -> a
forall a. Num a => a -> a -> a
- a
maxif a -> a -> a
forall a. Num a => a -> a -> a
- a
1) a -> a -> a
forall a. Real a => a -> a -> a
`mod'` (a
2 a -> a -> a
forall a. Num a => a -> a -> a
* a
maxif) a -> a -> a
forall a. Num a => a -> a -> a
- a
maxif a -> a -> a
forall a. Num a => a -> a -> a
- a
1)
        where maxif :: a
maxif = a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
maxi
   coordSampler SamplerRepeat
SamplerRepeat a
maxi a
v = a -> a
forall a b. (RealFrac a, Integral b) => a -> b
floor a
v a -> a -> a
forall a. Integral a => a -> a -> a
`mod` a
maxi

   w :: Int
w = Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Image px -> Int
forall a. Image a -> Int
imageWidth Image px
img
   h :: Int
h = Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Image px -> Int
forall a. Image a -> Int
imageHeight Image px
img

   clampedX :: Float -> Int
clampedX = SamplerRepeat -> Int -> Float -> Int
forall a a.
(RealFrac a, Integral a) =>
SamplerRepeat -> a -> a -> a
coordSampler SamplerRepeat
sampling Int
w
   clampedY :: Float -> Int
clampedY = SamplerRepeat -> Int -> Float -> Int
forall a a.
(RealFrac a, Integral a) =>
SamplerRepeat -> a -> a -> a
coordSampler SamplerRepeat
sampling Int
h

   px :: Int
px = Float -> Int
clampedX Float
x
   pxn :: Int
pxn = Float -> Int
clampedX (Float -> Int) -> Float -> Int
forall a b. (a -> b) -> a -> b
$ Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
1
   py :: Int
py = Float -> Int
clampedY Float
y
   pyn :: Int
pyn = Float -> Int
clampedY (Float -> Int) -> Float -> Int
forall a b. (a -> b) -> a -> b
$ Float
y Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
1

   dx, dy :: Float
   !dx :: Float
dx = Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
- Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Float -> Int
forall a b. (RealFrac a, Integral b) => a -> b
floor Float
x :: Int)
   !dy :: Float
dy = Float
y Float -> Float -> Float
forall a. Num a => a -> a -> a
- Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Float -> Int
forall a b. (RealFrac a, Integral b) => a -> b
floor Float
y :: Int)

   at :: Int -> Int -> px
   at :: Int -> Int -> px
at !Int
xx !Int
yy =
        Vector (PixelBaseComponent px) -> Int -> px
forall a. Pixel a => Vector (PixelBaseComponent a) -> Int -> a
unsafePixelAt Vector (PixelBaseComponent px)
rawData (Int -> px) -> Int -> px
forall a b. (a -> b) -> a -> b
$ (Int
yy Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
w Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
xx) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
compCount

   (PixelBaseComponent px
covX, PixelBaseComponent px
icovX) = Float -> (PixelBaseComponent px, PixelBaseComponent px)
forall a. Modulable a => Float -> (a, a)
clampCoverage Float
dx
   (PixelBaseComponent px
covY, PixelBaseComponent px
icovY) = Float -> (PixelBaseComponent px, PixelBaseComponent px)
forall a. Modulable a => Float -> (a, a)
clampCoverage Float
dy

   interpX :: px -> px -> px
interpX = (Int
 -> PixelBaseComponent px
 -> PixelBaseComponent px
 -> PixelBaseComponent px)
-> px -> px -> px
forall a.
Pixel a =>
(Int
 -> PixelBaseComponent a
 -> PixelBaseComponent a
 -> PixelBaseComponent a)
-> a -> a -> a
mixWith ((PixelBaseComponent px
 -> PixelBaseComponent px -> PixelBaseComponent px)
-> Int
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a b. a -> b -> a
const ((PixelBaseComponent px
  -> PixelBaseComponent px -> PixelBaseComponent px)
 -> Int
 -> PixelBaseComponent px
 -> PixelBaseComponent px
 -> PixelBaseComponent px)
-> (PixelBaseComponent px
    -> PixelBaseComponent px -> PixelBaseComponent px)
-> Int
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a b. (a -> b) -> a -> b
$ PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a. Modulable a => a -> a -> a -> a -> a
alphaOver PixelBaseComponent px
covX PixelBaseComponent px
icovX)
   interpY :: px -> px -> px
interpY = (Int
 -> PixelBaseComponent px
 -> PixelBaseComponent px
 -> PixelBaseComponent px)
-> px -> px -> px
forall a.
Pixel a =>
(Int
 -> PixelBaseComponent a
 -> PixelBaseComponent a
 -> PixelBaseComponent a)
-> a -> a -> a
mixWith ((PixelBaseComponent px
 -> PixelBaseComponent px -> PixelBaseComponent px)
-> Int
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a b. a -> b -> a
const ((PixelBaseComponent px
  -> PixelBaseComponent px -> PixelBaseComponent px)
 -> Int
 -> PixelBaseComponent px
 -> PixelBaseComponent px
 -> PixelBaseComponent px)
-> (PixelBaseComponent px
    -> PixelBaseComponent px -> PixelBaseComponent px)
-> Int
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a b. (a -> b) -> a -> b
$ PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a. Modulable a => a -> a -> a -> a -> a
alphaOver PixelBaseComponent px
covY PixelBaseComponent px
icovY)

   compCount :: Int
compCount = px -> Int
forall a. Pixel a => a -> Int
componentCount (px
forall a. HasCallStack => a
undefined :: px)
   rawData :: Vector (PixelBaseComponent px)
rawData = Image px -> Vector (PixelBaseComponent px)
forall a. Image a -> Vector (PixelBaseComponent a)
imageData Image px
img

bilinearPixelInterpolation :: (Pixel px, Modulable (PixelBaseComponent px))
                           => ParametricValues px -> Float -> Float -> px
{-# SPECIALIZE INLINE
    bilinearPixelInterpolation :: ParametricValues PixelRGBA8 -> Float -> Float -> PixelRGBA8
  #-}
bilinearPixelInterpolation :: ParametricValues px -> Float -> Float -> px
bilinearPixelInterpolation (ParametricValues { px
_westValue :: forall a. ParametricValues a -> a
_southValue :: forall a. ParametricValues a -> a
_eastValue :: forall a. ParametricValues a -> a
_northValue :: forall a. ParametricValues a -> a
_westValue :: px
_southValue :: px
_eastValue :: px
_northValue :: px
.. }) !Float
dx !Float
dy = 
  (Int
 -> PixelBaseComponent px
 -> PixelBaseComponent px
 -> PixelBaseComponent px)
-> px -> px -> px
forall a.
Pixel a =>
(Int
 -> PixelBaseComponent a
 -> PixelBaseComponent a
 -> PixelBaseComponent a)
-> a -> a -> a
mixWith ((PixelBaseComponent px
 -> PixelBaseComponent px -> PixelBaseComponent px)
-> Int
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a b. a -> b -> a
const ((PixelBaseComponent px
  -> PixelBaseComponent px -> PixelBaseComponent px)
 -> Int
 -> PixelBaseComponent px
 -> PixelBaseComponent px
 -> PixelBaseComponent px)
-> (PixelBaseComponent px
    -> PixelBaseComponent px -> PixelBaseComponent px)
-> Int
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a b. (a -> b) -> a -> b
$ PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a. Modulable a => a -> a -> a -> a -> a
alphaOver PixelBaseComponent px
covY PixelBaseComponent px
icovY)
        ((Int
 -> PixelBaseComponent px
 -> PixelBaseComponent px
 -> PixelBaseComponent px)
-> px -> px -> px
forall a.
Pixel a =>
(Int
 -> PixelBaseComponent a
 -> PixelBaseComponent a
 -> PixelBaseComponent a)
-> a -> a -> a
mixWith ((PixelBaseComponent px
 -> PixelBaseComponent px -> PixelBaseComponent px)
-> Int
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a b. a -> b -> a
const ((PixelBaseComponent px
  -> PixelBaseComponent px -> PixelBaseComponent px)
 -> Int
 -> PixelBaseComponent px
 -> PixelBaseComponent px
 -> PixelBaseComponent px)
-> (PixelBaseComponent px
    -> PixelBaseComponent px -> PixelBaseComponent px)
-> Int
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a b. (a -> b) -> a -> b
$ PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a. Modulable a => a -> a -> a -> a -> a
alphaOver PixelBaseComponent px
covX PixelBaseComponent px
icovX) px
_northValue px
_eastValue)
        ((Int
 -> PixelBaseComponent px
 -> PixelBaseComponent px
 -> PixelBaseComponent px)
-> px -> px -> px
forall a.
Pixel a =>
(Int
 -> PixelBaseComponent a
 -> PixelBaseComponent a
 -> PixelBaseComponent a)
-> a -> a -> a
mixWith ((PixelBaseComponent px
 -> PixelBaseComponent px -> PixelBaseComponent px)
-> Int
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a b. a -> b -> a
const ((PixelBaseComponent px
  -> PixelBaseComponent px -> PixelBaseComponent px)
 -> Int
 -> PixelBaseComponent px
 -> PixelBaseComponent px
 -> PixelBaseComponent px)
-> (PixelBaseComponent px
    -> PixelBaseComponent px -> PixelBaseComponent px)
-> Int
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a b. (a -> b) -> a -> b
$ PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
-> PixelBaseComponent px
forall a. Modulable a => a -> a -> a -> a -> a
alphaOver PixelBaseComponent px
covX PixelBaseComponent px
icovX) px
_westValue px
_southValue)
  where
   (!PixelBaseComponent px
covX, !PixelBaseComponent px
icovX) = Float -> (PixelBaseComponent px, PixelBaseComponent px)
forall a. Modulable a => Float -> (a, a)
clampCoverage Float
dx
   (!PixelBaseComponent px
covY, !PixelBaseComponent px
icovY) = Float -> (PixelBaseComponent px, PixelBaseComponent px)
forall a. Modulable a => Float -> (a, a)
clampCoverage Float
dy

bilinearInterpolation :: InterpolablePixel px
                      => ParametricValues px -> Float -> Float -> px
{-# INLINE bilinearInterpolation #-}
bilinearInterpolation :: ParametricValues px -> Float -> Float -> px
bilinearInterpolation ParametricValues { px
_westValue :: px
_southValue :: px
_eastValue :: px
_northValue :: px
_westValue :: forall a. ParametricValues a -> a
_southValue :: forall a. ParametricValues a -> a
_eastValue :: forall a. ParametricValues a -> a
_northValue :: forall a. ParametricValues a -> a
.. } Float
u Float
v = Holder px Float -> px
forall a. InterpolablePixel a => Holder a Float -> a
fromFloatPixel (Holder px Float -> px) -> Holder px Float -> px
forall a b. (a -> b) -> a -> b
$ Float -> Holder px Float -> Holder px Float -> Holder px Float
forall (f :: * -> *) a.
(Additive f, Num a) =>
a -> f a -> f a -> f a
lerp Float
v Holder px Float
uBottom Holder px Float
uTop where
  -- The arguments are flipped, because the lerp function from Linear is...

  -- inversed in u v

  !uTop :: Holder px Float
uTop = Float -> Holder px Float -> Holder px Float -> Holder px Float
forall (f :: * -> *) a.
(Additive f, Num a) =>
a -> f a -> f a -> f a
lerp Float
u (px -> Holder px Float
forall a. InterpolablePixel a => a -> Holder a Float
toFloatPixel px
_eastValue) (px -> Holder px Float
forall a. InterpolablePixel a => a -> Holder a Float
toFloatPixel px
_northValue)
  !uBottom :: Holder px Float
uBottom = Float -> Holder px Float -> Holder px Float -> Holder px Float
forall (f :: * -> *) a.
(Additive f, Num a) =>
a -> f a -> f a -> f a
lerp Float
u (px -> Holder px Float
forall a. InterpolablePixel a => a -> Holder a Float
toFloatPixel px
_southValue) (px -> Holder px Float
forall a. InterpolablePixel a => a -> Holder a Float
toFloatPixel px
_westValue)


bicubicInterpolation :: forall px . (InterpolablePixel px, Num (Holder px Float))
                     => CubicCoefficient px -> Float -> Float -> px
bicubicInterpolation :: CubicCoefficient px -> Float -> Float -> px
bicubicInterpolation CubicCoefficient px
params Float
x Float
y =
  Holder px Float -> px
forall a. InterpolablePixel a => Holder a Float -> a
fromFloatPixel (Holder px Float -> px)
-> (Holder px Float -> Holder px Float) -> Holder px Float -> px
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Float -> Float) -> Holder px Float -> Holder px Float
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Float -> Float
clamp (Holder px Float -> px) -> Holder px Float -> px
forall a b. (a -> b) -> a -> b
$ Holder px Float
af Holder px Float -> Holder px Float -> Holder px Float
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^+^ Holder px Float
bf Holder px Float -> Holder px Float -> Holder px Float
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^+^ Holder px Float
cf Holder px Float -> Holder px Float -> Holder px Float
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^+^ Holder px Float
df
  where
    ParametricValues V4 (Holder px Float)
a V4 (Holder px Float)
b V4 (Holder px Float)
c V4 (Holder px Float)
d = CubicCoefficient px -> ParametricValues (V4 (Holder px Float))
forall px.
CubicCoefficient px -> ParametricValues (V4 (Holder px Float))
getCubicCoefficients CubicCoefficient px
params
    maxi :: Float
maxi = Proxy px -> Float
forall a. InterpolablePixel a => Proxy a -> Float
maxRepresentable (Proxy px
forall p. Proxy p
Proxy :: Proxy px)
    clamp :: Float -> Float
clamp = Float -> Float -> Float
forall a. Ord a => a -> a -> a
max Float
0 (Float -> Float) -> (Float -> Float) -> Float -> Float
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Float -> Float -> Float
forall a. Ord a => a -> a -> a
min Float
maxi
    xv, vy, vyy, vyyy :: V4 Float
    xv :: V4 Float
xv = Float -> Float -> Float -> Float -> V4 Float
forall a. a -> a -> a -> a -> V4 a
V4 Float
1 Float
x (Float
xFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
x) (Float
xFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
xFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
x)
    vy :: V4 Float
vy = V4 Float
xv V4 Float -> Float -> V4 Float
forall (f :: * -> *) a. (Functor f, Num a) => f a -> a -> f a
^* Float
y
    vyy :: V4 Float
vyy = V4 Float
vy V4 Float -> Float -> V4 Float
forall (f :: * -> *) a. (Functor f, Num a) => f a -> a -> f a
^* Float
y
    vyyy :: V4 Float
vyyy = V4 Float
vyy V4 Float -> Float -> V4 Float
forall (f :: * -> *) a. (Functor f, Num a) => f a -> a -> f a
^* Float
y

    f (f a)
v1 ^^*^ :: f (f a) -> f a -> f (f a)
^^*^ f a
v2 = f a -> a -> f a
forall (f :: * -> *) a. (Functor f, Num a) => f a -> a -> f a
(^*) (f a -> a -> f a) -> f (f a) -> f (a -> f a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f (f a)
v1 f (a -> f a) -> f a -> f (f a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> f a
v2

    V4 Holder px Float
af Holder px Float
bf Holder px Float
cf Holder px Float
df = (V4 (Holder px Float)
a V4 (Holder px Float) -> V4 Float -> V4 (Holder px Float)
forall (f :: * -> *) (f :: * -> *) a.
(Applicative f, Functor f, Num a) =>
f (f a) -> f a -> f (f a)
^^*^ V4 Float
xv) V4 (Holder px Float)
-> V4 (Holder px Float) -> V4 (Holder px Float)
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^+^ (V4 (Holder px Float)
b V4 (Holder px Float) -> V4 Float -> V4 (Holder px Float)
forall (f :: * -> *) (f :: * -> *) a.
(Applicative f, Functor f, Num a) =>
f (f a) -> f a -> f (f a)
^^*^ V4 Float
vy) V4 (Holder px Float)
-> V4 (Holder px Float) -> V4 (Holder px Float)
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^+^ (V4 (Holder px Float)
c V4 (Holder px Float) -> V4 Float -> V4 (Holder px Float)
forall (f :: * -> *) (f :: * -> *) a.
(Applicative f, Functor f, Num a) =>
f (f a) -> f a -> f (f a)
^^*^ V4 Float
vyy) V4 (Holder px Float)
-> V4 (Holder px Float) -> V4 (Holder px Float)
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^+^ (V4 (Holder px Float)
d V4 (Holder px Float) -> V4 Float -> V4 (Holder px Float)
forall (f :: * -> *) (f :: * -> *) a.
(Applicative f, Functor f, Num a) =>
f (f a) -> f a -> f (f a)
^^*^ V4 Float
vyyy)