packages feed

caramia-0.7.2.2: demos/query-objects/Main.hs

{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}

module Main ( main ) where

import Control.Monad.IO.Class
import Control.Monad.Trans.State.Strict
import Control.Monad.Trans.Class ( lift )
import Data.Bits
import Data.Text ( Text )
import qualified Data.Vector.Storable as V
import Foreign.C.String
import Foreign.Ptr
import Foreign.Storable
import Graphics.Caramia.Prelude hiding ( init )
import Graphics.Caramia
import Graphics.UI.SDL

main :: IO ()
main =
    withCString "query-objects" $ \cstr -> do
        _ <- glSetAttribute SDL_GL_CONTEXT_MAJOR_VERSION 3
        _ <- glSetAttribute SDL_GL_CONTEXT_MINOR_VERSION 3
        _ <- glSetAttribute SDL_GL_CONTEXT_PROFILE_MASK SDL_GL_CONTEXT_PROFILE_CORE
        _ <- glSetAttribute  SDL_GL_CONTEXT_FLAGS SDL_GL_CONTEXT_DEBUG_FLAG
        window <- createWindow cstr SDL_WINDOWPOS_UNDEFINED SDL_WINDOWPOS_UNDEFINED
                                    500 500
                                    (SDL_WINDOW_OPENGL .|.
                                     SDL_WINDOW_SHOWN)
        _ <- glCreateContext window
        giveContext $ do
            color_program <- newPipelineVF passThroughVertex2DShader
                                           coloredFragmentProgram
                                           mempty
            color_loc <- getUniformLocation "color" color_program
            offset_loc <- getUniformLocation "offset" color_program
            vao <- newVAO
            vao2 <- newVAO
            pos_vec <- newImmutableBufferFromVector $ V.fromList
                            [ -0.3, -0.3, 0.0
                            , 0.3, -0.3, 0.0
                            , -0.3, 0.3, 0.0
                            , 0.3, 0.3, 0.0 ]
            pos2_vec <- newImmutableBufferFromVector $ V.fromList
                            [ -0.2, -0.2, 0.1
                            , 0.2, -0.2, 0.1
                            , -0.2, 0.2, 0.1
                            , 0.2, 0.2, 0.1 ]
            sourceVertexData pos_vec
                             defaultSourcing {
                                 components = 3
                               , attributeIndex = 0
                               , sourceType = SFloat
                             }
                             vao
            sourceVertexData pos2_vec
                             defaultSourcing {
                                 components = 3
                               , attributeIndex = 0
                               , sourceType = SFloat
                             }
                             vao2

            flip evalStateT (False, -1.0 :: Float) $ forever $ do
                clear clearing { clearDepth = Just 1.0
                               , clearColor = Just $ rgba 0.1 0.1 0.1 1.0 }
                      screenFramebuffer

                samples <- newNumericQuery SamplesPassed
                any_samples <- newBooleanQuery AnySamplesPassed
                elapsed <- newNumericQuery TimeElapsed
                go_right <- fst <$> get

                runDraws defaultDrawParams { pipeline = color_program
                                        , fragmentPassTests =
                                            defaultFragmentPassTests {
                                                depthTest = Just Less } } $ do
                    x <- lift $ snd <$> get
                    setUniform (rgba 1 0 0 1) color_loc color_program
                    setUniform (x, 0.0 :: Float) offset_loc color_program
                    drawR drawCommand {
                        primitiveType = TriangleStrip
                      , primitivesVAO = vao
                      , numIndices = 4
                      , sourceData = Primitives { firstIndex = 0 } }
                    if go_right
                      then beginQuery samples
                      else beginQuery any_samples
                    beginQuery elapsed
                    setUniform (0 :: Float, 0 :: Float) offset_loc color_program
                    setUniform (rgba 0 1 1 1) color_loc color_program
                    drawR drawCommand {
                        primitiveType = TriangleStrip
                      , primitivesVAO = vao2
                      , numIndices = 4
                      , sourceData = Primitives { firstIndex = 0 } }
                    if go_right
                      then endQuery samples
                      else endQuery any_samples
                    endQuery elapsed

                elapsed_result <- getResults elapsed
                liftIO $ do
                    if go_right
                      then do
                          samples_result <- getResults samples
                          putStr $ "samples: " <> show samples_result <> " "
                      else do
                          any_samples_result <- getResults any_samples
                          putStr $ "any samples: " <> show any_samples_result <> " "
                    putStrLn $ "elapsed: " <> show elapsed_result

                modify (\(x, y) -> (x, if go_right then y+0.003 else y-0.003))
                y <- snd <$> get
                when (y > 1.0) $ modify (\(_, y) -> (False, y))
                when (y < -1.0) $ modify (\(_, y) -> (True, y))

                liftIO $ glSwapWindow window
                runPendingFinalizers

newImmutableBufferFromVector :: V.Vector Float -> IO Buffer
newImmutableBufferFromVector vec =
    V.unsafeWith vec $ \ptr -> do
        let byte_size = sizeOf (undefined :: Float) * V.length vec
        newBuffer defaultBufferCreation {
                 size = byte_size
               , initialData = Just $ castPtr ptr
               , accessHints = (Static, Draw)
               , accessFlags = NoAccess }

passThroughVertex2DShader :: Text
passThroughVertex2DShader =
    "#version 330\n" <>
    "uniform vec2 offset;\n" <>
    "layout (location=0) in vec2 pos;\n" <>
    "void main() {\n" <>
    "    gl_Position = vec4(pos+offset, 0, 1);\n" <>
    "}\n"

coloredFragmentProgram :: Text
coloredFragmentProgram =
    "#version 330\n" <>
    "uniform vec4 color;\n" <>
    "layout (location=0) out vec4 fcolor;\n" <>
    "void main() {\n" <>
    "    fcolor = color;\n" <>
    "}\n"