~alcinnz/Mondrian

7564554b3527f7e220c09c24cc9f8035d3f196b0 — Adrian Cochrane 9 months ago 350eab7
Commit border renderer, make them trapazoidal.
2 files changed, 79 insertions(+), 1 deletions(-)

M app/Main.hs
A lib/Graphics/Rendering/Rect/Border.hs
M app/Main.hs => app/Main.hs +1 -1
@@ 73,7 73,7 @@ main = do
        liftIO $ glViewport 0 0 (fromIntegral dw) (fromIntegral dh)

        let rect = Rect 0 0 (fromIntegral dw) (fromIntegral dh)
            rects = Rects (shrink1 rect 15) (shrink1 rect 10) (shrink1 rect 5) rect
            rects = Rects (shrink1 rect 150) (shrink1 rect 100) (shrink1 rect 50) rect

        render style' rects $ orthoProjection sz


A lib/Graphics/Rendering/Rect/Border.hs => lib/Graphics/Rendering/Rect/Border.hs +78 -0
@@ 0,0 1,78 @@
module Graphics.Rendering.Rect.Border(renderBorder, Border(..), BorderStyle(..),
        topColour, rightColour, bottomColour, leftColour) where

import Graphics.Rendering.Rect.CSS.Border
import Graphics.Rendering.Rect.Types
import qualified Data.ByteString.Char8 as B8
import Control.Monad.IO.Class (MonadIO(..))
import Linear (M44)

borderFragmentShader :: B8.ByteString
borderFragmentShader = B8.pack $ unlines [
    "#version 330 core",
    "uniform float widths[4];",
    "uniform vec4 colours[4];",
    "uniform int styles[5];",
    "uniform vec2 boxSize;",
    "in vec2 coord;",
    "out vec4 fcolour;",
    "",
    "const int TOP = 0;",
    "const int RIGHT = 1;",
    "const int BOTTOM = 2;",
    "const int LEFT = 3;",
    "const int NONE = 4;",
    "",
    "const int NOBORDER = 0;",
    "const int SOLID = 1;",
    "const int DASHED = 2;",
    "const int DOTTED = 3;",
    "const int DOUBLE = 4;",
    "const int GROOVE = 5;",
    "const int RIDGE = 6;",
    "const int INSET = 7;",
    "const int OUTSET = 8;",
    "",
    "bool inTrap(float x, float y, float width, int height, int left, int right) {",
    "   float a = y/widths[height];",
    "   return a*widths[left] <= x && x <= width - widths[right]*a;",
    "}",
    "",
    "void main() {",
    "   int side = NONE;",
    "   if (coord.y < abs(widths[TOP]) &&",
    "           inTrap(coord.x, coord.y, boxSize.x, TOP, LEFT, RIGHT))",
    "       side = TOP;",
    "   else if (coord.x < abs(widths[LEFT]) &&",
    "           inTrap(coord.y, coord.x, boxSize.y, LEFT, TOP, BOTTOM))",
    "       side = LEFT;",
    "   else if (boxSize.x - coord.x < abs(widths[RIGHT]) &&",
    "           inTrap(coord.y, boxSize.x-coord.x, boxSize.y, RIGHT,TOP,BOTTOM))",
    "       side = RIGHT;",
    "   else if (boxSize.y - coord.y < abs(widths[BOTTOM])) side = BOTTOM;",
    "",
    "   vec2 pos = coord;",
    "   if (side == RIGHT || side == BOTTOM) pos = boxSize - coord;",
    "   if (side == TOP || side == BOTTOM) pos = pos.xy;",
    "",
    "   if (styles[side] == SOLID) fcolour = colours[side];",
    "   else fcolour = vec4(0.0);",
    "}"
  ]

renderBorder :: (MonadIO m, MonadIO n) => n (Border -> Rects -> M44 Float -> m ())
renderBorder = do
    inner <- renderRectWith borderFragmentShader [
            "widths[0]", "widths[1]", "widths[2]", "widths[3]",
            "colours[0]", "colours[1]", "colours[2]", "colours[3]",
            "styles[0]", "styles[1]", "styles[2]", "styles[3]", "styles[4]"]
    return $ \self rects -> let (b, p) = (borderBox rects, paddingBox rects)
        in inner [] [
            u $ top p - top b, u $ right b - right p,
            u $ bottom b - bottom p, u $ left p - left b,
            c $ topColour self, c $ rightColour self,
            c $ bottomColour self, c $ leftColour self,
            u $ fromEnum $ topStyle self, u $ fromEnum $ rightStyle self,
            u $ fromEnum $ bottomStyle self, u $ fromEnum $ leftStyle self,
            u (0 :: Int)
        ] borderBox borderBox rects