<commit_before>{-# LANGUAGE RecordWildCards, GeneralizedNewtypeDeriving, DeriveDataTypeable #-}
module Yage.Rendering (
      module GLReExports
    , runYageRenderer
    , renderScene

    ) where

import Debug.Trace

import qualified   Data.Map                        as Map
import             Data.List                       (groupBy)
import             Foreign.Storable                (sizeOf)
import             Control.Concurrent              (threadDelay)
import             System.Mem                      (performGC)

import             Data.Typeable
import             Control.Applicative
import             Control.Monad.Reader
import             Control.Monad.State

import             Graphics.GLUtil                 hiding (makeVAO)
import qualified   Graphics.Rendering.OpenGL       as GL
import             Graphics.Rendering.OpenGL.GL    (($=))
import             Graphics.Rendering.OpenGL.GL    as GLReExports (Color4(..))
---------------------------------------------------------------------------------------------------
import             Linear                          (V3(..), zero)
import             Linear.Quaternion               (Quaternion)
---------------------------------------------------------------------------------------------------
import             Yage.Import
import             Yage.Core.Raw.FFI
import 			   Yage.Rendering.Types
import             Yage.Rendering.WorldState
import             Yage.Rendering.Shader           ((.=))
import qualified   Yage.Rendering.Shader           as Shader
import             Yage.Rendering.Utils
import 			   Yage.Resources
{-=================================================================================================-}


renderScene :: RenderScene -> YageRenderer ()
renderScene scene = renderFrame scene >> afterFrame



afterFrame :: YageRenderer ()
afterFrame = io $ do
    -- this should not be part of the rendering, indeed
    performGC
    --threadDelay (16*1000) -- 60fps
    return ()


renderFrame :: RenderScene -> YageRenderer ()
renderFrame scene = do
    beforeRender
    doRender scene
    afterRender


doRender :: RenderScene -> YageRenderer ()
doRender scene@RenderScene{..} = do
    let batches = createShaderBatches scene entities
    mapM_ renderBatch batches --- insert batch rendering here


renderWithData :: RenderScene -> SomeRenderable -> YageRenderer ()
renderWithData scene r = requestRenderData r >>= \res -> render scene res r


renderBatch :: RenderBatch SomeRenderable -> YageRenderer ()
renderBatch b@RenderBatch{..} = preBatch >> mapM_ perItem batch


createShaderBatches :: RenderScene -> [SomeRenderable] -> [RenderBatch SomeRenderable]
createShaderBatches scene rs = 
    let shaderGroups = groupBy sameShader rs
    in map mkShaderBatch shaderGroups
    where
        sameShader :: SomeRenderable -> SomeRenderable -> Bool
        sameShader a b = shader a == shader b
        mkShaderBatch :: [SomeRenderable] -> RenderBatch SomeRenderable
        mkShaderBatch rs =
            let batchShader = shader . head $ rs
            in RenderBatch
                { preBatch = do
                    shader <- requestShader batchShader 
                    io $ GL.currentProgram $= Just (program shader)
                    setSceneGlobals scene shader
                , perItem = renderWithData scene
                , batch = rs
                }



beforeRender :: YageRenderer ()
beforeRender = do
    setupFrame
    prepareResources


setupFrame :: YageRenderer ()
setupFrame = withWindow $ \win -> do
    clearC <- asks $ clearColor . renderConfig
    io $ do
        beginDraw $ win

        GL.clearColor $= fmap realToFrac clearC
        GL.depthFunc $= Just GL.Less -- to init
        GL.depthMask $= GL.Enabled      -- to init
        
        GL.clear [GL.ColorBuffer, GL.DepthBuffer]


        w <- width win
        h <- height win
        r <- return . floor =<< pixelRatio win
        GL.viewport $= ((GL.Position 0 0), (GL.Size (fromIntegral (r * w)) (fromIntegral (r * h))) )


-- | Unloads unneeded render-resources and loads needed resources
prepareResources :: YageRenderer ()
prepareResources = return ()

---------------------------------------------------------------------------------------------------


afterRender :: YageRenderer ()
afterRender = withWindow $ \win -> io . endDraw $ win

---------------------------------------------------------------------------------------------------

render :: RenderScene -> RenderData -> SomeRenderable -> YageRenderer ()
render scene rd@RenderData{..} r = do
    shadeItem shaderProgram scene r
    io $ withVAO vao $ drawIndexedTris . fromIntegral $ triangleCount


setSceneGlobals :: RenderScene -> YageShaderProgram -> YageRenderer ()
setSceneGlobals scene sProg = shade sProg $ do
    Shader.sGlobalTime       .= sceneTime scene
    Shader.sProjectionMatrix .= projectionMatrix scene
    Shader.sViewMatrix       .= viewMatrix scene


shadeItem :: YageShaderProgram -> RenderScene -> SomeRenderable -> YageRenderer ()
shadeItem sProg scene r = shade sProg $ do
    Shader.sModelMatrix      .= (modelMatrix $! r)
---------------------------------------------------------------------------------------------------


withWindow :: (YGLWindow -> YageRenderer a) -> YageRenderer a
withWindow f = asks window >>= f


withApplication :: (YApplication -> YageRenderer a) -> YageRenderer a
withApplication f = asks application >>= f


---------------------------------------------------------------------------------------------------<commit_msg>shader-batch rendering<commit_after>{-# LANGUAGE RecordWildCards, GeneralizedNewtypeDeriving, DeriveDataTypeable #-}
module Yage.Rendering (
      module GLReExports
    , runYageRenderer
    , renderScene

    ) where

import Debug.Trace

import qualified   Data.Map                        as Map
import             Data.List                       (groupBy)
import             Foreign.Storable                (sizeOf)
import             Control.Concurrent              (threadDelay)
import             System.Mem                      (performGC)

import             Data.Typeable
import             Control.Applicative
import             Control.Monad.Reader
import             Control.Monad.State

import             Graphics.GLUtil                 hiding (makeVAO)
import qualified   Graphics.Rendering.OpenGL       as GL
import             Graphics.Rendering.OpenGL.GL    (($=))
import             Graphics.Rendering.OpenGL.GL    as GLReExports (Color4(..))
---------------------------------------------------------------------------------------------------
import             Linear                          (V3(..), zero)
import             Linear.Quaternion               (Quaternion)
---------------------------------------------------------------------------------------------------
import             Yage.Import
import             Yage.Core.Raw.FFI
import 			   Yage.Rendering.Types
import             Yage.Rendering.WorldState
import             Yage.Rendering.Shader           ((.=))
import qualified   Yage.Rendering.Shader           as Shader
import             Yage.Rendering.Utils
import 			   Yage.Resources
{-=================================================================================================-}


renderScene :: RenderScene -> YageRenderer ()
renderScene scene = renderFrame scene >> afterFrame



afterFrame :: YageRenderer ()
afterFrame = io $ do
    -- this should not be part of the rendering, indeed
    performGC
    --threadDelay (16*1000) -- 60fps
    return ()


renderFrame :: RenderScene -> YageRenderer ()
renderFrame scene = do
    beforeRender
    doRender scene
    afterRender


doRender :: RenderScene -> YageRenderer ()
doRender scene@RenderScene{..} = do
    let batches = createShaderBatches scene entities
    mapM_ renderBatch batches --- insert batch rendering here


renderWithData :: RenderScene -> SomeRenderable -> YageRenderer ()
renderWithData scene r = requestRenderData r >>= \res -> render scene res r


renderBatch :: RenderBatch SomeRenderable -> YageRenderer ()
renderBatch b@RenderBatch{..} = preBatch >> mapM_ perItem batch


createShaderBatches :: RenderScene -> [SomeRenderable] -> [RenderBatch SomeRenderable]
createShaderBatches scene rs = 
    let shaderGroups = groupBy sameShader rs
    in map mkShaderBatch shaderGroups
    where
        sameShader :: SomeRenderable -> SomeRenderable -> Bool
        sameShader a b = shader a == shader b
        mkShaderBatch :: [SomeRenderable] -> RenderBatch SomeRenderable
        mkShaderBatch rs =
            let batchShader = shader . head $ rs
            in RenderBatch
                { preBatch = do
                    shader <- requestShader batchShader 
                    io $! GL.currentProgram $= Just (program shader)
                    setSceneGlobals scene shader
                , perItem = renderWithData scene
                , batch = rs
                }



beforeRender :: YageRenderer ()
beforeRender = do
    setupFrame
    prepareResources


setupFrame :: YageRenderer ()
setupFrame = withWindow $ \win -> do
    clearC <- asks $ clearColor . renderConfig
    io $! do
        beginDraw $ win

        GL.clearColor $= fmap realToFrac clearC
        GL.depthFunc $= Just GL.Less -- to init
        GL.depthMask $= GL.Enabled      -- to init
        
        GL.clear [GL.ColorBuffer, GL.DepthBuffer]


        w <- width win
        h <- height win
        r <- return . floor =<< pixelRatio win
        GL.viewport $= ((GL.Position 0 0), (GL.Size (fromIntegral (r * w)) (fromIntegral (r * h))) )


-- | Unloads unneeded render-resources and loads needed resources
prepareResources :: YageRenderer ()
prepareResources = return ()

---------------------------------------------------------------------------------------------------


afterRender :: YageRenderer ()
afterRender = withWindow $ \win -> io . endDraw $ win

---------------------------------------------------------------------------------------------------

render :: RenderScene -> RenderData -> SomeRenderable -> YageRenderer ()
render scene rd@RenderData{..} r = do
    shadeItem shaderProgram scene r
    io $! withVAO vao $! drawIndexedTris . fromIntegral $ triangleCount


setSceneGlobals :: RenderScene -> YageShaderProgram -> YageRenderer ()
setSceneGlobals scene sProg = shade sProg $ do
    Shader.sGlobalTime       .= sceneTime scene
    Shader.sProjectionMatrix .= projectionMatrix scene
    Shader.sViewMatrix       .= viewMatrix scene


shadeItem :: YageShaderProgram -> RenderScene -> SomeRenderable -> YageRenderer ()
shadeItem sProg scene r = shade sProg $! do
    Shader.sModelMatrix      .= (modelMatrix $! r)
---------------------------------------------------------------------------------------------------


withWindow :: (YGLWindow -> YageRenderer a) -> YageRenderer a
withWindow f = asks window >>= f


withApplication :: (YApplication -> YageRenderer a) -> YageRenderer a
withApplication f = asks application >>= f


---------------------------------------------------------------------------------------------------
{'fraction_non_alphanumeric': 0.19671539433315285, 'fraction_numerical': 0.002165674066053059, 'mean_word_length': 1.6406957350488445, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6781443', 'n_tokens_mistral': 2691, 'n_tokens_neox': 2573, 'n_words': 747}