GPipe-GLFW4-2.0.0: test/Graphics/GPipe/Context/GLFW/MultiPassSpec.hs
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wno-missing-signatures #-}
{-# OPTIONS_GHC -Wno-deferred-type-errors #-}
module Graphics.GPipe.Context.GLFW.MultiPassSpec (spec) where
import Test.Hspec (Spec, describe, it)
import Control.Lens ((^.))
import Control.Monad (unless)
import Control.Monad.IO.Class (liftIO)
import Data.Word (Word32)
import Graphics.GPipe
import qualified Graphics.GPipe.Context.GLFW as GLFW
import qualified Test.Common as C
spec :: Spec
spec = do
describe "Multi-pass render" $ do
it "should render a quad with another rendering on it" $ do
C.runContext GLFW.defaultHandleConfig $ do
win <- newWindow (WindowFormatColor RGB8) (GLFW.defaultWindowConfig "Checkers")
vertexBuffer :: Buffer os (B2 Float) <- newBuffer 4
writeBuffer vertexBuffer 0 [V2 0 0, V2 1 0, V2 0 1, V2 1 1]
tex <- newTexture2D R8 (V2 8 8) 1
let whiteBlack = cycle [minBound,maxBound] :: [Word32]
blackWhite = tail whiteBlack
writeTexture2D tex 0 0 (V2 8 8) (cycle (take 8 whiteBlack ++ take 8 blackWhite))
colorTex <- newTexture2D RG8 (V2 256 256) 1
depthTex <- newTexture2D Depth16 (V2 256 256) 1
shader1 <- compileShader $ do
texMappedFragmentStream <- getProjectedFragments 256 (V3 0.5 (-0.8) (-0.8)) (V3 0.5 0.5 0) (V3 0 1 0) textureMappedPrimitives
solidFragmentStream <- getProjectedFragments 256 (V3 (-0.6) (-0.6) 0.8) (V3 0.25 0.25 0) (V3 0 1 0) solidPrimitives
let filterMode = SamplerFilter Nearest Nearest Nearest Nothing
edge = (pure ClampToEdge, 0)
samp <- newSampler2D (const (tex, filterMode, edge))
let sampleTexture = sample2D samp SampleAuto Nothing Nothing
texMappedFragmentStream2 = filterFragments ((>* 0.5) . sampleTexture) texMappedFragmentStream
texMappedFragmentStream3 = fmap (const (V2 1 0)) texMappedFragmentStream2
solidFragmentStream2 = fmap (const (V2 0 1)) solidFragmentStream
fragmentStream = solidFragmentStream2 `mappend` texMappedFragmentStream3
fragmentStream2 = withRasterizedInfo (\a r -> (a, rasterizedFragCoord r ^. _z)) fragmentStream
drawDepth (\s -> (NoBlending, depthImage s, DepthOption Less True)) fragmentStream2 $ \ a -> do
drawColor (\ s -> (colorImage s, pure True, False)) a
shader2 <- compileShader $ do
fragmentStream <- getProjectedFragments 800 (V3 1 2 2) (V3 0.5 0.5 0) (V3 0 1 0) id
let filterMode = SamplerFilter Linear Linear Nearest Nothing
edge = (pure ClampToEdge, 0)
samp <- newSampler2D (const (colorTex, filterMode, edge))
let sampleTexture = sample2D samp SampleAuto Nothing Nothing
fragmentStream2 = fmap ((\(V2 r g) -> V3 r 0 g) . sampleTexture) fragmentStream
drawWindowColor (const (win, ContextColorOption NoBlending (pure True))) fragmentStream2
Just start <- liftIO GLFW.getTime
renderLoop start win [
do
vertexArray <- newVertexArray vertexBuffer
let singleTriangle = takeVertices 3 vertexArray
cImage <- getTexture2DImage colorTex 0
dImage <- getTexture2DImage depthTex 0
clearImageColor cImage 0
clearImageDepth dImage 1
shader1 $ ShaderEnvironment
(toPrimitiveArray TriangleStrip vertexArray)
(toPrimitiveArray TriangleList singleTriangle)
cImage
dImage
,
do
clearWindowColor win 0.5
vertexArray <- newVertexArray vertexBuffer
shader2 (toPrimitiveArray TriangleStrip vertexArray)
]
getProjectedFragments size eye center up sf = do
primitiveStream <- toPrimitiveStream sf
let primitiveStream2 = fmap (\pos2d -> (make3d eye center up pos2d, pos2d)) primitiveStream
rasterize (const (FrontAndBack, PolygonFill, ViewPort (V2 0 0) (V2 size size), DepthRange 0 1)) primitiveStream2
make3d :: Floating a => V3 a -> V3 a -> V3 a -> V2 a -> V4 a
make3d eye center up (V2 x y) = projMat !*! viewMat !* V4 x y 0 1
where
viewMat = lookAt eye center up
projMat = perspective (pi/3) 1 1 100
renderLoop :: Double -> Window os c ds -> [Render os ()] -> ContextT GLFW.Handle os IO ()
renderLoop start win renderings = do
mapM_ render renderings
swapWindowBuffers win
closeRequested <- GLFW.windowShouldClose win
Just now <- liftIO GLFW.getTime
unless (now - start > 1 || closeRequested == Just True) $
renderLoop start win renderings
data ShaderEnvironment = ShaderEnvironment
{
textureMappedPrimitives, solidPrimitives :: PrimitiveArray Triangles (B2 Float),
colorImage :: Image (Format RGFloat),
depthImage :: Image (Format Depth)
}