{-# LANGUAGE DataKinds, FlexibleContexts, RankNTypes, MultiParamTypeClasses, TypeFamilyDependencies, TypeFamilies, FlexibleInstances, UndecidableInstances, DeriveGeneric #-} {-| An example of shader variable: @ data Transform2 = Transform2 GMat3 deriving Generic @ An example of vertex shader: @ vertexShader :: VertexShader -- The types of the uniforms: '[Transform2, View2, Depth] -- The types of the attributes: '[Position2, UV] -- The types of the varying (outputs), excluding 'VertexShaderOutput'. '[UV] vertexShader -- Set of uniforms: (Transform2 trans :- View2 view :- Depth z :- N) -- Set of attributes: (Position2 (GVec2 x y) :- uv@(UV _) :- N) = -- Matrix and vector multiplication: let GVec3 x' y' _ = view .*. trans .* GVec3 x y 1 -- Set of outputs: in Vertex (GVec4 x' y' z 1) -- Vertex position. :- uv :- N @ -} module Graphics.Rendering.Ombra.Shader ( module Data.Boolean, module Data.VectorSpace, -- * Types Shader.Shader, Shader.VertexShader, Shader.FragmentShader, Shader.VertexShaderOutput(..), Shader.FragmentShaderOutput(..), Shader.ShaderVars, Shader.VOShaderVars, Shader.Uniform, Shader.Attribute, Shader.Generic, Shader.SVList(..), -- ** GPU types Shader.GBool, Shader.GFloat, Shader.GInt, Shader.GSampler2D, Shader.GSamplerCube, Shader.GVec2(..), Shader.GVec3(..), Shader.GVec4(..), Shader.GBVec2(..), Shader.GBVec3(..), Shader.GBVec4(..), Shader.GIVec2(..), Shader.GIVec3(..), Shader.GIVec4(..), Shader.GMat2(..), Shader.GMat3(..), Shader.GMat4(..), Shader.GArray, -- * GPU functions (Shader.!), Shader.loop, Shader.store, Shader.texture2D, Shader.texture2DBias, Shader.texture2DProj, Shader.texture2DProjBias, Shader.texture2DProj4, Shader.texture2DProjBias4, Shader.texture2DLod, Shader.texture2DProjLod, Shader.texture2DProjLod4, Shader.arrayLength, -- ** Various math functions Matrix(..), Ext(..), minG, maxG, modG, floorG, ceilingG, Shader.radians, Shader.degrees, Shader.exp2, Shader.log2, Shader.inversesqrt, Shader.fract, Shader.clamp, Shader.mix, Shader.step, Shader.smoothstep, Shader.distance, -- TODO: implement AffineSpace? -- Shader.length, Shader.faceforward, Shader.reflect, Shader.refract, Shader.matrixCompMult, -- *** Vector relational functions Shader.VecOrd, Shader.VecEq, Shader.lessThan, Shader.lessThanEqual, Shader.greaterThan, Shader.greaterThanEqual, Shader.equal, Shader.notEqual, Shader.GBoolVector, Shader.anyBV, Shader.allBV, Shader.notBV, -- ** Constructors Shader.ToGBool, Shader.bool, Shader.ToGInt, Shader.int, Shader.ToGFloat, Shader.float, -- TODO: better vector constructors {- Shader.Components, Shader.CompList, Shader.ToCompList, (Shader.#), Shader.ToGVec2, Shader.vec2, Shader.ToGVec3, Shader.vec3, Shader.ToGVec4, Shader.vec4, Shader.ToGBVec2, Shader.bvec2, Shader.ToGBVec3, Shader.bvec3, Shader.ToGBVec4, Shader.bvec4, Shader.ToGIVec2, Shader.ivec2, Shader.ToGIVec3, Shader.ivec3, Shader.ToGIVec4, Shader.ivec4, Shader.ToGMat2, Shader.mat2, Shader.ToGMat3, Shader.mat3, Shader.ToGMat4, Shader.mat4, -} -- ** Other Shader.position, Shader.fragData, Shader.fragCoord, Shader.fragFrontFacing, -- * Common shader variables UV(..) ) where import Data.Proxy import GHC.Generics (Generic) import Graphics.Rendering.Ombra.Shader.CPU import Graphics.Rendering.Ombra.Shader.Language ((#)) import qualified Graphics.Rendering.Ombra.Shader.Language as Shader import Graphics.Rendering.Ombra.Shader.ShaderVar hiding (Shader) import Graphics.Rendering.Ombra.Shader.Stages import Graphics.Rendering.Ombra.Vector import Data.Boolean import qualified Data.Boolean.Numbers as B import Data.Cross import Data.VectorSpace import Prelude data UV = UV Shader.GVec2 deriving Generic type instance BooleanOf Shader.GBool = Shader.GBool type instance BooleanOf Shader.GFloat = Shader.GBool type instance BooleanOf Shader.GInt = Shader.GBool type instance BooleanOf Shader.GSampler2D = Shader.GBool type instance BooleanOf Shader.GSamplerCube = Shader.GBool type instance BooleanOf Shader.GVec2 = Shader.GBool type instance BooleanOf Shader.GVec3 = Shader.GBool type instance BooleanOf Shader.GVec4 = Shader.GBool type instance BooleanOf Shader.GBVec2 = Shader.GBool type instance BooleanOf Shader.GBVec3 = Shader.GBool type instance BooleanOf Shader.GBVec4 = Shader.GBool type instance BooleanOf Shader.GIVec2 = Shader.GBool type instance BooleanOf Shader.GIVec3 = Shader.GBool type instance BooleanOf Shader.GIVec4 = Shader.GBool type instance BooleanOf Shader.GMat2 = Shader.GBool type instance BooleanOf Shader.GMat3 = Shader.GBool type instance BooleanOf Shader.GMat4 = Shader.GBool type instance BooleanOf (Shader.GArray n t) = Shader.GBool instance Boolean Shader.GBool where true = Shader.true false = Shader.false (&&*) = (Shader.&&) (||*) = (Shader.||) notB = Shader.not instance (Shader.ShaderType a, BooleanOf a ~ Shader.GBool) => IfB a where ifB = Shader.ifThenElse instance (Shader.ShaderType a, BooleanOf a ~ Shader.GBool) => EqB a where (==*) = (Shader.==) (/=*) = (Shader./=) instance (Shader.ShaderType a, BooleanOf a ~ Shader.GBool) => OrdB a where (<*) = (Shader.<) (<=*) = (Shader.<=) (>*) = (Shader.>) (>=*) = (Shader.>=) -- | Faster GPU 'max'/'B.maxB'. maxG :: Shader.GenTypeGFloat a b => a -> b -> a maxG = Shader.max -- | Faster GPU 'min'/'B.minB'. minG :: Shader.GenTypeGFloat a b => a -> b -> a minG = Shader.min instance Num Shader.GFloat where (+) = (Shader.+) (-) = (Shader.-) (*) = (Shader.*) abs = Shader.abs signum = Shader.sign fromInteger = Shader.fromInteger negate = Shader.negate instance Num Shader.GInt where (+) = (Shader.+) (-) = (Shader.-) (*) = (Shader.*) abs = Shader.absI signum = Shader.signI fromInteger = Shader.fromInteger negate = Shader.negateI instance B.NumB Shader.GFloat where type IntegerOf Shader.GFloat = Shader.GInt fromIntegerB = Shader.float instance B.NumB Shader.GInt where type IntegerOf Shader.GInt = Shader.GInt fromIntegerB = id instance AdditiveGroup Shader.GFloat where zeroV = Shader.zero (^+^) = (Shader.+) (^-^) = (Shader.-) negateV = Shader.negate -- | GPU 'mod' that can be used on floats and float vectors. modG :: Shader.GenType a => a -> a -> a modG = Shader.mod instance B.IntegralB Shader.GInt where quotRem a b = let q = a Shader./ b in (q, a - b * q) -- XXX: ??? divMod a b = let (q, r) = B.quotRem a b f = 1 - abs (signum r + signum b) in (q - f, r + b * f) toIntegerB = id instance Fractional Shader.GFloat where (/) = (Shader./) fromRational = Shader.fromRational instance Floating Shader.GFloat where pi = 3.1415926535897932384626433832795 exp = Shader.exp log = Shader.log sqrt = Shader.sqrt (**) = (Shader.^) sin = Shader.sin cos = Shader.cos tan = Shader.tan asin = Shader.asin acos = Shader.acos atan = Shader.atan -- TODO sinh = error "Hyperbolic functions are not implemented." cosh = error "Hyperbolic functions are not implemented." asinh = error "Hyperbolic functions are not implemented." acosh = error "Hyperbolic functions are not implemented." atanh = error "Hyperbolic functions are not implemented." floatToInt :: (B.NumB b, B.IntegerOf b ~ Shader.GInt) => Shader.GFloat -> b floatToInt = B.fromIntegerB . Shader.int instance B.RealFracB Shader.GFloat where properFraction x = let tx = signum x * floorG (abs x) in (floatToInt tx, x - tx) -- truncate x = floatToInt $ signum x * floorG (abs x) round x = floatToInt . floorG $ x + 0.5 ceiling = floatToInt . ceilingG floor = floatToInt . floorG floorG :: Shader.GenType a => a -> a floorG = Shader.floor ceilingG :: Shader.GenType a => a -> a ceilingG = Shader.ceil instance B.RealFloatB Shader.GFloat where isNaN = error "isNaN: not supported" isInfinite = error "isInfinite: not supported" isNegativeZero = error "isNegativeZero: not supported" isIEEE = error "isIEEE: not supported" atan2 = Shader.atan2 -- Vectors instance AdditiveGroup Shader.GVec2 where zeroV = Shader.zero (^+^) = (Shader.+) (^-^) = (Shader.-) negateV = Shader.negate instance VectorSpace Shader.GVec2 where type Scalar Shader.GVec2 = Shader.GFloat (*^) = (Shader.*) instance InnerSpace Shader.GVec2 where (<.>) = Shader.dot instance Ext Shader.GVec2 where type Extended Shader.GVec2 = Shader.GVec3 v ^| z = Shader.vec3 $ v # z v ^|^ Shader.GVec3 _ _ z = Shader.vec3 $ v # z extract = Shader.vec2 instance AdditiveGroup Shader.GVec3 where zeroV = Shader.zero (^+^) = (Shader.+) (^-^) = (Shader.-) negateV = Shader.negate instance VectorSpace Shader.GVec3 where type Scalar Shader.GVec3 = Shader.GFloat (*^) = (Shader.*) instance InnerSpace Shader.GVec3 where (<.>) = Shader.dot instance HasCross3 Shader.GVec3 where cross3 = Shader.cross instance Ext Shader.GVec3 where type Extended Shader.GVec3 = Shader.GVec4 v ^| w = Shader.vec4 $ v # w v ^|^ Shader.GVec4 _ _ _ w = Shader.vec4 $ v # w extract = Shader.vec3 instance AdditiveGroup Shader.GVec4 where zeroV = Shader.zero (^+^) = (Shader.+) (^-^) = (Shader.-) negateV = Shader.negate instance VectorSpace Shader.GVec4 where type Scalar Shader.GVec4 = Shader.GFloat (*^) = (Shader.*) instance InnerSpace Shader.GVec4 where (<.>) = Shader.dot -- Matrices instance AdditiveGroup Shader.GMat2 where zeroV = Shader.zero (^+^) = (Shader.+) (^-^) = (Shader.-) negateV = Shader.negateM instance VectorSpace Shader.GMat2 where type Scalar Shader.GMat2 = Shader.GFloat (*^) = (Shader.*) instance AdditiveGroup Shader.GMat3 where zeroV = Shader.zero (^+^) = (Shader.+) (^-^) = (Shader.-) negateV = Shader.negateM instance Ext Shader.GMat2 where type Extended Shader.GMat2 = Shader.GMat3 v ^| z = Shader.mat3 $ v # z # z # z # z # z Shader.GMat2 x y ^|^ Shader.GMat3 x' y' z' = Shader.GMat3 (x ^|^ x') (y ^|^ y') z' extract = Shader.mat2 instance Matrix Shader.GMat2 where type Row Shader.GMat2 = Shader.GVec2 idmtx = Shader.mat2 (1.0 :: Shader.GFloat) (.*.) = (Shader.*) (.*) = (Shader.*) (*.) = (Shader.*) transpose (Shader.GMat2 (Shader.GVec2 a b) (Shader.GVec2 c d)) = Shader.GMat2 (Shader.GVec2 a c) (Shader.GVec2 b d) instance VectorSpace Shader.GMat3 where type Scalar Shader.GMat3 = Shader.GFloat (*^) = (Shader.*) instance Ext Shader.GMat3 where type Extended Shader.GMat3 = Shader.GMat4 v ^| z = Shader.mat4 $ v # z # z # z # z # z # z # z Shader.GMat3 x y z ^|^ Shader.GMat4 x' y' z' w' = Shader.GMat4 (x ^|^ x') (y ^|^ y') (z ^|^ z') w' extract = Shader.mat3 instance Matrix Shader.GMat3 where type Row Shader.GMat3 = Shader.GVec3 idmtx = Shader.mat3 (1.0 :: Shader.GFloat) (.*.) = (Shader.*) (.*) = (Shader.*) (*.) = (Shader.*) transpose (Shader.GMat3 (Shader.GVec3 a b c) (Shader.GVec3 d e f) (Shader.GVec3 g h i)) = Shader.GMat3 (Shader.GVec3 a d g) (Shader.GVec3 b e h) (Shader.GVec3 c f i) instance AdditiveGroup Shader.GMat4 where zeroV = Shader.zero (^+^) = (Shader.+) (^-^) = (Shader.-) negateV = Shader.negateM instance VectorSpace Shader.GMat4 where type Scalar Shader.GMat4 = Shader.GFloat (*^) = (Shader.*) instance Matrix Shader.GMat4 where type Row Shader.GMat4 = Shader.GVec4 idmtx = Shader.mat4 (1.0 :: Shader.GFloat) (.*.) = (Shader.*) (.*) = (Shader.*) (*.) = (Shader.*) transpose (Shader.GMat4 (Shader.GVec4 a b c d) (Shader.GVec4 e f g h) (Shader.GVec4 i j k l) (Shader.GVec4 m n o p)) = Shader.GMat4 (Shader.GVec4 a e i m) (Shader.GVec4 b f j n) (Shader.GVec4 c g k o) (Shader.GVec4 d h l p)