GLUT-2.7.0.13: examples/Misc/ARBOcclude.hs
{-
ARBOcclude.hs (adapted from arbocclude.c which is (c) Brian Paul)
Copyright (c) Sven Panne 2002-2018 <svenpanne@gmail.com>
This file is part of HOpenGL and distributed under a BSD-style license
See the file libraries/GLUT/LICENSE
-}
import Control.Monad ( unless, when )
import Data.IORef ( IORef, newIORef )
import System.Exit ( exitWith, ExitCode(ExitSuccess), exitFailure )
import Graphics.UI.GLUT
data State = State {
anim :: IORef Bool,
xPos :: IORef GLfloat,
sign :: IORef GLfloat,
lastTime :: IORef Int }
makeState :: IO State
makeState = do
a <- newIORef True
x <- newIORef 0
s <- newIORef 1
l <- newIORef =<< get elapsedTime
return $ State { anim = a, xPos = x, sign = s, lastTime = l }
petrol, orange, white :: Color3 GLfloat
petrol = Color3 0.0 0.6 0.8
orange = Color3 0.8 0.5 0.0
white = Color3 1.0 1.0 1.0
printString :: Vertex2 GLfloat -> String -> IO ()
printString pos s = do
color white
rasterPos pos
renderString Fixed8By13 s
idle :: State -> IdleCallback
idle state = do
time <- get elapsedTime
l <- get (lastTime state)
let timeDiff = fromIntegral (time - l)
when (timeDiff >= 20) $ do -- 50Hz update
lastTime state $= time
s <- get (sign state)
step state (timeDiff / 1000 * s)
x <- get (xPos state)
when (x > 2.5) $ do
xPos state $= 2.5
sign state $= (-1)
when (x < -2.5) $ do
xPos state $= (-2.5)
sign state $= 1
display :: QueryObject -> State -> DisplayCallback
display occQuery state = do
clear [ ColorBuffer, DepthBuffer ]
matrixMode $= Projection
loadIdentity
frustum (-1) 1 (-1) 1 5 25
matrixMode $= Modelview 0
loadIdentity
translate (Vector3 0 0 (-15 :: GLfloat))
drawOccludingPolygons
-- draw the test polygon with occlusion testing
passed <- preservingMatrix $ do
x <- get (xPos state)
translate (Vector3 x 0 (-0.5))
scale 0.3 0.3 (1.0 :: GLfloat)
rotate (-90 * x) (Vector3 0 0 1)
withQuery SamplesPassed occQuery $ do
colorMask $= Color4 Disabled Disabled Disabled Disabled
depthMask $= Disabled
drawRect
p <- waitForResult occQuery
-- turn off occlusion testing
colorMask $= Color4 Enabled Enabled Enabled Enabled
depthMask $= Enabled
-- draw the orange rect, so we can see what's going on
color orange
drawRect
return p
-- Print result message
matrixMode $= Projection
loadIdentity
ortho (-1) 1 (-1) 1 (-1) 1
matrixMode $= Modelview 0
loadIdentity
printString (Vertex2 (-0.50) (-0.7))
(" " ++ flushRight 4 passed ++ " Fragments Visible")
when (passed == 0) $
printString (Vertex2 (-0.25) (-0.8)) "Fully Occluded"
swapBuffers
drawOccludingPolygons :: IO ()
drawOccludingPolygons = do
color petrol
drawQuads [
Vertex2 (-1.6) (-1.5),
Vertex2 (-0.4) (-1.5),
Vertex2 (-0.4) 1.5 ,
Vertex2 (-1.6) 1.5 ,
Vertex2 0.4 (-1.5),
Vertex2 1.6 (-1.5),
Vertex2 1.6 1.5 ,
Vertex2 0.4 1.5 ]
drawRect :: IO ()
drawRect = do
drawQuads [
Vertex2 (-1) (-1),
Vertex2 1 (-1),
Vertex2 1 1 ,
Vertex2 (-1) 1 ]
drawQuads :: [Vertex2 GLfloat] -> IO ()
drawQuads = renderPrimitive Quads . mapM_ vertex
waitForResult :: QueryObject -> IO GLuint
waitForResult occQuery = do
let loop = do -- do useful work here, if any
ready <- get (queryResultAvailable occQuery)
unless ready loop
loop
get (queryResult occQuery)
flushRight :: Show a => Int -> a -> String
flushRight width x = replicate (width - length s) ' ' ++ s
where s = show x
keyboard :: State -> KeyboardMouseCallback
keyboard _ (Char '\27') Down _ _ = exitWith ExitSuccess
keyboard state (Char ' ') Down _ _ = do anim state $~ not
setIdleCallback state
keyboard state (SpecialKey KeyLeft) Down _ _ = step state (-0.1)
keyboard state (SpecialKey KeyRight) Down _ _ = step state 0.1
keyboard _ _ _ _ _ = return ()
setIdleCallback :: State -> IO ()
setIdleCallback state = do
a <- get (anim state)
idleCallback $= if a then Just (idle state) else Nothing
step :: State -> GLfloat -> IO ()
step state s = do
xPos state $~ (+ s)
postRedisplay Nothing
myInit :: IO ()
myInit = do
exts <- get glExtensions
unless ("GL_ARB_occlusion_query" `elem` exts) $ do
putStrLn "Sorry, this demo requires the GL_ARB_occlusion_query extension."
exitFailure
bits <- get (queryCounterBits SamplesPassed)
unless (bits > 0) $ do
putStrLn "Hmmm, GL_QUERY_COUNTER_BITS_ARB is zero!"
exitFailure
depthFunc $= Just Less
main :: IO ()
main = do
(progName, _args) <- getArgsAndInitialize
initialWindowPosition $= Position 0 0
initialWindowSize $= Size 400 400
initialDisplayMode $= [ RGBMode, DoubleBuffered, WithDepthBuffer ]
_ <- createWindow progName
state <- makeState
reshapeCallback $= Just (\size -> viewport $= (Position 0 0, size))
keyboardMouseCallback $= Just (keyboard state)
setIdleCallback state
occQuery <- genObjectName
displayCallback $= display occQuery state
myInit
mainLoop