~alcinnz/Mondrian

ref: e816039387124999a1dd08a4de554e0f47864c0a Mondrian/lib/Graphics/Rendering/Rect/Backgrounds.hs -rw-r--r-- 2.5 KiB
e8160393 — Adrian Cochrane Add support for colour stops, equally spaced. 1 year, 4 months ago
                                                                                
1adb7b35 Adrian Cochrane
eba0f9a2 Adrian Cochrane
6236cf8a Adrian Cochrane
eba0f9a2 Adrian Cochrane
4fb39760 Adrian Cochrane
7a7ce8ff Adrian Cochrane
4fb39760 Adrian Cochrane
94547420 Adrian Cochrane
7a7ce8ff Adrian Cochrane
6236cf8a Adrian Cochrane
94547420 Adrian Cochrane
eba0f9a2 Adrian Cochrane
10e61b66 Adrian Cochrane
eba0f9a2 Adrian Cochrane
049383f6 Adrian Cochrane
eba0f9a2 Adrian Cochrane
94547420 Adrian Cochrane
4fb39760 Adrian Cochrane
94547420 Adrian Cochrane
1adb7b35 Adrian Cochrane
e8160393 Adrian Cochrane
c4d7272d Adrian Cochrane
e8160393 Adrian Cochrane
c4d7272d Adrian Cochrane
1adb7b35 Adrian Cochrane
7a7ce8ff Adrian Cochrane
94547420 Adrian Cochrane
7a7ce8ff Adrian Cochrane
4fb39760 Adrian Cochrane
e8160393 Adrian Cochrane
94547420 Adrian Cochrane
4fb39760 Adrian Cochrane
1adb7b35 Adrian Cochrane
e8160393 Adrian Cochrane
1adb7b35 Adrian Cochrane
94547420 Adrian Cochrane
6236cf8a Adrian Cochrane
4fb39760 Adrian Cochrane
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
module Graphics.Rendering.Rect.Backgrounds(Backgrounds(..), Pattern(..),
    Resize(..), Length(..), resolveSize, renderBackgrounds) where

import Graphics.Rendering.Rect.CSS.Backgrounds
import Graphics.Rendering.Rect.Types
import Graphics.Rendering.Rect.Image (Texture(texSize))
import qualified Data.ByteString.Char8 as B8
import Linear (M44, V2(..))

import Control.Monad.IO.Class (MonadIO(..))
import Data.Maybe (fromMaybe, listToMaybe)
import Control.Monad (forM)

baseFragmentShader = B8.pack $ unlines [
    "#version 330 core",
    "out vec4 fcolour;",
    "uniform vec4 colour;",
    "void main() { fcolour = colour; }"
  ]

imageFragmentShader = B8.pack $ unlines [
    "#version 330 core",
    "in vec2 coord;",
    "out vec4 fcolour;",
    "uniform sampler2D image;",
    "uniform vec2 size;",
    "void main() { fcolour = texture(image, coord/size); }"
  ]

linearFragmentShader = B8.pack $ unlines [
    "#version 330 core",
    "in vec2 coord;",
    "out vec4 fcolour;",
    "uniform vec2 size;",
    "uniform vec4 stops[10];",
    "uniform int nStops;",
    "uniform float angle;",
    "void main() {",
    "   vec2 pos = coord/size;", -- Range 0..1
    "   pos -= 0.5; pos *= 2;", -- Range -1..1
    "   float a = pos.x*sin(angle) + pos.y*-cos(angle);", -- Range -1..1
    "   a /= 2; a += 0.5;", -- Range 0..1
    "   a *= float(min(nStops, 10) - 1);", -- Range 0..(nStops-1)
    "   fcolour = mix(stops[int(floor(a))], stops[int(ceil(a))], fract(a));",
    "}"
  ]

renderBackgrounds :: (MonadIO m, MonadIO n) =>
    n (Backgrounds Texture -> Rects -> M44 Float -> m ())
renderBackgrounds = do
    base <- renderRectWith baseFragmentShader ["colour"]
    layer <- renderRectWith imageFragmentShader ["size"]
    linear <- renderRectWith linearFragmentShader ["size","stops","nStops","angle"]
    return $ \self a b -> do
        base [] [c $ background self] (headDef borderBox $ clip self) a b
        let layers = image self `zip` (clip self ++ repeat borderBox)
                `zip` (bgSize self ++ repeat (Size Auto Auto))
        forM layers $ \((pat0, clip0), size0) -> case pat0 of
            None -> return ()
            Img img0 -> layer [img0] [
                    u $ v2 $ resolveSize (size $ clip0 a) (texSize img0) size0
                ] clip0 a b
            Linear angle stops -> linear [] [
                    u $ v2 $ size $ clip0 a, cs 10 stops, u $ length stops, u angle
                ] clip0 a b
        return ()

headDef def = fromMaybe def . listToMaybe
v2 = uncurry V2