module Render.ShadowMap.Pipeline ( Pipeline , allocate , Settings(..) , defaults ) where import RIO import Control.Monad.Trans.Resource (ResourceT) import Data.Tagged (Tagged(..)) import Geomancy (Transform) import Vulkan.Core10 qualified as Vk import Vulkan.Zero (zero) import Engine.Vulkan.Pipeline qualified as Pipeline import Engine.Vulkan.Types (HasVulkan, HasRenderPass(..), DsBindings) import Render.Code (compileVert, glsl) import Render.Code.Lit (structLight) import Render.DescSets.Set0 (vertexPos, instanceTransform) import Render.DescSets.Sun (Sun, pattern MAX_VIEWS) type Config = Pipeline.Config '[Sun] () Transform type Pipeline = Pipeline.Pipeline '[Sun] () Transform data Settings = Settings { cull :: Vk.CullModeFlagBits , depthBias :: Maybe (Float, Float) } defaults :: Settings defaults = Settings { cull = Vk.CULL_MODE_BACK_BIT , depthBias = Just (2.0, 2.5) } allocate :: ( HasVulkan env , HasRenderPass renderpass ) => Tagged Sun DsBindings -> renderpass -> Settings -> ResourceT (RIO env) Pipeline allocate tset0 rp settings = do (_, p) <- Pipeline.allocate Nothing Vk.SAMPLE_COUNT_1_BIT (config tset0 settings) rp pure p config :: Tagged Sun DsBindings -> Settings -> Config config (Tagged set0) Settings{..} = zero { Pipeline.cDescLayouts = Tagged @'[Sun] [set0] , Pipeline.cVertexCode = Just vertCode , Pipeline.cVertexInput = vertexInput , Pipeline.cDepthBias = depthBias , Pipeline.cCull = cull } where vertexInput = Pipeline.vertexInput [ vertexPos , instanceTransform ] vertCode :: ByteString vertCode = $(compileVert [glsl| #version 450 #extension GL_ARB_separate_shader_objects : enable #extension GL_EXT_multiview : enable ${structLight} layout(set=0, binding=0, std140) uniform Globals { Light lights[${MAX_VIEWS}]; }; layout(location = 0) in vec3 vPosition; layout(location = 1) in mat4 iModel; void main() { gl_Position = lights[gl_ViewIndex].viewProjection * iModel * vec4(vPosition, 1.0); } |])